Home | History | Annotate | Line # | Download | only in mainbus
fd.c revision 1.17
      1  1.17     lukem /*	$NetBSD: fd.c,v 1.17 2003/07/14 22:48:25 lukem Exp $	*/
      2   1.1   reinoud 
      3   1.1   reinoud /*-
      4   1.1   reinoud  * Copyright (c) 1998 The NetBSD Foundation, Inc.
      5   1.1   reinoud  * All rights reserved.
      6   1.1   reinoud  *
      7   1.1   reinoud  * This code is derived from software contributed to The NetBSD Foundation
      8   1.1   reinoud  * by Charles M. Hannum.
      9   1.1   reinoud  *
     10   1.1   reinoud  * Redistribution and use in source and binary forms, with or without
     11   1.1   reinoud  * modification, are permitted provided that the following conditions
     12   1.1   reinoud  * are met:
     13   1.1   reinoud  * 1. Redistributions of source code must retain the above copyright
     14   1.1   reinoud  *    notice, this list of conditions and the following disclaimer.
     15   1.1   reinoud  * 2. Redistributions in binary form must reproduce the above copyright
     16   1.1   reinoud  *    notice, this list of conditions and the following disclaimer in the
     17   1.1   reinoud  *    documentation and/or other materials provided with the distribution.
     18   1.1   reinoud  * 3. All advertising materials mentioning features or use of this software
     19   1.1   reinoud  *    must display the following acknowledgement:
     20   1.1   reinoud  *        This product includes software developed by the NetBSD
     21   1.1   reinoud  *        Foundation, Inc. and its contributors.
     22   1.1   reinoud  * 4. Neither the name of The NetBSD Foundation nor the names of its
     23   1.1   reinoud  *    contributors may be used to endorse or promote products derived
     24   1.1   reinoud  *    from this software without specific prior written permission.
     25   1.1   reinoud  *
     26   1.1   reinoud  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     27   1.1   reinoud  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     28   1.1   reinoud  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     29   1.1   reinoud  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     30   1.1   reinoud  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     31   1.1   reinoud  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     32   1.1   reinoud  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     33   1.1   reinoud  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     34   1.1   reinoud  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     35   1.1   reinoud  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     36   1.1   reinoud  * POSSIBILITY OF SUCH DAMAGE.
     37   1.1   reinoud  */
     38   1.1   reinoud 
     39   1.1   reinoud /*-
     40   1.1   reinoud  * Copyright (c) 1990 The Regents of the University of California.
     41   1.1   reinoud  * All rights reserved.
     42   1.1   reinoud  *
     43   1.1   reinoud  * This code is derived from software contributed to Berkeley by
     44   1.1   reinoud  * Don Ahn.
     45   1.1   reinoud  *
     46   1.1   reinoud  * Redistribution and use in source and binary forms, with or without
     47   1.1   reinoud  * modification, are permitted provided that the following conditions
     48   1.1   reinoud  * are met:
     49   1.1   reinoud  * 1. Redistributions of source code must retain the above copyright
     50   1.1   reinoud  *    notice, this list of conditions and the following disclaimer.
     51   1.1   reinoud  * 2. Redistributions in binary form must reproduce the above copyright
     52   1.1   reinoud  *    notice, this list of conditions and the following disclaimer in the
     53   1.1   reinoud  *    documentation and/or other materials provided with the distribution.
     54   1.1   reinoud  * 3. All advertising materials mentioning features or use of this software
     55   1.1   reinoud  *    must display the following acknowledgement:
     56   1.1   reinoud  *	This product includes software developed by the University of
     57   1.1   reinoud  *	California, Berkeley and its contributors.
     58   1.1   reinoud  * 4. Neither the name of the University nor the names of its contributors
     59   1.1   reinoud  *    may be used to endorse or promote products derived from this software
     60   1.1   reinoud  *    without specific prior written permission.
     61   1.1   reinoud  *
     62   1.1   reinoud  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     63   1.1   reinoud  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     64   1.1   reinoud  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     65   1.1   reinoud  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     66   1.1   reinoud  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     67   1.1   reinoud  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     68   1.1   reinoud  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     69   1.1   reinoud  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     70   1.1   reinoud  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     71   1.1   reinoud  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     72   1.1   reinoud  * SUCH DAMAGE.
     73   1.1   reinoud  *
     74   1.1   reinoud  *	@(#)fd.c	7.4 (Berkeley) 5/25/91
     75   1.1   reinoud  *	from: fd.c,v 1.104 1997/01/09 04:30:08 mycroft Exp
     76   1.1   reinoud  */
     77   1.1   reinoud 
     78   1.1   reinoud /*
     79   1.1   reinoud  * Floppy formatting facilities merged from FreeBSD fd.c driver:
     80   1.1   reinoud  *	Id: fd.c,v 1.53 1995/03/12 22:40:56 joerg Exp
     81   1.1   reinoud  * which carries the same copyright/redistribution notice as shown above with
     82   1.1   reinoud  * the addition of the following statement before the "Redistribution and
     83   1.1   reinoud  * use ..." clause:
     84   1.1   reinoud  *
     85   1.1   reinoud  * Copyright (c) 1993, 1994 by
     86   1.1   reinoud  *  jc (at) irbs.UUCP (John Capo)
     87   1.1   reinoud  *  vak (at) zebub.msk.su (Serge Vakulenko)
     88   1.1   reinoud  *  ache (at) astral.msk.su (Andrew A. Chernov)
     89   1.1   reinoud  *
     90   1.1   reinoud  * Copyright (c) 1993, 1994, 1995 by
     91   1.1   reinoud  *  joerg_wunsch (at) uriah.sax.de (Joerg Wunsch)
     92   1.1   reinoud  *  dufault (at) hda.com (Peter Dufault)
     93   1.1   reinoud  */
     94  1.17     lukem 
     95  1.17     lukem #include <sys/cdefs.h>
     96  1.17     lukem __KERNEL_RCSID(0, "$NetBSD: fd.c,v 1.17 2003/07/14 22:48:25 lukem Exp $");
     97   1.1   reinoud 
     98   1.1   reinoud #include "opt_ddb.h"
     99   1.1   reinoud 
    100   1.1   reinoud #include <sys/param.h>
    101   1.1   reinoud #include <sys/systm.h>
    102   1.1   reinoud #include <sys/callout.h>
    103   1.1   reinoud #include <sys/kernel.h>
    104   1.1   reinoud #include <sys/file.h>
    105   1.1   reinoud #include <sys/ioctl.h>
    106   1.1   reinoud #include <sys/device.h>
    107   1.1   reinoud #include <sys/disklabel.h>
    108   1.1   reinoud #include <sys/disk.h>
    109   1.1   reinoud #include <sys/buf.h>
    110   1.1   reinoud #include <sys/malloc.h>
    111   1.1   reinoud #include <sys/uio.h>
    112   1.1   reinoud #include <sys/syslog.h>
    113   1.1   reinoud #include <sys/queue.h>
    114   1.1   reinoud #include <sys/proc.h>
    115   1.1   reinoud #include <sys/fdio.h>
    116   1.6   gehenna #include <sys/conf.h>
    117   1.1   reinoud 
    118   1.1   reinoud #include <uvm/uvm_extern.h>
    119   1.1   reinoud 
    120   1.4   thorpej #include <arm/fiq.h>
    121   1.4   thorpej 
    122   1.1   reinoud #include <machine/cpu.h>
    123   1.3   thorpej #include <machine/intr.h>
    124   1.1   reinoud #include <machine/io.h>
    125   1.2   thorpej #include <arm/arm32/katelib.h>
    126   1.1   reinoud #include <machine/bus.h>
    127   1.4   thorpej 
    128   1.1   reinoud #include <arm/iomd/iomdreg.h>
    129   1.4   thorpej #include <arm/iomd/iomdvar.h>
    130   1.4   thorpej 
    131   1.1   reinoud #include <acorn32/mainbus/piocvar.h>
    132   1.1   reinoud #include <acorn32/mainbus/fdreg.h>
    133   1.1   reinoud 
    134   1.1   reinoud #include "locators.h"
    135   1.1   reinoud 
    136   1.1   reinoud #define NE7CMD_CONFIGURE 0x13
    137   1.1   reinoud 
    138   1.1   reinoud #define FDUNIT(dev)	(minor(dev) / 8)
    139   1.1   reinoud #define FDTYPE(dev)	(minor(dev) % 8)
    140   1.1   reinoud 
    141   1.1   reinoud /* XXX misuse a flag to identify format operation */
    142   1.1   reinoud #define B_FORMAT B_XXX
    143   1.1   reinoud 
    144   1.1   reinoud enum fdc_state {
    145   1.1   reinoud 	DEVIDLE = 0,
    146   1.1   reinoud 	MOTORWAIT,
    147   1.1   reinoud 	DOSEEK,
    148   1.1   reinoud 	SEEKWAIT,
    149   1.1   reinoud 	SEEKTIMEDOUT,
    150   1.1   reinoud 	SEEKCOMPLETE,
    151   1.1   reinoud 	DOIO,
    152   1.1   reinoud 	IOCOMPLETE,
    153   1.1   reinoud 	IOTIMEDOUT,
    154   1.1   reinoud 	DORESET,
    155   1.1   reinoud 	RESETCOMPLETE,
    156   1.1   reinoud 	RESETTIMEDOUT,
    157   1.1   reinoud 	DORECAL,
    158   1.1   reinoud 	RECALWAIT,
    159   1.1   reinoud 	RECALTIMEDOUT,
    160   1.1   reinoud 	RECALCOMPLETE,
    161   1.1   reinoud };
    162   1.1   reinoud 
    163   1.1   reinoud /* software state, per controller */
    164   1.1   reinoud struct fdc_softc {
    165   1.1   reinoud 	struct device sc_dev;		/* boilerplate */
    166   1.1   reinoud 	void *sc_ih;
    167   1.1   reinoud 
    168   1.1   reinoud 	bus_space_tag_t sc_iot;		/* ISA i/o space identifier */
    169   1.1   reinoud 	bus_space_handle_t   sc_ioh;	/* ISA io handle */
    170   1.1   reinoud 
    171   1.1   reinoud 	struct callout sc_timo_ch;	/* timeout callout */
    172   1.1   reinoud 	struct callout sc_intr_ch;	/* pseudo-intr callout */
    173   1.1   reinoud 
    174   1.4   thorpej 	/* ...for pseudo-DMA... */
    175   1.4   thorpej 	struct fiqhandler sc_fh;	/* FIQ handler descriptor */
    176   1.4   thorpej 	struct fiqregs sc_fr;		/* FIQ handler reg context */
    177   1.1   reinoud 	int sc_drq;
    178   1.1   reinoud 
    179   1.1   reinoud 	struct fd_softc *sc_fd[4];	/* pointers to children */
    180   1.1   reinoud 	TAILQ_HEAD(drivehead, fd_softc) sc_drives;
    181   1.1   reinoud 	enum fdc_state sc_state;
    182   1.1   reinoud 	int sc_errors;			/* number of retries so far */
    183   1.1   reinoud 	u_char sc_status[7];		/* copy of registers */
    184   1.1   reinoud };
    185   1.1   reinoud 
    186   1.1   reinoud /* controller driver configuration */
    187   1.1   reinoud int fdcprobe __P((struct device *, struct cfdata *, void *));
    188   1.1   reinoud int fdprint __P((void *, const char *));
    189   1.1   reinoud void fdcattach __P((struct device *, struct device *, void *));
    190   1.1   reinoud 
    191   1.9   thorpej CFATTACH_DECL(fdc, sizeof(struct fdc_softc),
    192  1.10   thorpej     fdcprobe, fdcattach, NULL, NULL);
    193   1.1   reinoud 
    194   1.1   reinoud /*
    195   1.1   reinoud  * Floppies come in various flavors, e.g., 1.2MB vs 1.44MB; here is how
    196   1.1   reinoud  * we tell them apart.
    197   1.1   reinoud  */
    198   1.1   reinoud struct fd_type {
    199   1.1   reinoud 	int	sectrac;	/* sectors per track */
    200   1.1   reinoud 	int	heads;		/* number of heads */
    201   1.1   reinoud 	int	seccyl;		/* sectors per cylinder */
    202   1.1   reinoud 	int	secsize;	/* size code for sectors */
    203   1.1   reinoud 	int	datalen;	/* data len when secsize = 0 */
    204   1.1   reinoud 	int	steprate;	/* step rate and head unload time */
    205   1.1   reinoud 	int	gap1;		/* gap len between sectors */
    206   1.1   reinoud 	int	gap2;		/* formatting gap */
    207   1.1   reinoud 	int	cyls;		/* total num of cylinders */
    208   1.1   reinoud 	int	size;		/* size of disk in sectors */
    209   1.1   reinoud 	int	step;		/* steps per cylinder */
    210   1.1   reinoud 	int	rate;		/* transfer speed code */
    211   1.1   reinoud 	u_char	fillbyte;	/* format fill byte */
    212   1.1   reinoud 	u_char	interleave;	/* interleave factor (formatting) */
    213   1.1   reinoud 	char	*name;
    214   1.1   reinoud };
    215   1.1   reinoud 
    216   1.1   reinoud /* The order of entries in the following table is important -- BEWARE! */
    217   1.1   reinoud struct fd_type fd_types[] = {
    218   1.1   reinoud 	{ 18,2,36,2,0xff,0xcf,0x1b,0x6c,80,2880,1,FDC_500KBPS,0xf6,1, "1.44MB"    }, /* 1.44MB diskette */
    219   1.1   reinoud 	{ 15,2,30,2,0xff,0xdf,0x1b,0x54,80,2400,1,FDC_500KBPS,0xf6,1, "1.2MB"    }, /* 1.2 MB AT-diskettes */
    220   1.1   reinoud 	{  9,2,18,2,0xff,0xdf,0x23,0x50,40, 720,2,FDC_300KBPS,0xf6,1, "360KB/AT" }, /* 360kB in 1.2MB drive */
    221   1.1   reinoud 	{  9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,1,FDC_250KBPS,0xf6,1, "360KB/PC" }, /* 360kB PC diskettes */
    222   1.1   reinoud 	{  9,2,18,2,0xff,0xdf,0x2a,0x50,80,1440,1,FDC_250KBPS,0xf6,1, "720KB"    }, /* 3.5" 720kB diskette */
    223   1.1   reinoud 	{  9,2,18,2,0xff,0xdf,0x23,0x50,80,1440,1,FDC_300KBPS,0xf6,1, "720KB/x"  }, /* 720kB in 1.2MB drive */
    224   1.1   reinoud 	{  9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,2,FDC_250KBPS,0xf6,1, "360KB/x"  }, /* 360kB in 720kB drive */
    225   1.1   reinoud };
    226   1.1   reinoud 
    227   1.1   reinoud /* software state, per disk (with up to 4 disks per ctlr) */
    228   1.1   reinoud struct fd_softc {
    229   1.1   reinoud 	struct device sc_dev;
    230   1.1   reinoud 	struct disk sc_dk;
    231   1.1   reinoud 
    232   1.1   reinoud 	struct fd_type *sc_deftype;	/* default type descriptor */
    233   1.1   reinoud 	struct fd_type *sc_type;	/* current type descriptor */
    234   1.1   reinoud 	struct fd_type sc_type_copy;	/* copy for fiddling when formatting */
    235   1.1   reinoud 
    236   1.1   reinoud 	struct callout sc_motoron_ch;
    237   1.1   reinoud 	struct callout sc_motoroff_ch;
    238   1.1   reinoud 
    239   1.1   reinoud 	daddr_t	sc_blkno;	/* starting block number */
    240   1.1   reinoud 	int sc_bcount;		/* byte count left */
    241   1.1   reinoud  	int sc_opts;			/* user-set options */
    242   1.1   reinoud 	int sc_skip;		/* bytes already transferred */
    243   1.1   reinoud 	int sc_nblks;		/* number of blocks currently transferring */
    244   1.1   reinoud 	int sc_nbytes;		/* number of bytes currently transferring */
    245   1.1   reinoud 
    246   1.1   reinoud 	int sc_drive;		/* physical unit number */
    247   1.1   reinoud 	int sc_flags;
    248   1.1   reinoud #define	FD_OPEN		0x01		/* it's open */
    249   1.1   reinoud #define	FD_MOTOR	0x02		/* motor should be on */
    250   1.1   reinoud #define	FD_MOTOR_WAIT	0x04		/* motor coming up */
    251   1.1   reinoud 	int sc_cylin;		/* where we think the head is */
    252   1.1   reinoud 
    253   1.1   reinoud 	void *sc_sdhook;	/* saved shutdown hook for drive. */
    254   1.1   reinoud 
    255   1.1   reinoud 	TAILQ_ENTRY(fd_softc) sc_drivechain;
    256   1.1   reinoud 	int sc_ops;		/* I/O ops since last switch */
    257   1.5   hannken 	struct bufq_state sc_q;	/* pending I/O requests */
    258   1.1   reinoud 	int sc_active;		/* number of active I/O operations */
    259   1.1   reinoud };
    260   1.1   reinoud 
    261   1.1   reinoud /* floppy driver configuration */
    262   1.1   reinoud int fdprobe __P((struct device *, struct cfdata *, void *));
    263   1.1   reinoud void fdattach __P((struct device *, struct device *, void *));
    264   1.1   reinoud 
    265   1.4   thorpej extern char floppy_read_fiq[], floppy_read_fiq_end[];
    266   1.4   thorpej extern char floppy_write_fiq[], floppy_write_fiq_end[];
    267   1.1   reinoud 
    268   1.9   thorpej CFATTACH_DECL(fd, sizeof(struct fd_softc),
    269  1.10   thorpej     fdprobe, fdattach, NULL, NULL);
    270   1.1   reinoud 
    271   1.1   reinoud extern struct cfdriver fd_cd;
    272   1.1   reinoud 
    273   1.6   gehenna dev_type_open(fdopen);
    274   1.6   gehenna dev_type_close(fdclose);
    275   1.6   gehenna dev_type_read(fdread);
    276   1.6   gehenna dev_type_write(fdwrite);
    277   1.6   gehenna dev_type_ioctl(fdioctl);
    278   1.6   gehenna dev_type_strategy(fdstrategy);
    279   1.6   gehenna 
    280   1.6   gehenna const struct bdevsw fd_bdevsw = {
    281   1.6   gehenna 	fdopen, fdclose, fdstrategy, fdioctl, nodump, nosize, D_DISK
    282   1.6   gehenna };
    283   1.6   gehenna 
    284   1.6   gehenna const struct cdevsw fd_cdevsw = {
    285   1.6   gehenna 	fdopen, fdclose, fdread, fdwrite, fdioctl,
    286  1.11  jdolecek 	nostop, notty, nopoll, nommap, nokqfilter, D_DISK
    287   1.6   gehenna };
    288   1.6   gehenna 
    289   1.1   reinoud void fdgetdisklabel __P((struct fd_softc *));
    290   1.1   reinoud int fd_get_parms __P((struct fd_softc *));
    291   1.1   reinoud void fdstart __P((struct fd_softc *));
    292   1.1   reinoud 
    293   1.1   reinoud struct dkdriver fddkdriver = { fdstrategy };
    294   1.1   reinoud 
    295   1.1   reinoud struct fd_type *fd_nvtotype __P((char *, int, int));
    296   1.1   reinoud void fd_set_motor __P((struct fdc_softc *fdc, int reset));
    297   1.1   reinoud void fd_motor_off __P((void *arg));
    298   1.1   reinoud void fd_motor_on __P((void *arg));
    299   1.1   reinoud int fdcresult __P((struct fdc_softc *fdc));
    300   1.1   reinoud int out_fdc __P((bus_space_tag_t iot, bus_space_handle_t ioh, u_char x));
    301   1.1   reinoud void fdcstart __P((struct fdc_softc *fdc));
    302   1.1   reinoud void fdcstatus __P((struct device *dv, int n, char *s));
    303   1.1   reinoud void fdctimeout __P((void *arg));
    304   1.1   reinoud void fdcpseudointr __P((void *arg));
    305   1.1   reinoud int fdcintr __P((void *));
    306   1.1   reinoud void fdcretry __P((struct fdc_softc *fdc));
    307   1.1   reinoud void fdfinish __P((struct fd_softc *fd, struct buf *bp));
    308   1.1   reinoud __inline struct fd_type *fd_dev_to_type __P((struct fd_softc *, dev_t));
    309   1.1   reinoud int fdformat __P((dev_t, struct ne7_fd_formb *, struct proc *));
    310   1.1   reinoud 
    311   1.1   reinoud int
    312   1.1   reinoud fdcprobe(parent, cf, aux)
    313   1.1   reinoud 	struct device *parent;
    314   1.1   reinoud 	struct cfdata *cf;
    315   1.1   reinoud 	void *aux;
    316   1.1   reinoud {
    317   1.1   reinoud 	struct pioc_attach_args *pa = aux;
    318   1.1   reinoud 	bus_space_tag_t iot;
    319   1.1   reinoud 	bus_space_handle_t ioh;
    320   1.1   reinoud 	int rv;
    321   1.1   reinoud 
    322   1.1   reinoud 	if (pa->pa_name && strcmp(pa->pa_name, "fdc") != 0)
    323   1.1   reinoud 		return(0);
    324   1.1   reinoud 
    325   1.1   reinoud 	iot = pa->pa_iot;
    326   1.1   reinoud 	rv = 0;
    327   1.1   reinoud 
    328   1.1   reinoud 	/* Map the i/o space. */
    329   1.1   reinoud 	if (bus_space_map(iot, pa->pa_iobase + pa->pa_offset, FDC_NPORT, 0, &ioh))
    330   1.1   reinoud 		return 0;
    331   1.1   reinoud 
    332   1.1   reinoud 	/* reset */
    333   1.1   reinoud 	bus_space_write_2(iot, ioh, fdout, 0);
    334   1.1   reinoud 	delay(100);
    335   1.1   reinoud 	bus_space_write_2(iot, ioh, fdout, FDO_FRST);
    336   1.1   reinoud 
    337   1.1   reinoud 	/* see if it can handle a command */
    338   1.1   reinoud 	if (out_fdc(iot, ioh, NE7CMD_SPECIFY) < 0)
    339   1.1   reinoud 		goto out;
    340   1.1   reinoud 	out_fdc(iot, ioh, 0xdf);
    341   1.1   reinoud 	out_fdc(iot, ioh, 2);
    342   1.1   reinoud 
    343   1.1   reinoud 	rv = 1;
    344   1.1   reinoud 	pa->pa_iosize = FDC_NPORT;
    345   1.1   reinoud 
    346   1.1   reinoud  out:
    347   1.1   reinoud 	bus_space_unmap(iot, ioh, FDC_NPORT);
    348   1.1   reinoud 	return rv;
    349   1.1   reinoud }
    350   1.1   reinoud 
    351   1.1   reinoud /*
    352   1.1   reinoud  * Arguments passed between fdcattach and fdprobe.
    353   1.1   reinoud  */
    354   1.1   reinoud struct fdc_attach_args {
    355   1.1   reinoud 	int fa_drive;
    356   1.1   reinoud 	struct fd_type *fa_deftype;
    357   1.1   reinoud };
    358   1.1   reinoud 
    359   1.1   reinoud /*
    360   1.1   reinoud  * Print the location of a disk drive (called just before attaching the
    361   1.1   reinoud  * the drive).  If `fdc' is not NULL, the drive was found but was not
    362   1.1   reinoud  * in the system config file; print the drive name as well.
    363   1.1   reinoud  * Return QUIET (config_find ignores this if the device was configured) to
    364   1.1   reinoud  * avoid printing `fdN not configured' messages.
    365   1.1   reinoud  */
    366   1.1   reinoud int
    367   1.1   reinoud fdprint(aux, fdc)
    368   1.1   reinoud 	void *aux;
    369   1.1   reinoud 	const char *fdc;
    370   1.1   reinoud {
    371   1.1   reinoud 	register struct fdc_attach_args *fa = aux;
    372   1.1   reinoud 
    373   1.1   reinoud 	if (!fdc)
    374  1.13   thorpej 		aprint_normal(" drive %d", fa->fa_drive);
    375   1.1   reinoud 	return QUIET;
    376   1.1   reinoud }
    377   1.1   reinoud 
    378   1.1   reinoud void
    379   1.1   reinoud fdcattach(parent, self, aux)
    380   1.1   reinoud 	struct device *parent, *self;
    381   1.1   reinoud 	void *aux;
    382   1.1   reinoud {
    383   1.1   reinoud 	struct fdc_softc *fdc = (void *)self;
    384   1.1   reinoud 	bus_space_tag_t iot;
    385   1.1   reinoud 	bus_space_handle_t ioh;
    386   1.1   reinoud 	struct pioc_attach_args *pa = aux;
    387   1.1   reinoud 	struct fdc_attach_args fa;
    388   1.1   reinoud 	int type;
    389   1.1   reinoud 
    390   1.1   reinoud 	iot = pa->pa_iot;
    391   1.1   reinoud 
    392   1.1   reinoud 	/* Re-map the I/O space. */
    393   1.1   reinoud 	if (bus_space_map(iot, pa->pa_iobase + pa->pa_offset, FDC_NPORT, 0, &ioh))
    394   1.1   reinoud 		panic("fdcattach: couldn't map I/O ports");
    395   1.1   reinoud 
    396   1.1   reinoud 	fdc->sc_iot = iot;
    397   1.1   reinoud 	fdc->sc_ioh = ioh;
    398   1.1   reinoud 
    399   1.1   reinoud 	fdc->sc_drq = pa->pa_iobase + pa->pa_offset + pa->pa_drq;
    400   1.1   reinoud 	fdc->sc_state = DEVIDLE;
    401   1.1   reinoud 	TAILQ_INIT(&fdc->sc_drives);
    402   1.1   reinoud 
    403   1.1   reinoud 	printf("\n");
    404   1.1   reinoud 
    405   1.1   reinoud 	callout_init(&fdc->sc_timo_ch);
    406   1.1   reinoud 	callout_init(&fdc->sc_intr_ch);
    407   1.1   reinoud 
    408   1.1   reinoud 	fdc->sc_ih = intr_claim(pa->pa_irq, IPL_BIO, "fdc",
    409   1.1   reinoud 	    fdcintr, fdc);
    410   1.1   reinoud 	if (!fdc->sc_ih)
    411   1.7    provos 		panic("%s: Cannot claim IRQ %d", self->dv_xname, pa->pa_irq);
    412   1.1   reinoud 
    413   1.1   reinoud #if 0
    414   1.1   reinoud 	/*
    415   1.1   reinoud 	 * The NVRAM info only tells us about the first two disks on the
    416   1.1   reinoud 	 * `primary' floppy controller.
    417   1.1   reinoud 	 */
    418   1.1   reinoud 	if (fdc->sc_dev.dv_unit == 0)
    419   1.1   reinoud 		type = mc146818_read(NULL, NVRAM_DISKETTE); /* XXX softc */
    420   1.1   reinoud 	else
    421   1.1   reinoud 		type = -1;
    422   1.1   reinoud #endif
    423   1.1   reinoud 	type = 0x10;	/* XXX - hardcoded for 1 floppy */
    424   1.1   reinoud 
    425   1.1   reinoud 	/* physical limit: four drives per controller. */
    426   1.1   reinoud 	for (fa.fa_drive = 0; fa.fa_drive < 4; fa.fa_drive++) {
    427   1.1   reinoud 		if (type >= 0 && fa.fa_drive < 2)
    428   1.1   reinoud 			fa.fa_deftype = fd_nvtotype(fdc->sc_dev.dv_xname,
    429   1.1   reinoud 			    type, fa.fa_drive);
    430   1.1   reinoud 		else
    431   1.1   reinoud 			fa.fa_deftype = NULL;		/* unknown */
    432   1.1   reinoud 		(void)config_found(self, (void *)&fa, fdprint);
    433   1.1   reinoud 	}
    434   1.1   reinoud }
    435   1.1   reinoud 
    436   1.1   reinoud int
    437   1.1   reinoud fdprobe(parent, cf, aux)
    438   1.1   reinoud 	struct device *parent;
    439   1.1   reinoud 	struct cfdata *cf;
    440   1.1   reinoud 	void *aux;
    441   1.1   reinoud {
    442   1.1   reinoud 	struct fdc_softc *fdc = (void *)parent;
    443   1.1   reinoud 	struct fdc_attach_args *fa = aux;
    444   1.1   reinoud 	int drive = fa->fa_drive;
    445   1.1   reinoud 	bus_space_tag_t iot = fdc->sc_iot;
    446   1.1   reinoud 	bus_space_handle_t ioh = fdc->sc_ioh;
    447   1.1   reinoud 	int n;
    448   1.1   reinoud 
    449   1.1   reinoud 	if (cf->cf_loc[FDCCF_DRIVE] != FDCCF_DRIVE_DEFAULT
    450   1.1   reinoud 	  && cf->cf_loc[FDCCF_DRIVE] != drive)
    451   1.1   reinoud 		return 0;
    452   1.1   reinoud 	/*
    453   1.1   reinoud 	 * XXX
    454   1.1   reinoud 	 * This is to work around some odd interactions between this driver
    455   1.1   reinoud 	 * and SMC Ethernet cards.
    456   1.1   reinoud 	 */
    457   1.1   reinoud 
    458   1.1   reinoud 	/* Don't need this for arm32 port but leave for the time being (it won't hurt) */
    459   1.1   reinoud 
    460   1.1   reinoud 	if (cf->cf_loc[FDCCF_DRIVE] == FDCCF_DRIVE_DEFAULT && drive >= 2)
    461   1.1   reinoud 		return 0;
    462   1.1   reinoud 
    463   1.1   reinoud 	/* select drive and turn on motor */
    464   1.1   reinoud 	bus_space_write_2(iot, ioh, fdout, drive | FDO_FRST | FDO_MOEN(drive));
    465   1.1   reinoud 	/* wait for motor to spin up */
    466   1.1   reinoud 	delay(250000);
    467   1.1   reinoud 	out_fdc(iot, ioh, NE7CMD_RECAL);
    468   1.1   reinoud 	out_fdc(iot, ioh, drive);
    469   1.1   reinoud 	/* wait for recalibrate */
    470   1.1   reinoud 	delay(2000000);
    471   1.1   reinoud 	out_fdc(iot, ioh, NE7CMD_SENSEI);
    472   1.1   reinoud 	n = fdcresult(fdc);
    473   1.1   reinoud #ifdef FD_DEBUG
    474   1.1   reinoud 	{
    475   1.1   reinoud 		int i;
    476   1.1   reinoud 		printf("fdprobe: status");
    477   1.1   reinoud 		for (i = 0; i < n; i++)
    478   1.1   reinoud 			printf(" %x", fdc->sc_status[i]);
    479   1.1   reinoud 		printf("\n");
    480   1.1   reinoud 	}
    481   1.1   reinoud #endif
    482   1.1   reinoud 	/* turn off motor */
    483   1.1   reinoud 	bus_space_write_1(iot, ioh, fdout, FDO_FRST);
    484   1.1   reinoud 
    485   1.1   reinoud 	if (n != 2 || (fdc->sc_status[0] & 0xf8) != 0x20)
    486   1.1   reinoud 		return 0;
    487   1.1   reinoud 
    488   1.1   reinoud 	return 1;
    489   1.1   reinoud }
    490   1.1   reinoud 
    491   1.1   reinoud /*
    492   1.1   reinoud  * Controller is working, and drive responded.  Attach it.
    493   1.1   reinoud  */
    494   1.1   reinoud void
    495   1.1   reinoud fdattach(parent, self, aux)
    496   1.1   reinoud 	struct device *parent, *self;
    497   1.1   reinoud 	void *aux;
    498   1.1   reinoud {
    499   1.1   reinoud 	struct fdc_softc *fdc = (void *)parent;
    500   1.1   reinoud 	struct fd_softc *fd = (void *)self;
    501   1.1   reinoud 	struct fdc_attach_args *fa = aux;
    502   1.1   reinoud 	struct fd_type *type = fa->fa_deftype;
    503   1.1   reinoud 	int drive = fa->fa_drive;
    504   1.1   reinoud 
    505   1.1   reinoud 	callout_init(&fd->sc_motoron_ch);
    506   1.1   reinoud 	callout_init(&fd->sc_motoroff_ch);
    507   1.1   reinoud 
    508   1.1   reinoud 	/* XXX Allow `flags' to override device type? */
    509   1.1   reinoud 
    510   1.1   reinoud 	if (type)
    511   1.1   reinoud 		printf(": %s %d cyl, %d head, %d sec\n", type->name,
    512   1.1   reinoud 		    type->cyls, type->heads, type->sectrac);
    513   1.1   reinoud 	else
    514   1.1   reinoud 		printf(": density unknown\n");
    515   1.1   reinoud 
    516   1.5   hannken 	bufq_alloc(&fd->sc_q, BUFQ_DISKSORT|BUFQ_SORT_CYLINDER);
    517   1.1   reinoud 	fd->sc_cylin = -1;
    518   1.1   reinoud 	fd->sc_drive = drive;
    519   1.1   reinoud 	fd->sc_deftype = type;
    520   1.1   reinoud 	fdc->sc_fd[drive] = fd;
    521   1.1   reinoud 
    522   1.1   reinoud 	/*
    523   1.1   reinoud 	 * Initialize and attach the disk structure.
    524   1.1   reinoud 	 */
    525   1.1   reinoud 	fd->sc_dk.dk_name = fd->sc_dev.dv_xname;
    526   1.1   reinoud 	fd->sc_dk.dk_driver = &fddkdriver;
    527   1.1   reinoud 	disk_attach(&fd->sc_dk);
    528   1.1   reinoud 
    529   1.1   reinoud 	/* Needed to power off if the motor is on when we halt. */
    530   1.1   reinoud 
    531   1.1   reinoud }
    532   1.1   reinoud 
    533   1.1   reinoud /*
    534   1.1   reinoud  * Translate nvram type into internal data structure.  Return NULL for
    535   1.1   reinoud  * none/unknown/unusable.
    536   1.1   reinoud  */
    537   1.1   reinoud struct fd_type *
    538   1.1   reinoud fd_nvtotype(fdc, nvraminfo, drive)
    539   1.1   reinoud 	char *fdc;
    540   1.1   reinoud 	int nvraminfo, drive;
    541   1.1   reinoud {
    542   1.1   reinoud 	int type;
    543   1.1   reinoud 
    544   1.1   reinoud 	type = (drive == 0 ? nvraminfo : nvraminfo << 4) & 0xf0;
    545   1.1   reinoud 	switch (type) {
    546   1.1   reinoud #ifndef RC7500
    547   1.1   reinoud 	case 0x00 :
    548   1.1   reinoud 		return NULL;
    549   1.1   reinoud #else
    550   1.1   reinoud 	case 0x00 :
    551   1.1   reinoud #endif	/* !RC7500 */
    552   1.1   reinoud 	case 0x10 :
    553   1.1   reinoud 		return &fd_types[0];
    554   1.1   reinoud 	default:
    555   1.1   reinoud 		printf("%s: drive %d: unknown device type 0x%x\n",
    556   1.1   reinoud 		    fdc, drive, type);
    557   1.1   reinoud 		return NULL;
    558   1.1   reinoud 	}
    559   1.1   reinoud }
    560   1.1   reinoud 
    561   1.1   reinoud __inline struct fd_type *
    562   1.1   reinoud fd_dev_to_type(fd, dev)
    563   1.1   reinoud 	struct fd_softc *fd;
    564   1.1   reinoud 	dev_t dev;
    565   1.1   reinoud {
    566   1.1   reinoud 	int type = FDTYPE(dev);
    567   1.1   reinoud 
    568   1.1   reinoud 	if (type > (sizeof(fd_types) / sizeof(fd_types[0])))
    569   1.1   reinoud 		return NULL;
    570   1.1   reinoud 	return type ? &fd_types[type - 1] : fd->sc_deftype;
    571   1.1   reinoud }
    572   1.1   reinoud 
    573   1.1   reinoud void
    574   1.1   reinoud fdstrategy(bp)
    575   1.1   reinoud 	register struct buf *bp;	/* IO operation to perform */
    576   1.1   reinoud {
    577   1.1   reinoud 	struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(bp->b_dev)];
    578   1.1   reinoud 	int sz;
    579   1.1   reinoud  	int s;
    580   1.1   reinoud 
    581   1.1   reinoud 	/* Valid unit, controller, and request? */
    582   1.1   reinoud 	if (bp->b_blkno < 0 ||
    583   1.1   reinoud 	    ((bp->b_bcount % FDC_BSIZE) != 0 &&
    584   1.1   reinoud 	     (bp->b_flags & B_FORMAT) == 0)) {
    585   1.1   reinoud 		bp->b_error = EINVAL;
    586   1.1   reinoud 		goto bad;
    587   1.1   reinoud 	}
    588   1.1   reinoud 
    589   1.1   reinoud 	/* If it's a null transfer, return immediately. */
    590   1.1   reinoud 	if (bp->b_bcount == 0)
    591   1.1   reinoud 		goto done;
    592   1.1   reinoud 
    593   1.1   reinoud 	sz = howmany(bp->b_bcount, FDC_BSIZE);
    594   1.1   reinoud 
    595   1.1   reinoud 	if (bp->b_blkno + sz > fd->sc_type->size) {
    596   1.1   reinoud 		sz = fd->sc_type->size - bp->b_blkno;
    597   1.1   reinoud 		if (sz == 0) {
    598   1.1   reinoud 			/* If exactly at end of disk, return EOF. */
    599   1.1   reinoud 			goto done;
    600   1.1   reinoud 		}
    601   1.1   reinoud 		if (sz < 0) {
    602   1.1   reinoud 			/* If past end of disk, return EINVAL. */
    603   1.1   reinoud 			bp->b_error = EINVAL;
    604   1.1   reinoud 			goto bad;
    605   1.1   reinoud 		}
    606   1.1   reinoud 		/* Otherwise, truncate request. */
    607   1.1   reinoud 		bp->b_bcount = sz << DEV_BSHIFT;
    608   1.1   reinoud 	}
    609   1.1   reinoud 
    610   1.1   reinoud 	bp->b_rawblkno = bp->b_blkno;
    611   1.1   reinoud  	bp->b_cylinder = bp->b_blkno / (FDC_BSIZE / DEV_BSIZE) / fd->sc_type->seccyl;
    612   1.1   reinoud 
    613   1.1   reinoud #ifdef FD_DEBUG
    614   1.1   reinoud 	printf("fdstrategy: b_blkno %d b_bcount %d blkno %d cylin %d sz %d\n",
    615   1.1   reinoud 	    bp->b_blkno, bp->b_bcount, fd->sc_blkno, bp->b_cylinder, sz);
    616   1.1   reinoud #endif
    617   1.1   reinoud 
    618   1.1   reinoud 	/* Queue transfer on drive, activate drive and controller if idle. */
    619   1.1   reinoud 	s = splbio();
    620   1.5   hannken 	BUFQ_PUT(&fd->sc_q, bp);
    621   1.1   reinoud 	callout_stop(&fd->sc_motoroff_ch);		/* a good idea */
    622   1.1   reinoud 	if (fd->sc_active == 0)
    623   1.1   reinoud 		fdstart(fd);
    624   1.1   reinoud #ifdef DIAGNOSTIC
    625   1.1   reinoud 	else {
    626   1.1   reinoud 		struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
    627   1.1   reinoud 		if (fdc->sc_state == DEVIDLE) {
    628   1.1   reinoud 			printf("fdstrategy: controller inactive\n");
    629   1.1   reinoud 			fdcstart(fdc);
    630   1.1   reinoud 		}
    631   1.1   reinoud 	}
    632   1.1   reinoud #endif
    633   1.1   reinoud 	splx(s);
    634   1.1   reinoud 	return;
    635   1.1   reinoud 
    636   1.1   reinoud bad:
    637   1.1   reinoud 	bp->b_flags |= B_ERROR;
    638   1.1   reinoud done:
    639   1.1   reinoud 	/* Toss transfer; we're done early. */
    640   1.1   reinoud 	bp->b_resid = bp->b_bcount;
    641   1.1   reinoud 	biodone(bp);
    642   1.1   reinoud }
    643   1.1   reinoud 
    644   1.1   reinoud void
    645   1.1   reinoud fdstart(fd)
    646   1.1   reinoud 	struct fd_softc *fd;
    647   1.1   reinoud {
    648   1.1   reinoud 	struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
    649   1.1   reinoud 	int active = fdc->sc_drives.tqh_first != 0;
    650   1.1   reinoud 
    651   1.1   reinoud 	/* Link into controller queue. */
    652   1.1   reinoud 	fd->sc_active = 1;
    653   1.1   reinoud 	TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain);
    654   1.1   reinoud 
    655   1.1   reinoud 	/* If controller not already active, start it. */
    656   1.1   reinoud 	if (!active)
    657   1.1   reinoud 		fdcstart(fdc);
    658   1.1   reinoud }
    659   1.1   reinoud 
    660   1.1   reinoud void
    661   1.1   reinoud fdfinish(fd, bp)
    662   1.1   reinoud 	struct fd_softc *fd;
    663   1.1   reinoud 	struct buf *bp;
    664   1.1   reinoud {
    665   1.1   reinoud 	struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
    666   1.1   reinoud 
    667   1.1   reinoud 	/*
    668   1.1   reinoud 	 * Move this drive to the end of the queue to give others a `fair'
    669   1.1   reinoud 	 * chance.  We only force a switch if N operations are completed while
    670   1.1   reinoud 	 * another drive is waiting to be serviced, since there is a long motor
    671   1.1   reinoud 	 * startup delay whenever we switch.
    672   1.1   reinoud 	 */
    673   1.5   hannken 	(void)BUFQ_GET(&fd->sc_q);
    674   1.1   reinoud 	if (fd->sc_drivechain.tqe_next && ++fd->sc_ops >= 8) {
    675   1.1   reinoud 		fd->sc_ops = 0;
    676   1.1   reinoud 		TAILQ_REMOVE(&fdc->sc_drives, fd, sc_drivechain);
    677   1.5   hannken 		if (BUFQ_PEEK(&fd->sc_q) != NULL)
    678   1.1   reinoud 			TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain);
    679   1.1   reinoud 		else
    680   1.1   reinoud 			fd->sc_active = 0;
    681   1.1   reinoud 	}
    682   1.1   reinoud 	bp->b_resid = fd->sc_bcount;
    683   1.1   reinoud 	fd->sc_skip = 0;
    684   1.1   reinoud 
    685   1.1   reinoud 	biodone(bp);
    686   1.1   reinoud 	/* turn off motor 5s from now */
    687   1.1   reinoud 	callout_reset(&fd->sc_motoroff_ch, 5 * hz, fd_motor_off, fd);
    688   1.1   reinoud 	fdc->sc_state = DEVIDLE;
    689   1.1   reinoud }
    690   1.1   reinoud 
    691   1.1   reinoud int
    692   1.1   reinoud fdread(dev, uio, flags)
    693   1.1   reinoud 	dev_t dev;
    694   1.1   reinoud 	struct uio *uio;
    695   1.1   reinoud 	int flags;
    696   1.1   reinoud {
    697   1.1   reinoud 
    698   1.1   reinoud 	return (physio(fdstrategy, NULL, dev, B_READ, minphys, uio));
    699   1.1   reinoud }
    700   1.1   reinoud 
    701   1.1   reinoud int
    702   1.1   reinoud fdwrite(dev, uio, flags)
    703   1.1   reinoud 	dev_t dev;
    704   1.1   reinoud 	struct uio *uio;
    705   1.1   reinoud 	int flags;
    706   1.1   reinoud {
    707   1.1   reinoud 
    708   1.1   reinoud 	return (physio(fdstrategy, NULL, dev, B_WRITE, minphys, uio));
    709   1.1   reinoud }
    710   1.1   reinoud 
    711   1.1   reinoud void
    712   1.1   reinoud fd_set_motor(fdc, reset)
    713   1.1   reinoud 	struct fdc_softc *fdc;
    714   1.1   reinoud 	int reset;
    715   1.1   reinoud {
    716   1.1   reinoud 	struct fd_softc *fd;
    717   1.1   reinoud 	u_char status;
    718   1.1   reinoud 	int n;
    719   1.1   reinoud 
    720   1.1   reinoud 	if ((fd = fdc->sc_drives.tqh_first) != NULL)
    721   1.1   reinoud 		status = fd->sc_drive;
    722   1.1   reinoud 	else
    723   1.1   reinoud 		status = 0;
    724   1.1   reinoud 	if (!reset)
    725   1.1   reinoud 		status |= FDO_FRST | FDO_FDMAEN;
    726   1.1   reinoud 	for (n = 0; n < 4; n++)
    727   1.1   reinoud 		if ((fd = fdc->sc_fd[n]) && (fd->sc_flags & FD_MOTOR))
    728   1.1   reinoud 			status |= FDO_MOEN(n);
    729   1.1   reinoud 	bus_space_write_2(fdc->sc_iot, fdc->sc_ioh, fdout, status);
    730   1.1   reinoud }
    731   1.1   reinoud 
    732   1.1   reinoud void
    733   1.1   reinoud fd_motor_off(arg)
    734   1.1   reinoud 	void *arg;
    735   1.1   reinoud {
    736   1.1   reinoud 	struct fd_softc *fd = arg;
    737   1.1   reinoud 	int s;
    738   1.1   reinoud 
    739   1.1   reinoud 	s = splbio();
    740   1.1   reinoud 	fd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT);
    741   1.1   reinoud 	fd_set_motor((struct fdc_softc *)fd->sc_dev.dv_parent, 0);
    742   1.1   reinoud 	splx(s);
    743   1.1   reinoud }
    744   1.1   reinoud 
    745   1.1   reinoud void
    746   1.1   reinoud fd_motor_on(arg)
    747   1.1   reinoud 	void *arg;
    748   1.1   reinoud {
    749   1.1   reinoud 	struct fd_softc *fd = arg;
    750   1.1   reinoud 	struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
    751   1.1   reinoud 	int s;
    752   1.1   reinoud 
    753   1.1   reinoud 	s = splbio();
    754   1.1   reinoud 	fd->sc_flags &= ~FD_MOTOR_WAIT;
    755   1.1   reinoud 	if ((fdc->sc_drives.tqh_first == fd) && (fdc->sc_state == MOTORWAIT))
    756   1.1   reinoud 		(void) fdcintr(fdc);
    757   1.1   reinoud 	splx(s);
    758   1.1   reinoud }
    759   1.1   reinoud 
    760   1.1   reinoud int
    761   1.1   reinoud fdcresult(fdc)
    762   1.1   reinoud 	struct fdc_softc *fdc;
    763   1.1   reinoud {
    764   1.1   reinoud 	bus_space_tag_t iot = fdc->sc_iot;
    765   1.1   reinoud 	bus_space_handle_t ioh = fdc->sc_ioh;
    766   1.1   reinoud 	u_char i;
    767   1.1   reinoud 	int j = 100000,
    768   1.1   reinoud 	    n = 0;
    769   1.1   reinoud 
    770   1.1   reinoud 	for (; j; j--) {
    771   1.1   reinoud 		i = bus_space_read_1(iot, ioh, fdsts) &
    772   1.1   reinoud 		    (NE7_DIO | NE7_RQM | NE7_CB);
    773   1.1   reinoud 		if (i == NE7_RQM)
    774   1.1   reinoud 			return n;
    775   1.1   reinoud 		if (i == (NE7_DIO | NE7_RQM | NE7_CB)) {
    776   1.1   reinoud 			if (n >= sizeof(fdc->sc_status)) {
    777   1.1   reinoud 				log(LOG_ERR, "fdcresult: overrun\n");
    778   1.1   reinoud 				return -1;
    779   1.1   reinoud 			}
    780   1.1   reinoud 			fdc->sc_status[n++] =
    781   1.1   reinoud 			    bus_space_read_1(iot, ioh, fddata);
    782   1.1   reinoud 		}
    783   1.1   reinoud 		delay(10);
    784   1.1   reinoud 	}
    785   1.1   reinoud 	log(LOG_ERR, "fdcresult: timeout\n");
    786   1.1   reinoud 	return -1;
    787   1.1   reinoud }
    788   1.1   reinoud 
    789   1.1   reinoud int
    790   1.1   reinoud out_fdc(iot, ioh, x)
    791   1.1   reinoud 	bus_space_tag_t iot;
    792   1.1   reinoud 	bus_space_handle_t ioh;
    793   1.1   reinoud 	u_char x;
    794   1.1   reinoud {
    795   1.1   reinoud 	int i = 100000;
    796   1.1   reinoud 
    797   1.1   reinoud 	while ((bus_space_read_1(iot, ioh, fdsts) & NE7_DIO) && i-- > 0);
    798   1.1   reinoud 	if (i <= 0)
    799   1.1   reinoud 		return -1;
    800   1.1   reinoud 	while ((bus_space_read_1(iot, ioh, fdsts) & NE7_RQM) == 0 && i-- > 0);
    801   1.1   reinoud 	if (i <= 0)
    802   1.1   reinoud 		return -1;
    803   1.1   reinoud 	bus_space_write_2(iot, ioh, fddata, x);
    804   1.1   reinoud 	return 0;
    805   1.1   reinoud }
    806   1.1   reinoud 
    807   1.1   reinoud int
    808   1.1   reinoud fdopen(dev, flags, mode, p)
    809   1.1   reinoud 	dev_t dev;
    810   1.1   reinoud 	int flags;
    811   1.1   reinoud 	int mode;
    812   1.1   reinoud 	struct proc *p;
    813   1.1   reinoud {
    814   1.1   reinoud  	int unit;
    815   1.1   reinoud 	struct fd_softc *fd;
    816   1.1   reinoud 	struct fd_type *type;
    817   1.1   reinoud 
    818   1.1   reinoud 	unit = FDUNIT(dev);
    819   1.1   reinoud 	if (unit >= fd_cd.cd_ndevs)
    820   1.1   reinoud 		return ENXIO;
    821   1.1   reinoud 	fd = fd_cd.cd_devs[unit];
    822   1.1   reinoud 	if (fd == 0)
    823   1.1   reinoud 		return ENXIO;
    824   1.1   reinoud 	type = fd_dev_to_type(fd, dev);
    825   1.1   reinoud 	if (type == NULL)
    826   1.1   reinoud 		return ENXIO;
    827   1.1   reinoud 
    828   1.1   reinoud 	if ((fd->sc_flags & FD_OPEN) != 0 &&
    829   1.1   reinoud 	    memcmp(fd->sc_type, type, sizeof(*type)))
    830   1.1   reinoud 		return EBUSY;
    831   1.1   reinoud 
    832   1.1   reinoud 	fd->sc_type_copy = *type;
    833   1.1   reinoud 	fd->sc_type = &fd->sc_type_copy;
    834   1.1   reinoud 	fd->sc_cylin = -1;
    835   1.1   reinoud 	fd->sc_flags |= FD_OPEN;
    836   1.1   reinoud 
    837   1.1   reinoud 	return 0;
    838   1.1   reinoud }
    839   1.1   reinoud 
    840   1.1   reinoud int
    841   1.1   reinoud fdclose(dev, flags, mode, p)
    842   1.1   reinoud 	dev_t dev;
    843   1.1   reinoud 	int flags;
    844   1.1   reinoud 	int mode;
    845   1.1   reinoud 	struct proc *p;
    846   1.1   reinoud {
    847   1.1   reinoud 	struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
    848   1.1   reinoud 
    849   1.1   reinoud 	fd->sc_flags &= ~FD_OPEN;
    850   1.1   reinoud 	fd->sc_opts &= ~(FDOPT_NORETRY|FDOPT_SILENT);
    851   1.1   reinoud 	return 0;
    852   1.1   reinoud }
    853   1.1   reinoud 
    854   1.1   reinoud void
    855   1.1   reinoud fdcstart(fdc)
    856   1.1   reinoud 	struct fdc_softc *fdc;
    857   1.1   reinoud {
    858   1.1   reinoud 
    859   1.1   reinoud #ifdef DIAGNOSTIC
    860   1.1   reinoud 	/* only got here if controller's drive queue was inactive; should
    861   1.1   reinoud 	   be in idle state */
    862   1.1   reinoud 	if (fdc->sc_state != DEVIDLE) {
    863   1.1   reinoud 		printf("fdcstart: not idle\n");
    864   1.1   reinoud 		return;
    865   1.1   reinoud 	}
    866   1.1   reinoud #endif
    867   1.1   reinoud 	(void) fdcintr(fdc);
    868   1.1   reinoud }
    869   1.1   reinoud 
    870   1.1   reinoud void
    871   1.1   reinoud fdcstatus(dv, n, s)
    872   1.1   reinoud 	struct device *dv;
    873   1.1   reinoud 	int n;
    874   1.1   reinoud 	char *s;
    875   1.1   reinoud {
    876   1.1   reinoud 	struct fdc_softc *fdc = (void *)dv->dv_parent;
    877   1.1   reinoud 	char bits[64];
    878   1.1   reinoud 
    879   1.1   reinoud 	if (n == 0) {
    880   1.1   reinoud 		out_fdc(fdc->sc_iot, fdc->sc_ioh, NE7CMD_SENSEI);
    881   1.1   reinoud 		(void) fdcresult(fdc);
    882   1.1   reinoud 		n = 2;
    883   1.1   reinoud 	}
    884   1.1   reinoud 
    885   1.1   reinoud 	printf("%s: %s", dv->dv_xname, s);
    886   1.1   reinoud 
    887   1.1   reinoud 	switch (n) {
    888   1.1   reinoud 	case 0:
    889   1.1   reinoud 		printf("\n");
    890   1.1   reinoud 		break;
    891   1.1   reinoud 	case 2:
    892   1.1   reinoud 		printf(" (st0 %s cyl %d)\n",
    893   1.1   reinoud 		    bitmask_snprintf(fdc->sc_status[0], NE7_ST0BITS,
    894   1.1   reinoud 		    bits, sizeof(bits)), fdc->sc_status[1]);
    895   1.1   reinoud 		break;
    896   1.1   reinoud 	case 7:
    897   1.1   reinoud 		printf(" (st0 %s", bitmask_snprintf(fdc->sc_status[0],
    898   1.1   reinoud 		    NE7_ST0BITS, bits, sizeof(bits)));
    899   1.1   reinoud 		printf(" st1 %s", bitmask_snprintf(fdc->sc_status[1],
    900   1.1   reinoud 		    NE7_ST1BITS, bits, sizeof(bits)));
    901   1.1   reinoud 		printf(" st2 %s", bitmask_snprintf(fdc->sc_status[2],
    902   1.1   reinoud 		    NE7_ST2BITS, bits, sizeof(bits)));
    903   1.1   reinoud 		printf(" cyl %d head %d sec %d)\n",
    904   1.1   reinoud 		    fdc->sc_status[3], fdc->sc_status[4], fdc->sc_status[5]);
    905   1.1   reinoud 		break;
    906   1.1   reinoud #ifdef DIAGNOSTIC
    907   1.1   reinoud 	default:
    908   1.1   reinoud 		printf("\nfdcstatus: weird size");
    909   1.1   reinoud 		break;
    910   1.1   reinoud #endif
    911   1.1   reinoud 	}
    912   1.1   reinoud }
    913   1.1   reinoud 
    914   1.1   reinoud void
    915   1.1   reinoud fdctimeout(arg)
    916   1.1   reinoud 	void *arg;
    917   1.1   reinoud {
    918   1.1   reinoud 	struct fdc_softc *fdc = arg;
    919   1.1   reinoud 	struct fd_softc *fd = fdc->sc_drives.tqh_first;
    920   1.1   reinoud 	int s;
    921   1.1   reinoud 
    922   1.1   reinoud 	s = splbio();
    923   1.1   reinoud #ifdef DEBUG
    924   1.1   reinoud 	log(LOG_ERR,"fdctimeout: state %d\n", fdc->sc_state);
    925   1.1   reinoud #endif
    926   1.1   reinoud 	fdcstatus(&fd->sc_dev, 0, "timeout");
    927   1.1   reinoud 
    928   1.5   hannken 	if (BUFQ_PEEK(&fd->sc_q) != NULL)
    929   1.1   reinoud 		fdc->sc_state++;
    930   1.1   reinoud 	else
    931   1.1   reinoud 		fdc->sc_state = DEVIDLE;
    932   1.1   reinoud 
    933   1.1   reinoud 	(void) fdcintr(fdc);
    934   1.1   reinoud 	splx(s);
    935   1.1   reinoud }
    936   1.1   reinoud 
    937   1.1   reinoud void
    938   1.1   reinoud fdcpseudointr(arg)
    939   1.1   reinoud 	void *arg;
    940   1.1   reinoud {
    941   1.1   reinoud 	int s;
    942   1.1   reinoud 
    943   1.1   reinoud 	/* Just ensure it has the right spl. */
    944   1.1   reinoud 	s = splbio();
    945   1.1   reinoud 	(void) fdcintr(arg);
    946   1.1   reinoud 	splx(s);
    947   1.1   reinoud }
    948   1.1   reinoud 
    949   1.1   reinoud int
    950   1.1   reinoud fdcintr(arg)
    951   1.1   reinoud 	void *arg;
    952   1.1   reinoud {
    953   1.1   reinoud 	struct fdc_softc *fdc = arg;
    954   1.1   reinoud #define	st0	fdc->sc_status[0]
    955   1.1   reinoud #define	cyl	fdc->sc_status[1]
    956   1.1   reinoud 	struct fd_softc *fd;
    957   1.1   reinoud 	struct buf *bp;
    958   1.1   reinoud 	bus_space_tag_t iot = fdc->sc_iot;
    959   1.1   reinoud 	bus_space_handle_t ioh = fdc->sc_ioh;
    960   1.1   reinoud 	int read, head, sec, i, nblks;
    961   1.1   reinoud 	struct fd_type *type;
    962   1.1   reinoud 	struct ne7_fd_formb *finfo = NULL;
    963   1.1   reinoud 
    964   1.1   reinoud loop:
    965   1.1   reinoud 	/* Is there a drive for the controller to do a transfer with? */
    966   1.1   reinoud 	fd = fdc->sc_drives.tqh_first;
    967   1.1   reinoud 	if (fd == NULL) {
    968   1.1   reinoud 		fdc->sc_state = DEVIDLE;
    969   1.1   reinoud  		return 1;
    970   1.1   reinoud 	}
    971   1.1   reinoud 
    972   1.1   reinoud 	/* Is there a transfer to this drive?  If not, deactivate drive. */
    973   1.5   hannken 	bp = BUFQ_PEEK(&fd->sc_q);
    974   1.1   reinoud 	if (bp == NULL) {
    975   1.1   reinoud 		fd->sc_ops = 0;
    976   1.1   reinoud 		TAILQ_REMOVE(&fdc->sc_drives, fd, sc_drivechain);
    977   1.1   reinoud 		fd->sc_active = 0;
    978   1.1   reinoud 		goto loop;
    979   1.1   reinoud 	}
    980   1.1   reinoud 
    981   1.1   reinoud 	if (bp->b_flags & B_FORMAT)
    982   1.1   reinoud 		finfo = (struct ne7_fd_formb *)bp->b_data;
    983   1.1   reinoud 
    984   1.1   reinoud 	switch (fdc->sc_state) {
    985   1.1   reinoud 	case DEVIDLE:
    986   1.1   reinoud 		fdc->sc_errors = 0;
    987   1.1   reinoud 		fd->sc_skip = 0;
    988   1.1   reinoud 		fd->sc_bcount = bp->b_bcount;
    989   1.1   reinoud 		fd->sc_blkno = bp->b_blkno / (FDC_BSIZE / DEV_BSIZE);
    990   1.1   reinoud 		callout_stop(&fd->sc_motoroff_ch);
    991   1.1   reinoud 		if ((fd->sc_flags & FD_MOTOR_WAIT) != 0) {
    992   1.1   reinoud 			fdc->sc_state = MOTORWAIT;
    993   1.1   reinoud 			return 1;
    994   1.1   reinoud 		}
    995   1.1   reinoud 		if ((fd->sc_flags & FD_MOTOR) == 0) {
    996   1.1   reinoud 			/* Turn on the motor, being careful about pairing. */
    997   1.1   reinoud 			struct fd_softc *ofd = fdc->sc_fd[fd->sc_drive ^ 1];
    998   1.1   reinoud 			if (ofd && ofd->sc_flags & FD_MOTOR) {
    999   1.1   reinoud 				callout_stop(&ofd->sc_motoroff_ch);
   1000   1.1   reinoud 				ofd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT);
   1001   1.1   reinoud 			}
   1002   1.1   reinoud 			fd->sc_flags |= FD_MOTOR | FD_MOTOR_WAIT;
   1003   1.1   reinoud 			fd_set_motor(fdc, 0);
   1004   1.1   reinoud 			fdc->sc_state = MOTORWAIT;
   1005   1.1   reinoud 			/* Allow .25s for motor to stabilize. */
   1006   1.1   reinoud 			callout_reset(&fd->sc_motoron_ch, hz / 4,
   1007   1.1   reinoud 			    fd_motor_on, fd);
   1008   1.1   reinoud 			return 1;
   1009   1.1   reinoud 		}
   1010   1.1   reinoud 		/* Make sure the right drive is selected. */
   1011   1.1   reinoud 		fd_set_motor(fdc, 0);
   1012   1.1   reinoud 
   1013   1.1   reinoud 		/* fall through */
   1014   1.1   reinoud 	case DOSEEK:
   1015   1.1   reinoud 	doseek:
   1016   1.1   reinoud 		if (fd->sc_cylin == bp->b_cylinder)
   1017   1.1   reinoud 			goto doio;
   1018   1.1   reinoud 
   1019   1.1   reinoud #if 1
   1020   1.1   reinoud 		out_fdc(iot, ioh, NE7CMD_CONFIGURE);/* configure command */
   1021   1.1   reinoud 		out_fdc(iot, ioh, 0);
   1022   1.1   reinoud 		out_fdc(iot, ioh, 0x18);
   1023   1.1   reinoud 		out_fdc(iot, ioh, 0);
   1024   1.1   reinoud #endif
   1025   1.1   reinoud 		out_fdc(iot, ioh, NE7CMD_SPECIFY);/* specify command */
   1026   1.1   reinoud 		out_fdc(iot, ioh, fd->sc_type->steprate);
   1027   1.1   reinoud 		out_fdc(iot, ioh, 6);		/* XXX head load time == 6ms */
   1028   1.1   reinoud 
   1029   1.1   reinoud 		out_fdc(iot, ioh, NE7CMD_SEEK);	/* seek function */
   1030   1.1   reinoud 		out_fdc(iot, ioh, fd->sc_drive);	/* drive number */
   1031   1.1   reinoud 		out_fdc(iot, ioh, bp->b_cylinder * fd->sc_type->step);
   1032   1.1   reinoud 
   1033   1.1   reinoud 		fd->sc_cylin = -1;
   1034   1.1   reinoud 		fdc->sc_state = SEEKWAIT;
   1035   1.1   reinoud 
   1036   1.1   reinoud 		fd->sc_dk.dk_seek++;
   1037   1.1   reinoud 		disk_busy(&fd->sc_dk);
   1038   1.1   reinoud 
   1039   1.1   reinoud 		callout_reset(&fdc->sc_timo_ch, 4 * hz, fdctimeout, fdc);
   1040   1.1   reinoud 		return 1;
   1041   1.1   reinoud 
   1042   1.1   reinoud 	case DOIO:
   1043   1.1   reinoud 	doio:
   1044   1.1   reinoud 		type = fd->sc_type;
   1045   1.1   reinoud 		if (finfo)
   1046   1.1   reinoud 			fd->sc_skip = (char *)&(finfo->fd_formb_cylno(0)) -
   1047   1.1   reinoud 				      (char *)finfo;
   1048   1.1   reinoud 		sec = fd->sc_blkno % type->seccyl;
   1049   1.1   reinoud 		nblks = type->seccyl - sec;
   1050   1.1   reinoud 		nblks = min(nblks, fd->sc_bcount / FDC_BSIZE);
   1051   1.1   reinoud 		nblks = min(nblks, FDC_MAXIOSIZE / FDC_BSIZE);
   1052   1.1   reinoud 		fd->sc_nblks = nblks;
   1053   1.1   reinoud 		fd->sc_nbytes = finfo ? bp->b_bcount : nblks * FDC_BSIZE;
   1054   1.1   reinoud 		head = sec / type->sectrac;
   1055   1.1   reinoud 		sec -= head * type->sectrac;
   1056   1.1   reinoud #ifdef DIAGNOSTIC
   1057  1.14   thorpej 		{daddr_t  block;
   1058   1.1   reinoud 		 block = (fd->sc_cylin * type->heads + head) * type->sectrac + sec;
   1059   1.1   reinoud 		 if (block != fd->sc_blkno) {
   1060  1.14   thorpej 			 printf("fdcintr: block %" PRId64
   1061  1.14   thorpej 			     " != blkno %" PRId64 "\n",
   1062   1.1   reinoud 				block, fd->sc_blkno);
   1063   1.1   reinoud #ifdef DDB
   1064   1.1   reinoud 			 Debugger();
   1065   1.1   reinoud #endif
   1066   1.1   reinoud 		 }}
   1067   1.1   reinoud #endif
   1068   1.1   reinoud 		read = bp->b_flags & B_READ;
   1069   1.4   thorpej 		if (read) {
   1070   1.4   thorpej 			fdc->sc_fh.fh_func = floppy_read_fiq;
   1071   1.4   thorpej 			fdc->sc_fh.fh_size = floppy_read_fiq_end -
   1072   1.4   thorpej 			    floppy_read_fiq;
   1073   1.4   thorpej 		} else {
   1074   1.4   thorpej 			fdc->sc_fh.fh_func = floppy_write_fiq;
   1075   1.4   thorpej 			fdc->sc_fh.fh_size = floppy_read_fiq_end -
   1076   1.4   thorpej 			    floppy_read_fiq;
   1077   1.4   thorpej 		}
   1078   1.4   thorpej 		fdc->sc_fh.fh_flags = 0;
   1079   1.4   thorpej 		fdc->sc_fh.fh_regs = &fdc->sc_fr;
   1080   1.4   thorpej 		fdc->sc_fr.fr_r9 = IOMD_BASE + (IOMD_FIQRQ << 2);
   1081   1.4   thorpej 		fdc->sc_fr.fr_r10 = fd->sc_nbytes;
   1082   1.4   thorpej 		fdc->sc_fr.fr_r11 = (u_int)(bp->b_data + fd->sc_skip);
   1083   1.4   thorpej 		fdc->sc_fr.fr_r12 = fdc->sc_drq;
   1084   1.1   reinoud #ifdef FD_DEBUG
   1085   1.4   thorpej 		printf("fdc-doio:r9=%x r10=%x r11=%x r12=%x data=%x skip=%x\n",
   1086   1.4   thorpej 		    fdc->sc_fr.fr_r9, fdc->sc_fr.fh_r10, fdc->sc_fr.fh_r11,
   1087   1.4   thorpej 		    fdc->sc_fr.fh_r12, (u_int)bp->b_data, fd->sc_skip);
   1088   1.1   reinoud #endif
   1089   1.4   thorpej 		if (fiq_claim(&fdc->sc_fh) == -1)
   1090   1.7    provos 			panic("%s: Cannot claim FIQ vector", fdc->sc_dev.dv_xname);
   1091   1.4   thorpej 		IOMD_WRITE_BYTE(IOMD_FIQMSK, 0x01);
   1092   1.1   reinoud 		bus_space_write_2(iot, ioh, fdctl, type->rate);
   1093   1.1   reinoud #ifdef FD_DEBUG
   1094   1.1   reinoud 		printf("fdcintr: %s drive %d track %d head %d sec %d nblks %d\n",
   1095   1.1   reinoud 			read ? "read" : "write", fd->sc_drive, fd->sc_cylin,
   1096   1.1   reinoud 			head, sec, nblks);
   1097   1.1   reinoud #endif
   1098   1.1   reinoud 		if (finfo) {
   1099   1.1   reinoud 			/* formatting */
   1100   1.1   reinoud 			if (out_fdc(iot, ioh, NE7CMD_FORMAT) < 0) {
   1101   1.1   reinoud 				fdc->sc_errors = 4;
   1102   1.1   reinoud 				fdcretry(fdc);
   1103   1.1   reinoud 				goto loop;
   1104   1.1   reinoud 			}
   1105   1.1   reinoud 			out_fdc(iot, ioh, (head << 2) | fd->sc_drive);
   1106   1.1   reinoud 			out_fdc(iot, ioh, finfo->fd_formb_secshift);
   1107   1.1   reinoud 			out_fdc(iot, ioh, finfo->fd_formb_nsecs);
   1108   1.1   reinoud 			out_fdc(iot, ioh, finfo->fd_formb_gaplen);
   1109   1.1   reinoud 			out_fdc(iot, ioh, finfo->fd_formb_fillbyte);
   1110   1.1   reinoud 		} else {
   1111   1.1   reinoud 			if (read)
   1112   1.1   reinoud 				out_fdc(iot, ioh, NE7CMD_READ);	/* READ */
   1113   1.1   reinoud 			else
   1114   1.1   reinoud 				out_fdc(iot, ioh, NE7CMD_WRITE); /* WRITE */
   1115   1.1   reinoud 			out_fdc(iot, ioh, (head << 2) | fd->sc_drive);
   1116   1.1   reinoud 			out_fdc(iot, ioh, fd->sc_cylin); /* track */
   1117   1.1   reinoud 			out_fdc(iot, ioh, head);
   1118   1.1   reinoud 			out_fdc(iot, ioh, sec + 1);	 /* sector +1 */
   1119   1.1   reinoud 			out_fdc(iot, ioh, type->secsize);/* sector size */
   1120   1.1   reinoud 			out_fdc(iot, ioh, type->sectrac);/* sectors/track */
   1121   1.1   reinoud 			out_fdc(iot, ioh, type->gap1);	 /* gap1 size */
   1122   1.1   reinoud 			out_fdc(iot, ioh, type->datalen);/* data length */
   1123   1.1   reinoud 		}
   1124   1.1   reinoud 		fdc->sc_state = IOCOMPLETE;
   1125   1.1   reinoud 
   1126   1.1   reinoud 		disk_busy(&fd->sc_dk);
   1127   1.1   reinoud 
   1128   1.1   reinoud 		/* allow 2 seconds for operation */
   1129   1.1   reinoud 		callout_reset(&fdc->sc_timo_ch, 2 * hz, fdctimeout, fdc);
   1130   1.1   reinoud 		return 1;				/* will return later */
   1131   1.1   reinoud 
   1132   1.1   reinoud 	case SEEKWAIT:
   1133   1.1   reinoud 		callout_stop(&fdc->sc_timo_ch);
   1134   1.1   reinoud 		fdc->sc_state = SEEKCOMPLETE;
   1135   1.1   reinoud 		/* allow 1/50 second for heads to settle */
   1136   1.1   reinoud #if 0
   1137   1.1   reinoud 		callout_reset(&fdc->sc_intr_ch, hz / 50, fdcpseudointr, fdc);
   1138   1.1   reinoud #endif
   1139   1.1   reinoud 		return 1;
   1140   1.1   reinoud 
   1141   1.1   reinoud 	case SEEKCOMPLETE:
   1142  1.12       mrg 		/* no data on seek */
   1143  1.12       mrg 		disk_unbusy(&fd->sc_dk, 0, 0);
   1144   1.1   reinoud 
   1145   1.1   reinoud 		/* Make sure seek really happened. */
   1146   1.1   reinoud 		out_fdc(iot, ioh, NE7CMD_SENSEI);
   1147   1.1   reinoud 		if (fdcresult(fdc) != 2 || (st0 & 0xf8) != 0x20 ||
   1148   1.1   reinoud 		    cyl != bp->b_cylinder * fd->sc_type->step) {
   1149   1.1   reinoud #ifdef FD_DEBUG
   1150   1.1   reinoud 			fdcstatus(&fd->sc_dev, 2, "seek failed");
   1151   1.1   reinoud #endif
   1152   1.1   reinoud 			fdcretry(fdc);
   1153   1.1   reinoud 			goto loop;
   1154   1.1   reinoud 		}
   1155   1.1   reinoud 		fd->sc_cylin = bp->b_cylinder;
   1156   1.1   reinoud 		goto doio;
   1157   1.1   reinoud 
   1158   1.1   reinoud 	case IOTIMEDOUT:
   1159   1.4   thorpej 		fiq_release(&fdc->sc_fh);
   1160   1.4   thorpej 		IOMD_WRITE_BYTE(IOMD_FIQMSK, 0x00);
   1161   1.1   reinoud 	case SEEKTIMEDOUT:
   1162   1.1   reinoud 	case RECALTIMEDOUT:
   1163   1.1   reinoud 	case RESETTIMEDOUT:
   1164   1.1   reinoud 		fdcretry(fdc);
   1165   1.1   reinoud 		goto loop;
   1166   1.1   reinoud 
   1167   1.1   reinoud 	case IOCOMPLETE: /* IO DONE, post-analyze */
   1168   1.1   reinoud 		callout_stop(&fdc->sc_timo_ch);
   1169   1.1   reinoud 
   1170  1.12       mrg 		disk_unbusy(&fd->sc_dk, (bp->b_bcount - bp->b_resid),
   1171  1.12       mrg 		    (bp->b_flags & B_READ));
   1172   1.1   reinoud 
   1173   1.1   reinoud 		if (fdcresult(fdc) != 7 || (st0 & 0xf8) != 0) {
   1174   1.4   thorpej 			fiq_release(&fdc->sc_fh);
   1175   1.4   thorpej 			IOMD_WRITE_BYTE(IOMD_FIQMSK, 0x00);
   1176   1.1   reinoud #ifdef FD_DEBUG
   1177   1.1   reinoud 			fdcstatus(&fd->sc_dev, 7, bp->b_flags & B_READ ?
   1178   1.1   reinoud 			    "read failed" : "write failed");
   1179   1.1   reinoud 			printf("blkno %d nblks %d\n",
   1180   1.1   reinoud 			    fd->sc_blkno, fd->sc_nblks);
   1181   1.1   reinoud #endif
   1182   1.1   reinoud 			fdcretry(fdc);
   1183   1.1   reinoud 			goto loop;
   1184   1.1   reinoud 		}
   1185   1.4   thorpej 		fiq_release(&fdc->sc_fh);
   1186   1.4   thorpej 		IOMD_WRITE_BYTE(IOMD_FIQMSK, 0x00);
   1187   1.1   reinoud 		if (fdc->sc_errors) {
   1188   1.1   reinoud #if 0
   1189   1.1   reinoud 			diskerr(bp, "fd", "soft error (corrected)", LOG_PRINTF,
   1190   1.1   reinoud 			    fd->sc_skip / FDC_BSIZE, (struct disklabel *)NULL);
   1191   1.1   reinoud 			printf("\n");
   1192   1.1   reinoud #endif
   1193   1.1   reinoud 			fdc->sc_errors = 0;
   1194   1.1   reinoud 		}
   1195   1.1   reinoud 		fd->sc_blkno += fd->sc_nblks;
   1196   1.1   reinoud 		fd->sc_skip += fd->sc_nbytes;
   1197   1.1   reinoud 		fd->sc_bcount -= fd->sc_nbytes;
   1198   1.1   reinoud 		if (!finfo && fd->sc_bcount > 0) {
   1199   1.1   reinoud 			bp->b_cylinder = fd->sc_blkno / fd->sc_type->seccyl;
   1200   1.1   reinoud 			goto doseek;
   1201   1.1   reinoud 		}
   1202   1.1   reinoud 		fdfinish(fd, bp);
   1203   1.1   reinoud 		goto loop;
   1204   1.1   reinoud 
   1205   1.1   reinoud 	case DORESET:
   1206   1.1   reinoud 		/* try a reset, keep motor on */
   1207   1.1   reinoud 		fd_set_motor(fdc, 1);
   1208   1.1   reinoud 		delay(100);
   1209   1.1   reinoud 		fd_set_motor(fdc, 0);
   1210   1.1   reinoud 		fdc->sc_state = RESETCOMPLETE;
   1211   1.1   reinoud 		callout_reset(&fdc->sc_timo_ch, hz / 2, fdctimeout, fdc);
   1212   1.1   reinoud 		return 1;			/* will return later */
   1213   1.1   reinoud 
   1214   1.1   reinoud 	case RESETCOMPLETE:
   1215   1.1   reinoud 		callout_stop(&fdc->sc_timo_ch);
   1216   1.1   reinoud 		/* clear the controller output buffer */
   1217   1.1   reinoud 		for (i = 0; i < 4; i++) {
   1218   1.1   reinoud 			out_fdc(iot, ioh, NE7CMD_SENSEI);
   1219   1.1   reinoud 			(void) fdcresult(fdc);
   1220   1.1   reinoud 		}
   1221   1.1   reinoud 
   1222   1.1   reinoud 		/* fall through */
   1223   1.1   reinoud 	case DORECAL:
   1224   1.1   reinoud 		out_fdc(iot, ioh, NE7CMD_RECAL);	/* recalibrate function */
   1225   1.1   reinoud 		out_fdc(iot, ioh, fd->sc_drive);
   1226   1.1   reinoud 		fdc->sc_state = RECALWAIT;
   1227   1.1   reinoud 		callout_reset(&fdc->sc_timo_ch, 5 * hz, fdctimeout, fdc);
   1228   1.1   reinoud 		return 1;			/* will return later */
   1229   1.1   reinoud 
   1230   1.1   reinoud 	case RECALWAIT:
   1231   1.1   reinoud 		callout_stop(&fdc->sc_timo_ch);
   1232   1.1   reinoud 		fdc->sc_state = RECALCOMPLETE;
   1233   1.1   reinoud 		/* allow 1/30 second for heads to settle */
   1234   1.1   reinoud #if 0
   1235   1.1   reinoud 		callout_reset(&fdc->sc_intr_ch, hz / 30, fdcpseudointr, fdc);
   1236   1.1   reinoud #endif
   1237   1.1   reinoud 		return 1;			/* will return later */
   1238   1.1   reinoud 
   1239   1.1   reinoud 	case RECALCOMPLETE:
   1240   1.1   reinoud 		out_fdc(iot, ioh, NE7CMD_SENSEI);
   1241   1.1   reinoud 		if (fdcresult(fdc) != 2 || (st0 & 0xf8) != 0x20 || cyl != 0) {
   1242   1.1   reinoud #ifdef FD_DEBUG
   1243   1.1   reinoud 			fdcstatus(&fd->sc_dev, 2, "recalibrate failed");
   1244   1.1   reinoud #endif
   1245   1.1   reinoud 			fdcretry(fdc);
   1246   1.1   reinoud 			goto loop;
   1247   1.1   reinoud 		}
   1248   1.1   reinoud 		fd->sc_cylin = 0;
   1249   1.1   reinoud 		goto doseek;
   1250   1.1   reinoud 
   1251   1.1   reinoud 	case MOTORWAIT:
   1252   1.1   reinoud 		if (fd->sc_flags & FD_MOTOR_WAIT)
   1253   1.1   reinoud 			return 1;		/* time's not up yet */
   1254   1.1   reinoud 		goto doseek;
   1255   1.1   reinoud 
   1256   1.1   reinoud 	default:
   1257   1.1   reinoud 		fdcstatus(&fd->sc_dev, 0, "stray interrupt");
   1258   1.1   reinoud 		return 1;
   1259   1.1   reinoud 	}
   1260   1.1   reinoud #ifdef DIAGNOSTIC
   1261   1.1   reinoud 	panic("fdcintr: impossible");
   1262   1.1   reinoud #endif
   1263   1.1   reinoud #undef	st0
   1264   1.1   reinoud #undef	cyl
   1265   1.1   reinoud }
   1266   1.1   reinoud 
   1267   1.1   reinoud void
   1268   1.1   reinoud fdcretry(fdc)
   1269   1.1   reinoud 	struct fdc_softc *fdc;
   1270   1.1   reinoud {
   1271   1.1   reinoud 	char bits[64];
   1272   1.1   reinoud 	struct fd_softc *fd;
   1273   1.1   reinoud 	struct buf *bp;
   1274   1.1   reinoud 
   1275   1.1   reinoud 	fd = fdc->sc_drives.tqh_first;
   1276   1.5   hannken 	bp = BUFQ_PEEK(&fd->sc_q);
   1277   1.1   reinoud 
   1278   1.1   reinoud 	if (fd->sc_opts & FDOPT_NORETRY)
   1279   1.1   reinoud 	    goto fail;
   1280   1.1   reinoud 	switch (fdc->sc_errors) {
   1281   1.1   reinoud 	case 0:
   1282   1.1   reinoud 		/* try again */
   1283   1.1   reinoud 		fdc->sc_state = DOSEEK;
   1284   1.1   reinoud 		break;
   1285   1.1   reinoud 
   1286   1.1   reinoud 	case 1: case 2: case 3:
   1287   1.1   reinoud 		/* didn't work; try recalibrating */
   1288   1.1   reinoud 		fdc->sc_state = DORECAL;
   1289   1.1   reinoud 		break;
   1290   1.1   reinoud 
   1291   1.1   reinoud 	case 4:
   1292   1.1   reinoud 		/* still no go; reset the bastard */
   1293   1.1   reinoud 		fdc->sc_state = DORESET;
   1294   1.1   reinoud 		break;
   1295   1.1   reinoud 
   1296   1.1   reinoud 	default:
   1297   1.1   reinoud 	fail:
   1298   1.1   reinoud 		if ((fd->sc_opts & FDOPT_SILENT) == 0) {
   1299   1.1   reinoud 			diskerr(bp, "fd", "hard error", LOG_PRINTF,
   1300   1.1   reinoud 				fd->sc_skip / FDC_BSIZE,
   1301   1.1   reinoud 				(struct disklabel *)NULL);
   1302   1.1   reinoud 
   1303   1.1   reinoud 			printf(" (st0 %s",
   1304   1.1   reinoud 			       bitmask_snprintf(fdc->sc_status[0],
   1305   1.1   reinoud 						NE7_ST0BITS, bits,
   1306   1.1   reinoud 						sizeof(bits)));
   1307   1.1   reinoud 			printf(" st1 %s",
   1308   1.1   reinoud 			       bitmask_snprintf(fdc->sc_status[1],
   1309   1.1   reinoud 						NE7_ST1BITS, bits,
   1310   1.1   reinoud 						sizeof(bits)));
   1311   1.1   reinoud 			printf(" st2 %s",
   1312   1.1   reinoud 			       bitmask_snprintf(fdc->sc_status[2],
   1313   1.1   reinoud 						NE7_ST2BITS, bits,
   1314   1.1   reinoud 						sizeof(bits)));
   1315   1.1   reinoud 			printf(" cyl %d head %d sec %d)\n",
   1316   1.1   reinoud 			       fdc->sc_status[3],
   1317   1.1   reinoud 			       fdc->sc_status[4],
   1318   1.1   reinoud 			       fdc->sc_status[5]);
   1319   1.1   reinoud 		}
   1320   1.1   reinoud 
   1321   1.1   reinoud 		bp->b_flags |= B_ERROR;
   1322   1.1   reinoud 		bp->b_error = EIO;
   1323   1.1   reinoud 		fdfinish(fd, bp);
   1324   1.1   reinoud 	}
   1325   1.1   reinoud 	fdc->sc_errors++;
   1326   1.1   reinoud }
   1327   1.1   reinoud 
   1328   1.1   reinoud int
   1329   1.1   reinoud fdioctl(dev, cmd, addr, flag, p)
   1330   1.1   reinoud 	dev_t dev;
   1331   1.1   reinoud 	u_long cmd;
   1332   1.1   reinoud 	caddr_t addr;
   1333   1.1   reinoud 	int flag;
   1334   1.1   reinoud 	struct proc *p;
   1335   1.1   reinoud {
   1336   1.1   reinoud 	struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
   1337   1.1   reinoud 	struct fdformat_parms *form_parms;
   1338   1.1   reinoud 	struct fdformat_cmd *form_cmd;
   1339   1.1   reinoud 	struct ne7_fd_formb *fd_formb;
   1340   1.1   reinoud 	struct disklabel buffer;
   1341   1.1   reinoud 	int error;
   1342   1.1   reinoud 	unsigned int scratch;
   1343   1.1   reinoud 	int il[FD_MAX_NSEC + 1];
   1344   1.1   reinoud 	register int i, j;
   1345   1.1   reinoud 
   1346   1.1   reinoud 	switch (cmd) {
   1347   1.1   reinoud 	case DIOCGDINFO:
   1348   1.1   reinoud 		memset(&buffer, 0, sizeof(buffer));
   1349   1.1   reinoud 
   1350   1.1   reinoud 		buffer.d_secpercyl = fd->sc_type->seccyl;
   1351   1.1   reinoud 		buffer.d_type = DTYPE_FLOPPY;
   1352   1.1   reinoud 		buffer.d_secsize = FDC_BSIZE;
   1353   1.1   reinoud 
   1354   1.1   reinoud 		if (readdisklabel(dev, fdstrategy, &buffer, NULL) != NULL)
   1355   1.1   reinoud 			return EINVAL;
   1356   1.1   reinoud 
   1357   1.1   reinoud 		*(struct disklabel *)addr = buffer;
   1358   1.1   reinoud 		return 0;
   1359   1.1   reinoud 
   1360   1.1   reinoud 	case DIOCWLABEL:
   1361   1.1   reinoud 		if ((flag & FWRITE) == 0)
   1362   1.1   reinoud 			return EBADF;
   1363   1.1   reinoud 		/* XXX do something */
   1364   1.1   reinoud 		return 0;
   1365   1.1   reinoud 
   1366   1.1   reinoud 	case DIOCWDINFO:
   1367   1.1   reinoud 		if ((flag & FWRITE) == 0)
   1368   1.1   reinoud 			return EBADF;
   1369   1.1   reinoud 
   1370   1.1   reinoud 		error = setdisklabel(&buffer, (struct disklabel *)addr, 0, NULL);
   1371   1.1   reinoud 		if (error)
   1372   1.1   reinoud 			return error;
   1373   1.1   reinoud 
   1374   1.1   reinoud 		error = writedisklabel(dev, fdstrategy, &buffer, NULL);
   1375   1.1   reinoud 		return error;
   1376   1.1   reinoud 
   1377   1.1   reinoud 	case FDIOCGETFORMAT:
   1378   1.1   reinoud 		form_parms = (struct fdformat_parms *)addr;
   1379   1.1   reinoud 		form_parms->fdformat_version = FDFORMAT_VERSION;
   1380   1.1   reinoud 		form_parms->nbps = 128 * (1 << fd->sc_type->secsize);
   1381   1.1   reinoud 		form_parms->ncyl = fd->sc_type->cyls;
   1382   1.1   reinoud 		form_parms->nspt = fd->sc_type->sectrac;
   1383   1.1   reinoud 		form_parms->ntrk = fd->sc_type->heads;
   1384   1.1   reinoud 		form_parms->stepspercyl = fd->sc_type->step;
   1385   1.1   reinoud 		form_parms->gaplen = fd->sc_type->gap2;
   1386   1.1   reinoud 		form_parms->fillbyte = fd->sc_type->fillbyte;
   1387   1.1   reinoud 		form_parms->interleave = fd->sc_type->interleave;
   1388   1.1   reinoud 		switch (fd->sc_type->rate) {
   1389   1.1   reinoud 		case FDC_500KBPS:
   1390   1.1   reinoud 			form_parms->xfer_rate = 500 * 1024;
   1391   1.1   reinoud 			break;
   1392   1.1   reinoud 		case FDC_300KBPS:
   1393   1.1   reinoud 			form_parms->xfer_rate = 300 * 1024;
   1394   1.1   reinoud 			break;
   1395   1.1   reinoud 		case FDC_250KBPS:
   1396   1.1   reinoud 			form_parms->xfer_rate = 250 * 1024;
   1397   1.1   reinoud 			break;
   1398   1.1   reinoud 		default:
   1399   1.1   reinoud 			return EINVAL;
   1400   1.1   reinoud 		}
   1401   1.1   reinoud 		return 0;
   1402   1.1   reinoud 
   1403   1.1   reinoud 	case FDIOCSETFORMAT:
   1404   1.1   reinoud 		if((flag & FWRITE) == 0)
   1405   1.1   reinoud 			return EBADF;	/* must be opened for writing */
   1406   1.1   reinoud 		form_parms = (struct fdformat_parms *)addr;
   1407   1.1   reinoud 		if (form_parms->fdformat_version != FDFORMAT_VERSION)
   1408   1.1   reinoud 			return EINVAL;	/* wrong version of formatting prog */
   1409   1.1   reinoud 
   1410   1.1   reinoud 		scratch = form_parms->nbps >> 7;
   1411   1.1   reinoud 		if ((form_parms->nbps & 0x7f) || ffs(scratch) == 0 ||
   1412   1.1   reinoud 		    scratch & ~(1 << (ffs(scratch)-1)))
   1413   1.1   reinoud 			/* not a power-of-two multiple of 128 */
   1414   1.1   reinoud 			return EINVAL;
   1415   1.1   reinoud 
   1416   1.1   reinoud 		switch (form_parms->xfer_rate) {
   1417   1.1   reinoud 		case 500 * 1024:
   1418   1.1   reinoud 			fd->sc_type->rate = FDC_500KBPS;
   1419   1.1   reinoud 			break;
   1420   1.1   reinoud 		case 300 * 1024:
   1421   1.1   reinoud 			fd->sc_type->rate = FDC_300KBPS;
   1422   1.1   reinoud 			break;
   1423   1.1   reinoud 		case 250 * 1024:
   1424   1.1   reinoud 			fd->sc_type->rate = FDC_250KBPS;
   1425   1.1   reinoud 			break;
   1426   1.1   reinoud 		default:
   1427   1.1   reinoud 			return EINVAL;
   1428   1.1   reinoud 		}
   1429   1.1   reinoud 
   1430   1.1   reinoud 		if (form_parms->nspt > FD_MAX_NSEC ||
   1431   1.1   reinoud 		    form_parms->fillbyte > 0xff ||
   1432   1.1   reinoud 		    form_parms->interleave > 0xff)
   1433   1.1   reinoud 			return EINVAL;
   1434   1.1   reinoud 		fd->sc_type->sectrac = form_parms->nspt;
   1435   1.1   reinoud 		if (form_parms->ntrk != 2 && form_parms->ntrk != 1)
   1436   1.1   reinoud 			return EINVAL;
   1437   1.1   reinoud 		fd->sc_type->heads = form_parms->ntrk;
   1438   1.1   reinoud 		fd->sc_type->seccyl = form_parms->nspt * form_parms->ntrk;
   1439   1.1   reinoud 		fd->sc_type->secsize = ffs(scratch)-1;
   1440   1.1   reinoud 		fd->sc_type->gap2 = form_parms->gaplen;
   1441   1.1   reinoud 		fd->sc_type->cyls = form_parms->ncyl;
   1442   1.1   reinoud 		fd->sc_type->size = fd->sc_type->seccyl * form_parms->ncyl *
   1443   1.1   reinoud 			form_parms->nbps / DEV_BSIZE;
   1444   1.1   reinoud 		fd->sc_type->step = form_parms->stepspercyl;
   1445   1.1   reinoud 		fd->sc_type->fillbyte = form_parms->fillbyte;
   1446   1.1   reinoud 		fd->sc_type->interleave = form_parms->interleave;
   1447   1.1   reinoud 		return 0;
   1448   1.1   reinoud 
   1449   1.1   reinoud 	case FDIOCFORMAT_TRACK:
   1450   1.1   reinoud 		if((flag & FWRITE) == 0)
   1451   1.1   reinoud 			return EBADF;	/* must be opened for writing */
   1452   1.1   reinoud 		form_cmd = (struct fdformat_cmd *)addr;
   1453   1.1   reinoud 		if (form_cmd->formatcmd_version != FDFORMAT_VERSION)
   1454   1.1   reinoud 			return EINVAL;	/* wrong version of formatting prog */
   1455   1.1   reinoud 
   1456   1.1   reinoud 		if (form_cmd->head >= fd->sc_type->heads ||
   1457   1.1   reinoud 		    form_cmd->cylinder >= fd->sc_type->cyls) {
   1458   1.1   reinoud 			return EINVAL;
   1459   1.1   reinoud 		}
   1460   1.1   reinoud 
   1461   1.1   reinoud 		fd_formb = malloc(sizeof(struct ne7_fd_formb),
   1462   1.1   reinoud 		    M_TEMP, M_NOWAIT);
   1463   1.1   reinoud 		if(fd_formb == 0)
   1464   1.1   reinoud 			return ENOMEM;
   1465   1.1   reinoud 
   1466   1.1   reinoud 
   1467   1.1   reinoud 		fd_formb->head = form_cmd->head;
   1468   1.1   reinoud 		fd_formb->cyl = form_cmd->cylinder;
   1469   1.1   reinoud 		fd_formb->transfer_rate = fd->sc_type->rate;
   1470   1.1   reinoud 		fd_formb->fd_formb_secshift = fd->sc_type->secsize;
   1471   1.1   reinoud 		fd_formb->fd_formb_nsecs = fd->sc_type->sectrac;
   1472   1.1   reinoud 		fd_formb->fd_formb_gaplen = fd->sc_type->gap2;
   1473   1.1   reinoud 		fd_formb->fd_formb_fillbyte = fd->sc_type->fillbyte;
   1474   1.1   reinoud 
   1475   1.1   reinoud 		memset(il, 0, sizeof il);
   1476   1.1   reinoud 		for (j = 0, i = 1; i <= fd_formb->fd_formb_nsecs; i++) {
   1477   1.1   reinoud 			while (il[(j%fd_formb->fd_formb_nsecs)+1])
   1478   1.1   reinoud 				j++;
   1479   1.1   reinoud 			il[(j%fd_formb->fd_formb_nsecs)+1] = i;
   1480   1.1   reinoud 			j += fd->sc_type->interleave;
   1481   1.1   reinoud 		}
   1482   1.1   reinoud 		for (i = 0; i < fd_formb->fd_formb_nsecs; i++) {
   1483   1.1   reinoud 			fd_formb->fd_formb_cylno(i) = form_cmd->cylinder;
   1484   1.1   reinoud 			fd_formb->fd_formb_headno(i) = form_cmd->head;
   1485   1.1   reinoud 			fd_formb->fd_formb_secno(i) = il[i+1];
   1486   1.1   reinoud 			fd_formb->fd_formb_secsize(i) = fd->sc_type->secsize;
   1487   1.1   reinoud 		}
   1488   1.1   reinoud 
   1489   1.1   reinoud 		error = fdformat(dev, fd_formb, p);
   1490   1.1   reinoud 		free(fd_formb, M_TEMP);
   1491   1.1   reinoud 		return error;
   1492   1.1   reinoud 
   1493   1.1   reinoud 	case FDIOCGETOPTS:		/* get drive options */
   1494   1.1   reinoud 		*(int *)addr = fd->sc_opts;
   1495   1.1   reinoud 		return 0;
   1496   1.1   reinoud 
   1497   1.1   reinoud 	case FDIOCSETOPTS:		/* set drive options */
   1498   1.1   reinoud 		fd->sc_opts = *(int *)addr;
   1499   1.1   reinoud 		return 0;
   1500   1.1   reinoud 
   1501   1.1   reinoud 	default:
   1502   1.1   reinoud 		return ENOTTY;
   1503   1.1   reinoud 	}
   1504   1.1   reinoud 
   1505   1.1   reinoud #ifdef DIAGNOSTIC
   1506   1.1   reinoud 	panic("fdioctl: impossible");
   1507   1.1   reinoud #endif
   1508   1.1   reinoud }
   1509   1.1   reinoud 
   1510   1.1   reinoud int
   1511   1.1   reinoud fdformat(dev, finfo, p)
   1512   1.1   reinoud 	dev_t dev;
   1513   1.1   reinoud 	struct ne7_fd_formb *finfo;
   1514   1.1   reinoud 	struct proc *p;
   1515   1.1   reinoud {
   1516   1.1   reinoud 	int rv = 0, s;
   1517   1.1   reinoud 	struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
   1518   1.1   reinoud 	struct fd_type *type = fd->sc_type;
   1519   1.1   reinoud 	struct buf *bp;
   1520   1.1   reinoud 
   1521   1.1   reinoud 	/* set up a buffer header for fdstrategy() */
   1522   1.1   reinoud 	bp = (struct buf *)malloc(sizeof(struct buf), M_TEMP, M_NOWAIT);
   1523   1.1   reinoud 	if(bp == 0)
   1524   1.1   reinoud 		return ENOBUFS;
   1525   1.1   reinoud 	memset((void *)bp, 0, sizeof(struct buf));
   1526   1.1   reinoud 	bp->b_flags = B_BUSY | B_PHYS | B_FORMAT;
   1527   1.1   reinoud 	bp->b_proc = p;
   1528   1.1   reinoud 	bp->b_dev = dev;
   1529   1.1   reinoud 
   1530   1.1   reinoud 	/*
   1531   1.1   reinoud 	 * calculate a fake blkno, so fdstrategy() would initiate a
   1532   1.1   reinoud 	 * seek to the requested cylinder
   1533   1.1   reinoud 	 */
   1534   1.1   reinoud 	bp->b_blkno = (finfo->cyl * (type->sectrac * type->heads)
   1535   1.1   reinoud 		       + finfo->head * type->sectrac) * FDC_BSIZE / DEV_BSIZE;
   1536   1.1   reinoud 
   1537   1.1   reinoud 	bp->b_bcount = sizeof(struct fd_idfield_data) * finfo->fd_formb_nsecs;
   1538   1.1   reinoud 	bp->b_data = (caddr_t)finfo;
   1539   1.1   reinoud 
   1540   1.1   reinoud #ifdef DEBUG
   1541  1.15     bjh21 	printf("fdformat: blkno %llx count %lx\n",
   1542  1.15     bjh21 	    (unsigned long long)bp->b_blkno, bp->b_bcount);
   1543   1.1   reinoud #endif
   1544   1.1   reinoud 
   1545   1.1   reinoud 	/* now do the format */
   1546   1.1   reinoud 	fdstrategy(bp);
   1547   1.1   reinoud 
   1548   1.1   reinoud 	/* ...and wait for it to complete */
   1549   1.1   reinoud 	s = splbio();
   1550   1.1   reinoud 	while(!(bp->b_flags & B_DONE)) {
   1551   1.1   reinoud 		rv = tsleep((caddr_t)bp, PRIBIO, "fdform", 20 * hz);
   1552   1.1   reinoud 		if (rv == EWOULDBLOCK)
   1553   1.1   reinoud 			break;
   1554   1.1   reinoud 	}
   1555   1.1   reinoud 	splx(s);
   1556   1.1   reinoud 
   1557   1.1   reinoud 	if (rv == EWOULDBLOCK) {
   1558   1.1   reinoud 		/* timed out */
   1559   1.1   reinoud 		rv = EIO;
   1560   1.1   reinoud 		biodone(bp);
   1561   1.1   reinoud 	}
   1562   1.1   reinoud 	if(bp->b_flags & B_ERROR) {
   1563   1.1   reinoud 		rv = bp->b_error;
   1564   1.1   reinoud 	}
   1565   1.1   reinoud 	free(bp, M_TEMP);
   1566   1.1   reinoud 	return rv;
   1567   1.1   reinoud }
   1568   1.1   reinoud 
   1569   1.1   reinoud #include "md.h"
   1570   1.1   reinoud #if NMD > 0
   1571   1.1   reinoud 
   1572   1.1   reinoud #include <dev/md.h>
   1573   1.1   reinoud 
   1574   1.1   reinoud int load_memory_disc_from_floppy __P((struct md_conf *md, dev_t dev));
   1575   1.1   reinoud 
   1576   1.1   reinoud int
   1577   1.1   reinoud load_memory_disc_from_floppy(md, dev)
   1578   1.1   reinoud 	struct md_conf *md;
   1579   1.1   reinoud 	dev_t dev;
   1580   1.1   reinoud {
   1581   1.1   reinoud 	struct buf *bp;
   1582   1.1   reinoud 	int loop;
   1583   1.1   reinoud 	int s;
   1584   1.1   reinoud 	int type;
   1585   1.1   reinoud 	int floppysize;
   1586   1.1   reinoud 
   1587   1.6   gehenna 	if (bdevsw_lookup(dev) != &fd_bdevsw)
   1588   1.1   reinoud 		return(EINVAL);
   1589   1.1   reinoud 
   1590   1.1   reinoud 	if (md->md_type == MD_UNCONFIGURED || md->md_addr == 0)
   1591   1.1   reinoud 		return(EBUSY);
   1592   1.1   reinoud 
   1593   1.1   reinoud 	type = FDTYPE(dev) - 1;
   1594   1.1   reinoud 	if (type < 0) type = 0;
   1595   1.1   reinoud 	floppysize = fd_types[type].size << (fd_types[type].secsize + 7);
   1596   1.1   reinoud 
   1597   1.1   reinoud 	if (md->md_size < floppysize) {
   1598   1.1   reinoud 		printf("Memory disc is not big enough for floppy image\n");
   1599   1.1   reinoud 		return(EINVAL);
   1600   1.1   reinoud 	}
   1601   1.1   reinoud 
   1602   1.1   reinoud /* We have the memory disk ! */
   1603   1.1   reinoud 
   1604   1.1   reinoud 	printf("Loading memory disc : %4dK ", 0);
   1605   1.1   reinoud 
   1606   1.1   reinoud /* obtain a buffer */
   1607   1.1   reinoud 
   1608   1.1   reinoud 	bp = geteblk(fd_types[type].sectrac * DEV_BSIZE);
   1609   1.1   reinoud 
   1610   1.1   reinoud /* request no partition relocation by driver on I/O operations */
   1611   1.1   reinoud 
   1612   1.1   reinoud 	bp->b_dev = dev;
   1613   1.1   reinoud 
   1614   1.1   reinoud 	s = spl0();
   1615   1.1   reinoud 
   1616   1.1   reinoud 	if (fdopen(bp->b_dev, 0, 0, curproc) != 0) {
   1617   1.1   reinoud 		brelse(bp);
   1618   1.1   reinoud 		printf("Cannot open floppy device\n");
   1619   1.1   reinoud 			return(EINVAL);
   1620   1.1   reinoud 	}
   1621   1.1   reinoud 
   1622   1.1   reinoud 	for (loop = 0;
   1623   1.1   reinoud 	    loop < (floppysize / DEV_BSIZE / fd_types[type].sectrac);
   1624   1.1   reinoud 	    ++loop) {
   1625   1.1   reinoud 		printf("\x08\x08\x08\x08\x08\x08%4dK ",
   1626   1.1   reinoud 		    loop * fd_types[type].sectrac * DEV_BSIZE / 1024);
   1627   1.1   reinoud 		bp->b_blkno = loop * fd_types[type].sectrac;
   1628   1.1   reinoud 		bp->b_bcount = fd_types[type].sectrac * DEV_BSIZE;
   1629   1.1   reinoud 		bp->b_flags |= B_READ;
   1630   1.1   reinoud 		bp->b_error = 0;
   1631   1.1   reinoud 		bp->b_resid = 0;
   1632   1.1   reinoud 		fdstrategy(bp);
   1633   1.1   reinoud 
   1634   1.1   reinoud 		if (biowait(bp))
   1635   1.7    provos 			panic("Cannot load floppy image");
   1636   1.1   reinoud 
   1637   1.1   reinoud 		memcpy((caddr_t)md->md_addr + loop * fd_types[type].sectrac
   1638   1.1   reinoud 		    * DEV_BSIZE, (caddr_t)bp->b_data,
   1639   1.1   reinoud 		    fd_types[type].sectrac * DEV_BSIZE);
   1640   1.1   reinoud 	}
   1641   1.1   reinoud 	printf("\x08\x08\x08\x08\x08\x08%4dK done\n",
   1642   1.1   reinoud 	    loop * fd_types[type].sectrac * DEV_BSIZE / 1024);
   1643   1.1   reinoud 
   1644   1.1   reinoud 	fdclose(bp->b_dev, 0, 0, curproc);
   1645   1.1   reinoud 
   1646   1.1   reinoud 	brelse(bp);
   1647   1.1   reinoud 
   1648   1.1   reinoud 	splx(s);
   1649   1.1   reinoud 	return(0);
   1650   1.1   reinoud }
   1651   1.1   reinoud 
   1652   1.1   reinoud #endif
   1653