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