xref: /freebsd/sys/dev/fdc/fdc.c (revision f5f7ba035f043e44c70bcf4b5c6cd2e02d3c6791)
15b81b6b3SRodney W. Grimes /*#define DEBUG 1*/
25b81b6b3SRodney W. Grimes /*-
35b81b6b3SRodney W. Grimes  * Copyright (c) 1990 The Regents of the University of California.
45b81b6b3SRodney W. Grimes  * All rights reserved.
55b81b6b3SRodney W. Grimes  *
65b81b6b3SRodney W. Grimes  * This code is derived from software contributed to Berkeley by
75b81b6b3SRodney W. Grimes  * Don Ahn.
85b81b6b3SRodney W. Grimes  *
95b81b6b3SRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
105b81b6b3SRodney W. Grimes  * modification, are permitted provided that the following conditions
115b81b6b3SRodney W. Grimes  * are met:
125b81b6b3SRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
135b81b6b3SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
145b81b6b3SRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
155b81b6b3SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
165b81b6b3SRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
175b81b6b3SRodney W. Grimes  * 3. All advertising materials mentioning features or use of this software
185b81b6b3SRodney W. Grimes  *    must display the following acknowledgement:
195b81b6b3SRodney W. Grimes  *	This product includes software developed by the University of
205b81b6b3SRodney W. Grimes  *	California, Berkeley and its contributors.
215b81b6b3SRodney W. Grimes  * 4. Neither the name of the University nor the names of its contributors
225b81b6b3SRodney W. Grimes  *    may be used to endorse or promote products derived from this software
235b81b6b3SRodney W. Grimes  *    without specific prior written permission.
245b81b6b3SRodney W. Grimes  *
255b81b6b3SRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
265b81b6b3SRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
275b81b6b3SRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
285b81b6b3SRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
295b81b6b3SRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
305b81b6b3SRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
315b81b6b3SRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
325b81b6b3SRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
335b81b6b3SRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
345b81b6b3SRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
355b81b6b3SRodney W. Grimes  * SUCH DAMAGE.
365b81b6b3SRodney W. Grimes  *
375b81b6b3SRodney W. Grimes  *	@(#)fd.c	7.4 (Berkeley) 5/25/91
385b81b6b3SRodney W. Grimes  *
395b81b6b3SRodney W. Grimes  * PATCHES MAGIC                LEVEL   PATCH THAT GOT US HERE
405b81b6b3SRodney W. Grimes  * --------------------         -----   ----------------------
415b81b6b3SRodney W. Grimes  * CURRENT PATCH LEVEL:         1       00153
425b81b6b3SRodney W. Grimes  * --------------------         -----   ----------------------
435b81b6b3SRodney W. Grimes  *
445b81b6b3SRodney W. Grimes  * 20 Apr 93	Julian Elischer		Heavily re worked, see notes below
455b81b6b3SRodney W. Grimes  *
465b81b6b3SRodney W. Grimes  * Largely rewritten to handle multiple controllers and drives
475b81b6b3SRodney W. Grimes  * By Julian Elischer, Sun Apr  4 16:34:33 WST 1993
485b81b6b3SRodney W. Grimes  */
49f5f7ba03SJordan K. Hubbard char	rev[] = "$Revision: 1.3 $";
505b81b6b3SRodney W. Grimes /*
51f5f7ba03SJordan K. Hubbard  * $Header: /a/cvs/386BSD/src/sys/i386/isa/fd.c,v 1.3 1993/08/12 09:21:20 rgrimes Exp $
525b81b6b3SRodney W. Grimes  */
535b81b6b3SRodney W. Grimes /*
545b81b6b3SRodney W. Grimes  * $Log: fd.c,v $
55f5f7ba03SJordan K. Hubbard  * Revision 1.3  1993/08/12  09:21:20  rgrimes
56f5f7ba03SJordan K. Hubbard  * Fixed poor timeout code in out_fdc.  The timeout counter was not being
57f5f7ba03SJordan K. Hubbard  * reinitialized between while loops.  Added comments about what was going
58f5f7ba03SJordan K. Hubbard  * on in the out_fdc routine.
59f5f7ba03SJordan K. Hubbard  *
60f5f7ba03SJordan K. Hubbard  * out_fdc now returns if the direction bit is not set in time instead of
61f5f7ba03SJordan K. Hubbard  * trying to wait for MRQ to get cleared.
62f5f7ba03SJordan K. Hubbard  *
633b3837dbSRodney W. Grimes  * Revision 1.2  1993/07/15  17:53:04  davidg
643b3837dbSRodney W. Grimes  * Modified attach printf's so that the output is compatible with the "new"
653b3837dbSRodney W. Grimes  * way of doing things. There still remain several drivers that need to
663b3837dbSRodney W. Grimes  * be updated.  Also added a compile-time option to pccons to switch the
673b3837dbSRodney W. Grimes  * control and caps-lock keys (REVERSE_CAPS_CTRL) - added for my personal
683b3837dbSRodney W. Grimes  * sanity.
693b3837dbSRodney W. Grimes  *
702a6c8980SDavid Greenman  * Revision 1.1.1.1  1993/06/12  14:58:02  rgrimes
712a6c8980SDavid Greenman  * Initial import, 0.1 + pk 0.2.4-B1
722a6c8980SDavid Greenman  *
735b81b6b3SRodney W. Grimes  * Revision 1.10  93/04/13  16:53:29  root
745b81b6b3SRodney W. Grimes  * make sure turning off a drive motor doesn't deselect another
755b81b6b3SRodney W. Grimes  * drive active at the time.
765b81b6b3SRodney W. Grimes  * Also added a pointer from the fd_data to it's fd_type.
775b81b6b3SRodney W. Grimes  *
785b81b6b3SRodney W. Grimes  * Revision 1.9  93/04/13  15:31:02  root
795b81b6b3SRodney W. Grimes  * make all seeks go through DOSEEK state so are sure of being done right.
805b81b6b3SRodney W. Grimes  *
815b81b6b3SRodney W. Grimes  * Revision 1.8  93/04/12  21:20:13  root
825b81b6b3SRodney W. Grimes  * only check if old fd is the one we are working on if there IS
835b81b6b3SRodney W. Grimes  * an old fd pointer. (in fdstate())
845b81b6b3SRodney W. Grimes  *
855b81b6b3SRodney W. Grimes  * Revision 1.7  93/04/11  17:05:35  root
865b81b6b3SRodney W. Grimes  * cleanup timeouts etc.
875b81b6b3SRodney W. Grimes  * also fix bug to select teh correct drive when running > 1 drive
885b81b6b3SRodney W. Grimes  * at a time.
895b81b6b3SRodney W. Grimes  *
905b81b6b3SRodney W. Grimes  * Revision 1.6  93/04/05  00:48:45  root
915b81b6b3SRodney W. Grimes  * change a timeout and add version to banner message
925b81b6b3SRodney W. Grimes  *
935b81b6b3SRodney W. Grimes  * Revision 1.5  93/04/04  16:39:08  root
945b81b6b3SRodney W. Grimes  * first working version.. some floppy controllers don't seem to
955b81b6b3SRodney W. Grimes  * like 2 int. status inquiries in a row.
965b81b6b3SRodney W. Grimes  *
975b81b6b3SRodney W. Grimes  */
985b81b6b3SRodney W. Grimes 
995b81b6b3SRodney W. Grimes #include "fd.h"
1005b81b6b3SRodney W. Grimes #if NFD > 0
1015b81b6b3SRodney W. Grimes 
1025b81b6b3SRodney W. Grimes #include "param.h"
1035b81b6b3SRodney W. Grimes #include "dkbad.h"
1045b81b6b3SRodney W. Grimes #include "systm.h"
1055b81b6b3SRodney W. Grimes #include "conf.h"
1065b81b6b3SRodney W. Grimes #include "file.h"
1075b81b6b3SRodney W. Grimes #include "ioctl.h"
108f5f7ba03SJordan K. Hubbard #include "disklabel.h"
1095b81b6b3SRodney W. Grimes #include "buf.h"
1105b81b6b3SRodney W. Grimes #include "uio.h"
1115b81b6b3SRodney W. Grimes #include "i386/isa/isa.h"
1125b81b6b3SRodney W. Grimes #include "i386/isa/isa_device.h"
1135b81b6b3SRodney W. Grimes #include "i386/isa/fdreg.h"
1145b81b6b3SRodney W. Grimes #include "i386/isa/icu.h"
1155b81b6b3SRodney W. Grimes #include "i386/isa/rtc.h"
1165b81b6b3SRodney W. Grimes #undef NFD
1175b81b6b3SRodney W. Grimes #define NFD 2
1185b81b6b3SRodney W. Grimes 
1195b81b6b3SRodney W. Grimes #define	FDUNIT(s)	((s>>3)&1)
1205b81b6b3SRodney W. Grimes #define	FDTYPE(s)	((s)&7)
1215b81b6b3SRodney W. Grimes 
1225b81b6b3SRodney W. Grimes #define b_cylin b_resid
1235b81b6b3SRodney W. Grimes #define FDBLK 512
1245b81b6b3SRodney W. Grimes #define NUMTYPES 4
1255b81b6b3SRodney W. Grimes 
1265b81b6b3SRodney W. Grimes struct fd_type {
1275b81b6b3SRodney W. Grimes 	int	sectrac;		/* sectors per track         */
1285b81b6b3SRodney W. Grimes 	int	secsize;		/* size code for sectors     */
1295b81b6b3SRodney W. Grimes 	int	datalen;		/* data len when secsize = 0 */
1305b81b6b3SRodney W. Grimes 	int	gap;			/* gap len between sectors   */
1315b81b6b3SRodney W. Grimes 	int	tracks;			/* total num of tracks       */
1325b81b6b3SRodney W. Grimes 	int	size;			/* size of disk in sectors   */
1335b81b6b3SRodney W. Grimes 	int	steptrac;		/* steps per cylinder        */
1345b81b6b3SRodney W. Grimes 	int	trans;			/* transfer speed code       */
1355b81b6b3SRodney W. Grimes 	int	heads;			/* number of heads	     */
1365b81b6b3SRodney W. Grimes };
1375b81b6b3SRodney W. Grimes 
1385b81b6b3SRodney W. Grimes struct fd_type fd_types[NUMTYPES] =
1395b81b6b3SRodney W. Grimes {
1405b81b6b3SRodney W. Grimes  	{ 18,2,0xFF,0x1B,80,2880,1,0,2 }, /* 1.44 meg HD 3.5in floppy    */
1415b81b6b3SRodney W. Grimes 	{ 15,2,0xFF,0x1B,80,2400,1,0,2 }, /* 1.2 meg HD floppy           */
1425b81b6b3SRodney W. Grimes 	{ 9,2,0xFF,0x23,40,720,2,1,2 },	/* 360k floppy in 1.2meg drive */
1435b81b6b3SRodney W. Grimes 	{ 9,2,0xFF,0x2A,40,720,1,1,2 },	/* 360k floppy in DD drive     */
1445b81b6b3SRodney W. Grimes };
1455b81b6b3SRodney W. Grimes 
1465b81b6b3SRodney W. Grimes #define DRVS_PER_CTLR 2
1475b81b6b3SRodney W. Grimes /***********************************************************************\
1485b81b6b3SRodney W. Grimes * Per controller structure.						*
1495b81b6b3SRodney W. Grimes \***********************************************************************/
1505b81b6b3SRodney W. Grimes struct fdc_data
1515b81b6b3SRodney W. Grimes {
1525b81b6b3SRodney W. Grimes 	int	fdcu;		/* our unit number */
1535b81b6b3SRodney W. Grimes 	int	baseport;
1545b81b6b3SRodney W. Grimes 	int	dmachan;
1555b81b6b3SRodney W. Grimes 	int	flags;
1565b81b6b3SRodney W. Grimes #define FDC_ATTACHED	0x01
1575b81b6b3SRodney W. Grimes 	struct	fd_data *fd;
1585b81b6b3SRodney W. Grimes 	int fdu;		/* the active drive	*/
1595b81b6b3SRodney W. Grimes 	struct buf head;	/* Head of buf chain      */
1605b81b6b3SRodney W. Grimes 	struct buf rhead;	/* Raw head of buf chain  */
1615b81b6b3SRodney W. Grimes 	int state;
1625b81b6b3SRodney W. Grimes 	int retry;
1635b81b6b3SRodney W. Grimes 	int status[7];		/* copy of the registers */
1645b81b6b3SRodney W. Grimes }fdc_data[(NFD+1)/DRVS_PER_CTLR];
1655b81b6b3SRodney W. Grimes 
1665b81b6b3SRodney W. Grimes /***********************************************************************\
1675b81b6b3SRodney W. Grimes * Per drive structure.							*
1685b81b6b3SRodney W. Grimes * N per controller (presently 2) (DRVS_PER_CTLR)			*
1695b81b6b3SRodney W. Grimes \***********************************************************************/
1705b81b6b3SRodney W. Grimes struct fd_data {
1715b81b6b3SRodney W. Grimes 	struct	fdc_data *fdc;
1725b81b6b3SRodney W. Grimes 	int	fdu;		/* this unit number */
1735b81b6b3SRodney W. Grimes 	int	fdsu;		/* this units number on this controller */
1745b81b6b3SRodney W. Grimes 	int	type;		/* Drive type (HD, DD     */
1755b81b6b3SRodney W. Grimes 	struct	fd_type *ft;	/* pointer to the type descriptor */
1765b81b6b3SRodney W. Grimes 	int	flags;
1775b81b6b3SRodney W. Grimes #define	FD_OPEN		0x01	/* it's open		*/
1785b81b6b3SRodney W. Grimes #define	FD_ACTIVE	0x02	/* it's active		*/
1795b81b6b3SRodney W. Grimes #define	FD_MOTOR	0x04	/* motor should be on	*/
1805b81b6b3SRodney W. Grimes #define	FD_MOTOR_WAIT	0x08	/* motor coming up	*/
1815b81b6b3SRodney W. Grimes 	int skip;
1825b81b6b3SRodney W. Grimes 	int hddrv;
1835b81b6b3SRodney W. Grimes 	int track;		/* where we think the head is */
1845b81b6b3SRodney W. Grimes } fd_data[NFD];
1855b81b6b3SRodney W. Grimes 
1865b81b6b3SRodney W. Grimes /***********************************************************************\
1875b81b6b3SRodney W. Grimes * Throughout this file the following conventions will be used:		*
1885b81b6b3SRodney W. Grimes * fd is a pointer to the fd_data struct for the drive in question	*
1895b81b6b3SRodney W. Grimes * fdc is a pointer to the fdc_data struct for the controller		*
1905b81b6b3SRodney W. Grimes * fdu is the floppy drive unit number					*
1915b81b6b3SRodney W. Grimes * fdcu is the floppy controller unit number				*
1925b81b6b3SRodney W. Grimes * fdsu is the floppy drive unit number on that controller. (sub-unit)	*
1935b81b6b3SRodney W. Grimes \***********************************************************************/
1945b81b6b3SRodney W. Grimes typedef int	fdu_t;
1955b81b6b3SRodney W. Grimes typedef int	fdcu_t;
1965b81b6b3SRodney W. Grimes typedef int	fdsu_t;
1975b81b6b3SRodney W. Grimes typedef	struct fd_data *fd_p;
1985b81b6b3SRodney W. Grimes typedef struct fdc_data *fdc_p;
1995b81b6b3SRodney W. Grimes 
2005b81b6b3SRodney W. Grimes #define DEVIDLE		0
2015b81b6b3SRodney W. Grimes #define FINDWORK	1
2025b81b6b3SRodney W. Grimes #define	DOSEEK		2
2035b81b6b3SRodney W. Grimes #define SEEKCOMPLETE 	3
2045b81b6b3SRodney W. Grimes #define	IOCOMPLETE	4
2055b81b6b3SRodney W. Grimes #define RECALCOMPLETE	5
2065b81b6b3SRodney W. Grimes #define	STARTRECAL	6
2075b81b6b3SRodney W. Grimes #define	RESETCTLR	7
2085b81b6b3SRodney W. Grimes #define	SEEKWAIT	8
2095b81b6b3SRodney W. Grimes #define	RECALWAIT	9
2105b81b6b3SRodney W. Grimes #define	MOTORWAIT	10
2115b81b6b3SRodney W. Grimes #define	IOTIMEDOUT	11
2125b81b6b3SRodney W. Grimes 
2135b81b6b3SRodney W. Grimes #ifdef	DEBUG
2145b81b6b3SRodney W. Grimes char *fdstates[] =
2155b81b6b3SRodney W. Grimes {
2165b81b6b3SRodney W. Grimes "DEVIDLE",
2175b81b6b3SRodney W. Grimes "FINDWORK",
2185b81b6b3SRodney W. Grimes "DOSEEK",
2195b81b6b3SRodney W. Grimes "SEEKCOMPLETE",
2205b81b6b3SRodney W. Grimes "IOCOMPLETE",
2215b81b6b3SRodney W. Grimes "RECALCOMPLETE",
2225b81b6b3SRodney W. Grimes "STARTRECAL",
2235b81b6b3SRodney W. Grimes "RESETCTLR",
2245b81b6b3SRodney W. Grimes "SEEKWAIT",
2255b81b6b3SRodney W. Grimes "RECALWAIT",
2265b81b6b3SRodney W. Grimes "MOTORWAIT",
2275b81b6b3SRodney W. Grimes "IOTIMEDOUT"
2285b81b6b3SRodney W. Grimes };
2295b81b6b3SRodney W. Grimes 
2305b81b6b3SRodney W. Grimes 
2315b81b6b3SRodney W. Grimes int	fd_debug = 1;
2325b81b6b3SRodney W. Grimes #define TRACE0(arg) if(fd_debug) printf(arg)
2335b81b6b3SRodney W. Grimes #define TRACE1(arg1,arg2) if(fd_debug) printf(arg1,arg2)
2345b81b6b3SRodney W. Grimes #else	DEBUG
2355b81b6b3SRodney W. Grimes #define TRACE0(arg)
2365b81b6b3SRodney W. Grimes #define TRACE1(arg1,arg2)
2375b81b6b3SRodney W. Grimes #endif	DEBUG
2385b81b6b3SRodney W. Grimes 
2395b81b6b3SRodney W. Grimes extern int hz;
2405b81b6b3SRodney W. Grimes /* state needed for current transfer */
2415b81b6b3SRodney W. Grimes 
2425b81b6b3SRodney W. Grimes /****************************************************************************/
2435b81b6b3SRodney W. Grimes /*                      autoconfiguration stuff                             */
2445b81b6b3SRodney W. Grimes /****************************************************************************/
2455b81b6b3SRodney W. Grimes int fdprobe(), fdattach(), fd_turnoff();
2465b81b6b3SRodney W. Grimes 
2475b81b6b3SRodney W. Grimes struct	isa_driver fddriver = {
2485b81b6b3SRodney W. Grimes 	fdprobe, fdattach, "fd",
2495b81b6b3SRodney W. Grimes };
2505b81b6b3SRodney W. Grimes 
2515b81b6b3SRodney W. Grimes /*
2525b81b6b3SRodney W. Grimes  * probe for existance of controller
2535b81b6b3SRodney W. Grimes  */
2545b81b6b3SRodney W. Grimes fdprobe(dev)
2555b81b6b3SRodney W. Grimes struct isa_device *dev;
2565b81b6b3SRodney W. Grimes {
2575b81b6b3SRodney W. Grimes 	fdcu_t	fdcu = dev->id_unit;
2585b81b6b3SRodney W. Grimes 	if(fdc_data[fdcu].flags & FDC_ATTACHED)
2595b81b6b3SRodney W. Grimes 	{
2605b81b6b3SRodney W. Grimes 		printf("fdc: same unit (%d) used multiple times\n",fdcu);
2615b81b6b3SRodney W. Grimes 		return 0;
2625b81b6b3SRodney W. Grimes 	}
2635b81b6b3SRodney W. Grimes 
2645b81b6b3SRodney W. Grimes 	fdc_data[fdcu].baseport = dev->id_iobase;
2655b81b6b3SRodney W. Grimes 
2665b81b6b3SRodney W. Grimes 	/* see if it can handle a command */
2675b81b6b3SRodney W. Grimes 	if (out_fdc(fdcu,NE7CMD_SPECIFY) < 0)
2685b81b6b3SRodney W. Grimes 	{
2695b81b6b3SRodney W. Grimes 		return(0);
2705b81b6b3SRodney W. Grimes 	}
2715b81b6b3SRodney W. Grimes 	out_fdc(fdcu,0xDF);
2725b81b6b3SRodney W. Grimes 	out_fdc(fdcu,2);
2735b81b6b3SRodney W. Grimes 	return (IO_FDCSIZE);
2745b81b6b3SRodney W. Grimes }
2755b81b6b3SRodney W. Grimes 
2765b81b6b3SRodney W. Grimes /*
2775b81b6b3SRodney W. Grimes  * wire controller into system, look for floppy units
2785b81b6b3SRodney W. Grimes  */
2795b81b6b3SRodney W. Grimes fdattach(dev)
2805b81b6b3SRodney W. Grimes struct isa_device *dev;
2815b81b6b3SRodney W. Grimes {
2825b81b6b3SRodney W. Grimes 	unsigned fdt,st0, cyl;
2835b81b6b3SRodney W. Grimes 	int	hdr;
2845b81b6b3SRodney W. Grimes 	fdu_t	fdu;
2855b81b6b3SRodney W. Grimes 	fdcu_t	fdcu = dev->id_unit;
2865b81b6b3SRodney W. Grimes 	fdc_p	fdc = fdc_data + fdcu;
2875b81b6b3SRodney W. Grimes 	fd_p	fd;
2885b81b6b3SRodney W. Grimes 	int	fdsu;
2895b81b6b3SRodney W. Grimes 
2905b81b6b3SRodney W. Grimes 	fdc->fdcu = fdcu;
2915b81b6b3SRodney W. Grimes 	fdc->flags |= FDC_ATTACHED;
2925b81b6b3SRodney W. Grimes 	fdc->dmachan = dev->id_drq;
2935b81b6b3SRodney W. Grimes 	fdc->state = DEVIDLE;
2945b81b6b3SRodney W. Grimes 
2955b81b6b3SRodney W. Grimes 	fdt = rtcin(RTC_FDISKETTE);
2965b81b6b3SRodney W. Grimes 	hdr = 0;
2975b81b6b3SRodney W. Grimes 
2985b81b6b3SRodney W. Grimes 	/* check for each floppy drive */
2995b81b6b3SRodney W. Grimes 	for (fdu = (fdcu * DRVS_PER_CTLR),fdsu = 0;
3005b81b6b3SRodney W. Grimes 	   ((fdu < NFD) && (fdsu < DRVS_PER_CTLR));
3015b81b6b3SRodney W. Grimes 	   fdu++,fdsu++)
3025b81b6b3SRodney W. Grimes 	{
3035b81b6b3SRodney W. Grimes 		/* is there a unit? */
304f5f7ba03SJordan K. Hubbard 		if ((fdt & 0xf0) == RTCFDT_NONE) {
305f5f7ba03SJordan K. Hubbard #define NO_TYPE NUMTYPES
306f5f7ba03SJordan K. Hubbard 			fd_data[fdu].type = NO_TYPE;
3075b81b6b3SRodney W. Grimes 			continue;
308f5f7ba03SJordan K. Hubbard 		}
3095b81b6b3SRodney W. Grimes 
3105b81b6b3SRodney W. Grimes #ifdef notyet
3115b81b6b3SRodney W. Grimes 		/* select it */
3125b81b6b3SRodney W. Grimes 		fd_turnon1(fdu);
3135b81b6b3SRodney W. Grimes 		spinwait(1000);	/* 1 sec */
3145b81b6b3SRodney W. Grimes 		out_fdc(fdcu,NE7CMD_RECAL);	/* Recalibrate Function */
3155b81b6b3SRodney W. Grimes 		out_fdc(fdcu,fdsu);
3165b81b6b3SRodney W. Grimes 		spinwait(1000);	/* 1 sec */
3175b81b6b3SRodney W. Grimes 
3185b81b6b3SRodney W. Grimes 		/* anything responding */
3195b81b6b3SRodney W. Grimes 		out_fdc(fdcu,NE7CMD_SENSEI);
3205b81b6b3SRodney W. Grimes 		st0 = in_fdc(fdcu);
3215b81b6b3SRodney W. Grimes 		cyl = in_fdc(fdcu);
3225b81b6b3SRodney W. Grimes 		if (st0 & 0xd0)
3235b81b6b3SRodney W. Grimes 			continue;
3245b81b6b3SRodney W. Grimes 
3255b81b6b3SRodney W. Grimes #endif
3265b81b6b3SRodney W. Grimes 		fd_data[fdu].track = -2;
3275b81b6b3SRodney W. Grimes 		fd_data[fdu].fdc = fdc;
3285b81b6b3SRodney W. Grimes 		fd_data[fdu].fdsu = fdsu;
3292a6c8980SDavid Greenman 		printf("fd%d: unit %d type ", fdcu, fdu);
3305b81b6b3SRodney W. Grimes 
3315b81b6b3SRodney W. Grimes 		if ((fdt & 0xf0) == RTCFDT_12M) {
3322a6c8980SDavid Greenman 			printf("1.2MB 5.25in\n");
3335b81b6b3SRodney W. Grimes 			fd_data[fdu].type = 1;
3345b81b6b3SRodney W. Grimes 			fd_data[fdu].ft = fd_types + 1;
3355b81b6b3SRodney W. Grimes 
3365b81b6b3SRodney W. Grimes 		}
3375b81b6b3SRodney W. Grimes 		if ((fdt & 0xf0) == RTCFDT_144M) {
3382a6c8980SDavid Greenman 			printf("1.44MB 3.5in\n");
3395b81b6b3SRodney W. Grimes 			fd_data[fdu].type = 0;
3405b81b6b3SRodney W. Grimes 			fd_data[fdu].ft = fd_types + 0;
3415b81b6b3SRodney W. Grimes 		}
3425b81b6b3SRodney W. Grimes 
3435b81b6b3SRodney W. Grimes 		fdt <<= 4;
3445b81b6b3SRodney W. Grimes 		fd_turnoff(fdu);
3455b81b6b3SRodney W. Grimes 		hdr = 1;
3465b81b6b3SRodney W. Grimes 	}
3475b81b6b3SRodney W. Grimes 
3485b81b6b3SRodney W. Grimes 	/* Set transfer to 500kbps */
3495b81b6b3SRodney W. Grimes 	outb(fdc->baseport+fdctl,0); /*XXX*/
3505b81b6b3SRodney W. Grimes }
3515b81b6b3SRodney W. Grimes 
3525b81b6b3SRodney W. Grimes int
3535b81b6b3SRodney W. Grimes fdsize(dev)
3545b81b6b3SRodney W. Grimes dev_t	dev;
3555b81b6b3SRodney W. Grimes {
3565b81b6b3SRodney W. Grimes 	return(0);
3575b81b6b3SRodney W. Grimes }
3585b81b6b3SRodney W. Grimes 
3595b81b6b3SRodney W. Grimes /****************************************************************************/
3605b81b6b3SRodney W. Grimes /*                               fdstrategy                                 */
3615b81b6b3SRodney W. Grimes /****************************************************************************/
3625b81b6b3SRodney W. Grimes fdstrategy(bp)
3635b81b6b3SRodney W. Grimes 	register struct buf *bp;	/* IO operation to perform */
3645b81b6b3SRodney W. Grimes {
3655b81b6b3SRodney W. Grimes 	register struct buf *dp,*dp0,*dp1;
3665b81b6b3SRodney W. Grimes 	long nblocks,blknum;
3675b81b6b3SRodney W. Grimes  	int	s;
3685b81b6b3SRodney W. Grimes  	fdcu_t	fdcu;
3695b81b6b3SRodney W. Grimes  	fdu_t	fdu;
3705b81b6b3SRodney W. Grimes  	fdc_p	fdc;
3715b81b6b3SRodney W. Grimes  	fd_p	fd;
3725b81b6b3SRodney W. Grimes 
3735b81b6b3SRodney W. Grimes  	fdu = FDUNIT(minor(bp->b_dev));
3745b81b6b3SRodney W. Grimes 	fd = &fd_data[fdu];
3755b81b6b3SRodney W. Grimes 	fdc = fd->fdc;
3765b81b6b3SRodney W. Grimes 	fdcu = fdc->fdcu;
3775b81b6b3SRodney W. Grimes  	/*type = FDTYPE(minor(bp->b_dev));*/
3785b81b6b3SRodney W. Grimes 
3795b81b6b3SRodney W. Grimes 	if ((fdu >= NFD) || (bp->b_blkno < 0)) {
3805b81b6b3SRodney W. Grimes 		printf("fdstrat: fdu = %d, blkno = %d, bcount = %d\n",
3815b81b6b3SRodney W. Grimes 			fdu, bp->b_blkno, bp->b_bcount);
3825b81b6b3SRodney W. Grimes 		pg("fd:error in fdstrategy");
3835b81b6b3SRodney W. Grimes 		bp->b_error = EINVAL;
3845b81b6b3SRodney W. Grimes 		bp->b_flags |= B_ERROR;
3855b81b6b3SRodney W. Grimes 		goto bad;
3865b81b6b3SRodney W. Grimes 	}
3875b81b6b3SRodney W. Grimes 	/*
3885b81b6b3SRodney W. Grimes 	 * Set up block calculations.
3895b81b6b3SRodney W. Grimes 	 */
3905b81b6b3SRodney W. Grimes 	blknum = (unsigned long) bp->b_blkno * DEV_BSIZE/FDBLK;
3915b81b6b3SRodney W. Grimes  	nblocks = fd->ft->size;
3925b81b6b3SRodney W. Grimes 	if (blknum + (bp->b_bcount / FDBLK) > nblocks) {
3935b81b6b3SRodney W. Grimes 		if (blknum == nblocks) {
3945b81b6b3SRodney W. Grimes 			bp->b_resid = bp->b_bcount;
3955b81b6b3SRodney W. Grimes 		} else {
3965b81b6b3SRodney W. Grimes 			bp->b_error = ENOSPC;
3975b81b6b3SRodney W. Grimes 			bp->b_flags |= B_ERROR;
3985b81b6b3SRodney W. Grimes 		}
3995b81b6b3SRodney W. Grimes 		goto bad;
4005b81b6b3SRodney W. Grimes 	}
4015b81b6b3SRodney W. Grimes  	bp->b_cylin = blknum / (fd->ft->sectrac * fd->ft->heads);
4025b81b6b3SRodney W. Grimes 	dp = &(fdc->head);
4035b81b6b3SRodney W. Grimes 	s = splbio();
4045b81b6b3SRodney W. Grimes 	disksort(dp, bp);
4055b81b6b3SRodney W. Grimes 	untimeout(fd_turnoff,fdu); /* a good idea */
4065b81b6b3SRodney W. Grimes 	fdstart(fdcu);
4075b81b6b3SRodney W. Grimes 	splx(s);
4085b81b6b3SRodney W. Grimes 	return;
4095b81b6b3SRodney W. Grimes 
4105b81b6b3SRodney W. Grimes bad:
4115b81b6b3SRodney W. Grimes 	biodone(bp);
4125b81b6b3SRodney W. Grimes }
4135b81b6b3SRodney W. Grimes 
4145b81b6b3SRodney W. Grimes /****************************************************************************/
4155b81b6b3SRodney W. Grimes /*                            motor control stuff                           */
4165b81b6b3SRodney W. Grimes /*		remember to not deselect the drive we're working on         */
4175b81b6b3SRodney W. Grimes /****************************************************************************/
418f5f7ba03SJordan K. Hubbard set_motor(fdcu, fdu, reset)
419f5f7ba03SJordan K. Hubbard 	fdcu_t fdcu;
420f5f7ba03SJordan K. Hubbard 	fdu_t fdu;
421f5f7ba03SJordan K. Hubbard 	int reset;
4225b81b6b3SRodney W. Grimes {
4235b81b6b3SRodney W. Grimes 	int m0,m1;
4245b81b6b3SRodney W. Grimes 	int selunit;
4255b81b6b3SRodney W. Grimes 	fd_p fd;
4265b81b6b3SRodney W. Grimes 	if(fd = fdc_data[fdcu].fd)/* yes an assign! */
4275b81b6b3SRodney W. Grimes 	{
4285b81b6b3SRodney W. Grimes 		selunit =  fd->fdsu;
4295b81b6b3SRodney W. Grimes 	}
4305b81b6b3SRodney W. Grimes 	else
4315b81b6b3SRodney W. Grimes 	{
4325b81b6b3SRodney W. Grimes 		selunit = 0;
4335b81b6b3SRodney W. Grimes 	}
4345b81b6b3SRodney W. Grimes 	m0 = fd_data[fdcu * DRVS_PER_CTLR + 0].flags & FD_MOTOR;
4355b81b6b3SRodney W. Grimes 	m1 = fd_data[fdcu * DRVS_PER_CTLR + 1].flags & FD_MOTOR;
4365b81b6b3SRodney W. Grimes 	outb(fdc_data[fdcu].baseport+fdout,
4375b81b6b3SRodney W. Grimes 		selunit
4385b81b6b3SRodney W. Grimes 		| (reset ? 0 : (FDO_FRST|FDO_FDMAEN))
4395b81b6b3SRodney W. Grimes 		| (m0 ? FDO_MOEN0 : 0)
4405b81b6b3SRodney W. Grimes 		| (m1 ? FDO_MOEN1 : 0));
4415b81b6b3SRodney W. Grimes 	TRACE1("[0x%x->fdout]",(
4425b81b6b3SRodney W. Grimes 		selunit
4435b81b6b3SRodney W. Grimes 		| (reset ? 0 : (FDO_FRST|FDO_FDMAEN))
4445b81b6b3SRodney W. Grimes 		| (m0 ? FDO_MOEN0 : 0)
4455b81b6b3SRodney W. Grimes 		| (m1 ? FDO_MOEN1 : 0)));
4465b81b6b3SRodney W. Grimes }
4475b81b6b3SRodney W. Grimes 
448f5f7ba03SJordan K. Hubbard fd_turnoff(fdu)
449f5f7ba03SJordan K. Hubbard 	fdu_t fdu;
4505b81b6b3SRodney W. Grimes {
451f5f7ba03SJordan K. Hubbard 	int	s;
452f5f7ba03SJordan K. Hubbard 
4535b81b6b3SRodney W. Grimes 	fd_p fd = fd_data + fdu;
454f5f7ba03SJordan K. Hubbard 	s = splbio();
4555b81b6b3SRodney W. Grimes 	fd->flags &= ~FD_MOTOR;
4565b81b6b3SRodney W. Grimes 	set_motor(fd->fdc->fdcu,fd->fdsu,0);
457f5f7ba03SJordan K. Hubbard 	splx(s);
4585b81b6b3SRodney W. Grimes }
4595b81b6b3SRodney W. Grimes 
460f5f7ba03SJordan K. Hubbard fd_motor_on(fdu)
461f5f7ba03SJordan K. Hubbard 	fdu_t fdu;
4625b81b6b3SRodney W. Grimes {
463f5f7ba03SJordan K. Hubbard 	int	s;
464f5f7ba03SJordan K. Hubbard 
4655b81b6b3SRodney W. Grimes 	fd_p fd = fd_data + fdu;
466f5f7ba03SJordan K. Hubbard 	s = splbio();
4675b81b6b3SRodney W. Grimes 	fd->flags &= ~FD_MOTOR_WAIT;
4685b81b6b3SRodney W. Grimes 	if((fd->fdc->fd == fd) && (fd->fdc->state == MOTORWAIT))
4695b81b6b3SRodney W. Grimes 	{
470f5f7ba03SJordan K. Hubbard 		fdintr(fd->fdc->fdcu);
4715b81b6b3SRodney W. Grimes 	}
472f5f7ba03SJordan K. Hubbard 	splx(s);
4735b81b6b3SRodney W. Grimes }
4745b81b6b3SRodney W. Grimes 
475f5f7ba03SJordan K. Hubbard fd_turnon(fdu)
476f5f7ba03SJordan K. Hubbard 	fdu_t fdu;
4775b81b6b3SRodney W. Grimes {
4785b81b6b3SRodney W. Grimes 	fd_p fd = fd_data + fdu;
4795b81b6b3SRodney W. Grimes 	if(!(fd->flags & FD_MOTOR))
4805b81b6b3SRodney W. Grimes 	{
4815b81b6b3SRodney W. Grimes 		fd_turnon1(fdu);
4825b81b6b3SRodney W. Grimes 		fd->flags |= FD_MOTOR_WAIT;
4835b81b6b3SRodney W. Grimes 		timeout(fd_motor_on,fdu,hz); /* in 1 sec its ok */
4845b81b6b3SRodney W. Grimes 	}
4855b81b6b3SRodney W. Grimes }
4865b81b6b3SRodney W. Grimes 
487f5f7ba03SJordan K. Hubbard fd_turnon1(fdu)
488f5f7ba03SJordan K. Hubbard 	fdu_t fdu;
4895b81b6b3SRodney W. Grimes {
4905b81b6b3SRodney W. Grimes 	fd_p fd = fd_data + fdu;
4915b81b6b3SRodney W. Grimes 	fd->flags |= FD_MOTOR;
4925b81b6b3SRodney W. Grimes 	set_motor(fd->fdc->fdcu,fd->fdsu,0);
4935b81b6b3SRodney W. Grimes }
4945b81b6b3SRodney W. Grimes 
4955b81b6b3SRodney W. Grimes /****************************************************************************/
4965b81b6b3SRodney W. Grimes /*                             fdc in/out                                   */
4975b81b6b3SRodney W. Grimes /****************************************************************************/
4985b81b6b3SRodney W. Grimes int
499f5f7ba03SJordan K. Hubbard in_fdc(fdcu)
500f5f7ba03SJordan K. Hubbard 	fdcu_t fdcu;
5015b81b6b3SRodney W. Grimes {
5025b81b6b3SRodney W. Grimes 	int baseport = fdc_data[fdcu].baseport;
5035b81b6b3SRodney W. Grimes 	int i, j = 100000;
5045b81b6b3SRodney W. Grimes 	while ((i = inb(baseport+fdsts) & (NE7_DIO|NE7_RQM))
5055b81b6b3SRodney W. Grimes 		!= (NE7_DIO|NE7_RQM) && j-- > 0)
5065b81b6b3SRodney W. Grimes 		if (i == NE7_RQM) return -1;
5075b81b6b3SRodney W. Grimes 	if (j <= 0)
5085b81b6b3SRodney W. Grimes 		return(-1);
5095b81b6b3SRodney W. Grimes #ifdef	DEBUG
5105b81b6b3SRodney W. Grimes 	i = inb(baseport+fddata);
5115b81b6b3SRodney W. Grimes 	TRACE1("[fddata->0x%x]",(unsigned char)i);
5125b81b6b3SRodney W. Grimes 	return(i);
5135b81b6b3SRodney W. Grimes #else
5145b81b6b3SRodney W. Grimes 	return inb(baseport+fddata);
5155b81b6b3SRodney W. Grimes #endif
5165b81b6b3SRodney W. Grimes }
5175b81b6b3SRodney W. Grimes 
518f5f7ba03SJordan K. Hubbard out_fdc(fdcu, x)
519f5f7ba03SJordan K. Hubbard 	fdcu_t fdcu;
520f5f7ba03SJordan K. Hubbard 	int x;
5215b81b6b3SRodney W. Grimes {
5225b81b6b3SRodney W. Grimes 	int baseport = fdc_data[fdcu].baseport;
5233b3837dbSRodney W. Grimes 	int i;
5245b81b6b3SRodney W. Grimes 
5253b3837dbSRodney W. Grimes 	/* Check that the direction bit is set */
5263b3837dbSRodney W. Grimes 	i = 100000;
5275b81b6b3SRodney W. Grimes 	while ((inb(baseport+fdsts) & NE7_DIO) && i-- > 0);
5283b3837dbSRodney W. Grimes 	if (i <= 0) return (-1);	/* Floppy timed out */
5293b3837dbSRodney W. Grimes 
5303b3837dbSRodney W. Grimes 	/* Check that the floppy controller is ready for a command */
5313b3837dbSRodney W. Grimes 	i = 100000;
5325b81b6b3SRodney W. Grimes 	while ((inb(baseport+fdsts) & NE7_RQM) == 0 && i-- > 0);
5333b3837dbSRodney W. Grimes 	if (i <= 0) return (-1);	/* Floppy timed out */
5343b3837dbSRodney W. Grimes 
5353b3837dbSRodney W. Grimes 	/* Send the command and return */
5365b81b6b3SRodney W. Grimes 	outb(baseport+fddata,x);
5375b81b6b3SRodney W. Grimes 	TRACE1("[0x%x->fddata]",x);
5385b81b6b3SRodney W. Grimes 	return (0);
5395b81b6b3SRodney W. Grimes }
5405b81b6b3SRodney W. Grimes 
5415b81b6b3SRodney W. Grimes /****************************************************************************/
5425b81b6b3SRodney W. Grimes /*                           fdopen/fdclose                                 */
5435b81b6b3SRodney W. Grimes /****************************************************************************/
5445b81b6b3SRodney W. Grimes Fdopen(dev, flags)
5455b81b6b3SRodney W. Grimes 	dev_t	dev;
5465b81b6b3SRodney W. Grimes 	int	flags;
5475b81b6b3SRodney W. Grimes {
5485b81b6b3SRodney W. Grimes  	fdu_t fdu = FDUNIT(minor(dev));
5495b81b6b3SRodney W. Grimes  	/*int type = FDTYPE(minor(dev));*/
5505b81b6b3SRodney W. Grimes 	int s;
5515b81b6b3SRodney W. Grimes 
5525b81b6b3SRodney W. Grimes 	/* check bounds */
553f5f7ba03SJordan K. Hubbard 	if (fdu >= NFD || fd_data[fdu].type == NO_TYPE) return(ENXIO);
5545b81b6b3SRodney W. Grimes 	/*if (type >= NUMTYPES) return(ENXIO);*/
5555b81b6b3SRodney W. Grimes 	fd_data[fdu].flags |= FD_OPEN;
5565b81b6b3SRodney W. Grimes 
5575b81b6b3SRodney W. Grimes 	return 0;
5585b81b6b3SRodney W. Grimes }
5595b81b6b3SRodney W. Grimes 
5605b81b6b3SRodney W. Grimes fdclose(dev, flags)
5615b81b6b3SRodney W. Grimes 	dev_t dev;
5625b81b6b3SRodney W. Grimes {
5635b81b6b3SRodney W. Grimes  	fdu_t fdu = FDUNIT(minor(dev));
5645b81b6b3SRodney W. Grimes 	fd_data[fdu].flags &= ~FD_OPEN;
5655b81b6b3SRodney W. Grimes 	return(0);
5665b81b6b3SRodney W. Grimes }
5675b81b6b3SRodney W. Grimes 
5685b81b6b3SRodney W. Grimes 
5695b81b6b3SRodney W. Grimes /***************************************************************\
5705b81b6b3SRodney W. Grimes *				fdstart				*
5715b81b6b3SRodney W. Grimes * We have just queued something.. if the controller is not busy	*
5725b81b6b3SRodney W. Grimes * then simulate the case where it has just finished a command	*
5735b81b6b3SRodney W. Grimes * So that it (the interrupt routine) looks on the queue for more*
5745b81b6b3SRodney W. Grimes * work to do and picks up what we just added.			*
5755b81b6b3SRodney W. Grimes * If the controller is already busy, we need do nothing, as it	*
5765b81b6b3SRodney W. Grimes * will pick up our work when the present work completes		*
5775b81b6b3SRodney W. Grimes \***************************************************************/
578f5f7ba03SJordan K. Hubbard fdstart(fdcu)
579f5f7ba03SJordan K. Hubbard 	fdcu_t fdcu;
5805b81b6b3SRodney W. Grimes {
5815b81b6b3SRodney W. Grimes 	register struct buf *dp,*bp;
5825b81b6b3SRodney W. Grimes 	int s;
5835b81b6b3SRodney W. Grimes  	fdu_t fdu;
5845b81b6b3SRodney W. Grimes 
5855b81b6b3SRodney W. Grimes 	s = splbio();
5865b81b6b3SRodney W. Grimes 	if(fdc_data[fdcu].state == DEVIDLE)
5875b81b6b3SRodney W. Grimes 	{
5885b81b6b3SRodney W. Grimes 		fdintr(fdcu);
5895b81b6b3SRodney W. Grimes 	}
5905b81b6b3SRodney W. Grimes 	splx(s);
5915b81b6b3SRodney W. Grimes }
5925b81b6b3SRodney W. Grimes 
593f5f7ba03SJordan K. Hubbard fd_timeout(fdcu)
594f5f7ba03SJordan K. Hubbard 	fdcu_t fdcu;
5955b81b6b3SRodney W. Grimes {
5965b81b6b3SRodney W. Grimes 	fdu_t fdu = fdc_data[fdcu].fdu;
5975b81b6b3SRodney W. Grimes 	int st0, st3, cyl;
5985b81b6b3SRodney W. Grimes 	struct buf *dp,*bp;
599f5f7ba03SJordan K. Hubbard 	int	s;
6005b81b6b3SRodney W. Grimes 
6015b81b6b3SRodney W. Grimes 	dp = &fdc_data[fdcu].head;
602f5f7ba03SJordan K. Hubbard 	s = splbio();
6035b81b6b3SRodney W. Grimes 	bp = dp->b_actf;
6045b81b6b3SRodney W. Grimes 
6055b81b6b3SRodney W. Grimes 	out_fdc(fdcu,NE7CMD_SENSED);
6065b81b6b3SRodney W. Grimes 	out_fdc(fdcu,fd_data[fdu].hddrv);
6075b81b6b3SRodney W. Grimes 	st3 = in_fdc(fdcu);
6085b81b6b3SRodney W. Grimes 
6095b81b6b3SRodney W. Grimes 	out_fdc(fdcu,NE7CMD_SENSEI);
6105b81b6b3SRodney W. Grimes 	st0 = in_fdc(fdcu);
6115b81b6b3SRodney W. Grimes 	cyl = in_fdc(fdcu);
6125b81b6b3SRodney W. Grimes 	printf("fd%d: Operation timeout ST0 %b cyl %d ST3 %b\n",
6135b81b6b3SRodney W. Grimes 			fdu,
6145b81b6b3SRodney W. Grimes 			st0,
6155b81b6b3SRodney W. Grimes 			NE7_ST0BITS,
6165b81b6b3SRodney W. Grimes 			cyl,
6175b81b6b3SRodney W. Grimes 			st3,
6185b81b6b3SRodney W. Grimes 			NE7_ST3BITS);
6195b81b6b3SRodney W. Grimes 
6205b81b6b3SRodney W. Grimes 	if (bp)
6215b81b6b3SRodney W. Grimes 	{
6225b81b6b3SRodney W. Grimes 		retrier(fdcu);
6235b81b6b3SRodney W. Grimes 		fdc_data[fdcu].status[0] = 0xc0;
6245b81b6b3SRodney W. Grimes 		fdc_data[fdcu].state = IOTIMEDOUT;
6255b81b6b3SRodney W. Grimes 		if( fdc_data[fdcu].retry < 6)
6265b81b6b3SRodney W. Grimes 			fdc_data[fdcu].retry = 6;
6275b81b6b3SRodney W. Grimes 	}
6285b81b6b3SRodney W. Grimes 	else
6295b81b6b3SRodney W. Grimes 	{
6305b81b6b3SRodney W. Grimes 		fdc_data[fdcu].fd = (fd_p) 0;
6315b81b6b3SRodney W. Grimes 		fdc_data[fdcu].fdu = -1;
6325b81b6b3SRodney W. Grimes 		fdc_data[fdcu].state = DEVIDLE;
6335b81b6b3SRodney W. Grimes 	}
634f5f7ba03SJordan K. Hubbard 	fdintr(fdcu);
635f5f7ba03SJordan K. Hubbard 	splx(s);
6365b81b6b3SRodney W. Grimes }
6375b81b6b3SRodney W. Grimes 
6385b81b6b3SRodney W. Grimes /* just ensure it has the right spl */
639f5f7ba03SJordan K. Hubbard fd_pseudointr(fdcu)
640f5f7ba03SJordan K. Hubbard 	fdcu_t fdcu;
6415b81b6b3SRodney W. Grimes {
6425b81b6b3SRodney W. Grimes 	int	s;
6435b81b6b3SRodney W. Grimes 	s = splbio();
6445b81b6b3SRodney W. Grimes 	fdintr(fdcu);
6455b81b6b3SRodney W. Grimes 	splx(s);
6465b81b6b3SRodney W. Grimes }
6475b81b6b3SRodney W. Grimes 
6485b81b6b3SRodney W. Grimes /***********************************************************************\
6495b81b6b3SRodney W. Grimes *                                 fdintr				*
6505b81b6b3SRodney W. Grimes * keep calling the state machine until it returns a 0			*
6515b81b6b3SRodney W. Grimes * ALWAYS called at SPLBIO 						*
6525b81b6b3SRodney W. Grimes \***********************************************************************/
653f5f7ba03SJordan K. Hubbard fdintr(fdcu)
654f5f7ba03SJordan K. Hubbard 	fdcu_t fdcu;
6555b81b6b3SRodney W. Grimes {
6565b81b6b3SRodney W. Grimes 	fdc_p fdc = fdc_data + fdcu;
6575b81b6b3SRodney W. Grimes 	while(fdstate(fdcu, fdc));
6585b81b6b3SRodney W. Grimes }
6595b81b6b3SRodney W. Grimes 
6605b81b6b3SRodney W. Grimes /***********************************************************************\
6615b81b6b3SRodney W. Grimes * The controller state machine.						*
6625b81b6b3SRodney W. Grimes * if it returns a non zero value, it should be called again immediatly	*
6635b81b6b3SRodney W. Grimes \***********************************************************************/
664f5f7ba03SJordan K. Hubbard int fdstate(fdcu, fdc)
665f5f7ba03SJordan K. Hubbard 	fdcu_t fdcu;
666f5f7ba03SJordan K. Hubbard 	fdc_p fdc;
6675b81b6b3SRodney W. Grimes {
6685b81b6b3SRodney W. Grimes 	int read,head,trac,sec,i,s,sectrac,cyl,st0;
6695b81b6b3SRodney W. Grimes 	unsigned long blknum;
6705b81b6b3SRodney W. Grimes 	fdu_t fdu = fdc->fdu;
6715b81b6b3SRodney W. Grimes 	fd_p fd;
6725b81b6b3SRodney W. Grimes 	register struct buf *dp,*bp;
6735b81b6b3SRodney W. Grimes 
6745b81b6b3SRodney W. Grimes 	dp = &(fdc->head);
6755b81b6b3SRodney W. Grimes 	bp = dp->b_actf;
6765b81b6b3SRodney W. Grimes 	if(!bp)
6775b81b6b3SRodney W. Grimes 	{
6785b81b6b3SRodney W. Grimes 		/***********************************************\
6795b81b6b3SRodney W. Grimes 		* nothing left for this controller to do	*
6805b81b6b3SRodney W. Grimes 		* Force into the IDLE state,			*
6815b81b6b3SRodney W. Grimes 		\***********************************************/
6825b81b6b3SRodney W. Grimes 		fdc->state = DEVIDLE;
6835b81b6b3SRodney W. Grimes 		if(fdc->fd)
6845b81b6b3SRodney W. Grimes 		{
6855b81b6b3SRodney W. Grimes 			printf("unexpected valid fd pointer (fdu = %d)\n"
6865b81b6b3SRodney W. Grimes 						,fdc->fdu);
6875b81b6b3SRodney W. Grimes 			fdc->fd = (fd_p) 0;
6885b81b6b3SRodney W. Grimes 			fdc->fdu = -1;
6895b81b6b3SRodney W. Grimes 		}
6905b81b6b3SRodney W. Grimes 		TRACE1("[fdc%d IDLE]",fdcu);
6915b81b6b3SRodney W. Grimes  		return(0);
6925b81b6b3SRodney W. Grimes 	}
6935b81b6b3SRodney W. Grimes 	fdu = FDUNIT(minor(bp->b_dev));
6945b81b6b3SRodney W. Grimes 	fd = fd_data + fdu;
6955b81b6b3SRodney W. Grimes 	if (fdc->fd && (fd != fdc->fd))
6965b81b6b3SRodney W. Grimes 	{
6975b81b6b3SRodney W. Grimes 		printf("confused fd pointers\n");
6985b81b6b3SRodney W. Grimes 	}
6995b81b6b3SRodney W. Grimes 	read = bp->b_flags & B_READ;
7005b81b6b3SRodney W. Grimes 	TRACE1("fd%d",fdu);
7015b81b6b3SRodney W. Grimes 	TRACE1("[%s]",fdstates[fdc->state]);
7025b81b6b3SRodney W. Grimes 	TRACE1("(0x%x)",fd->flags);
7035b81b6b3SRodney W. Grimes 	untimeout(fd_turnoff, fdu);
7045b81b6b3SRodney W. Grimes 	timeout(fd_turnoff,fdu,4 * hz);
7055b81b6b3SRodney W. Grimes 	switch (fdc->state)
7065b81b6b3SRodney W. Grimes 	{
7075b81b6b3SRodney W. Grimes 	case DEVIDLE:
7085b81b6b3SRodney W. Grimes 	case FINDWORK:	/* we have found new work */
7095b81b6b3SRodney W. Grimes 		fdc->retry = 0;
7105b81b6b3SRodney W. Grimes 		fd->skip = 0;
7115b81b6b3SRodney W. Grimes 		fdc->fd = fd;
7125b81b6b3SRodney W. Grimes 		fdc->fdu = fdu;
7135b81b6b3SRodney W. Grimes 		/*******************************************************\
7145b81b6b3SRodney W. Grimes 		* If the next drive has a motor startup pending, then	*
7155b81b6b3SRodney W. Grimes 		* it will start up in it's own good time		*
7165b81b6b3SRodney W. Grimes 		\*******************************************************/
7175b81b6b3SRodney W. Grimes 		if(fd->flags & FD_MOTOR_WAIT)
7185b81b6b3SRodney W. Grimes 		{
7195b81b6b3SRodney W. Grimes 			fdc->state = MOTORWAIT;
7205b81b6b3SRodney W. Grimes 			return(0); /* come back later */
7215b81b6b3SRodney W. Grimes 		}
7225b81b6b3SRodney W. Grimes 		/*******************************************************\
7235b81b6b3SRodney W. Grimes 		* Maybe if it's not starting, it SHOULD be starting	*
7245b81b6b3SRodney W. Grimes 		\*******************************************************/
7255b81b6b3SRodney W. Grimes 		if (!(fd->flags & FD_MOTOR))
7265b81b6b3SRodney W. Grimes 		{
7275b81b6b3SRodney W. Grimes 			fdc->state = MOTORWAIT;
7285b81b6b3SRodney W. Grimes 			fd_turnon(fdu);
7295b81b6b3SRodney W. Grimes 			return(0);
7305b81b6b3SRodney W. Grimes 		}
7315b81b6b3SRodney W. Grimes 		else	/* at least make sure we are selected */
7325b81b6b3SRodney W. Grimes 		{
7335b81b6b3SRodney W. Grimes 			set_motor(fdcu,fd->fdsu,0);
7345b81b6b3SRodney W. Grimes 		}
7355b81b6b3SRodney W. Grimes 		fdc->state = DOSEEK;
7365b81b6b3SRodney W. Grimes 		break;
7375b81b6b3SRodney W. Grimes 	case DOSEEK:
7385b81b6b3SRodney W. Grimes 		if (bp->b_cylin == fd->track)
7395b81b6b3SRodney W. Grimes 		{
7405b81b6b3SRodney W. Grimes 			fdc->state = SEEKCOMPLETE;
7415b81b6b3SRodney W. Grimes 			break;
7425b81b6b3SRodney W. Grimes 		}
7435b81b6b3SRodney W. Grimes 		out_fdc(fdcu,NE7CMD_SEEK);	/* Seek function */
7445b81b6b3SRodney W. Grimes 		out_fdc(fdcu,fd->fdsu);		/* Drive number */
7455b81b6b3SRodney W. Grimes 		out_fdc(fdcu,bp->b_cylin * fd->ft->steptrac);
7465b81b6b3SRodney W. Grimes 		fd->track = -2;
7475b81b6b3SRodney W. Grimes 		fdc->state = SEEKWAIT;
748f5f7ba03SJordan K. Hubbard 		timeout(fd_timeout,fdcu,2 * hz);
7495b81b6b3SRodney W. Grimes 		return(0);	/* will return later */
7505b81b6b3SRodney W. Grimes 	case SEEKWAIT:
751f5f7ba03SJordan K. Hubbard 		untimeout(fd_timeout,fdcu);
7525b81b6b3SRodney W. Grimes 		/* allow heads to settle */
7535b81b6b3SRodney W. Grimes 		timeout(fd_pseudointr,fdcu,hz/50);
7545b81b6b3SRodney W. Grimes 		fdc->state = SEEKCOMPLETE;
7555b81b6b3SRodney W. Grimes 		return(0);	/* will return later */
7565b81b6b3SRodney W. Grimes 		break;
7575b81b6b3SRodney W. Grimes 
7585b81b6b3SRodney W. Grimes 	case SEEKCOMPLETE : /* SEEK DONE, START DMA */
7595b81b6b3SRodney W. Grimes 		/* Make sure seek really happened*/
7605b81b6b3SRodney W. Grimes 		if(fd->track == -2)
7615b81b6b3SRodney W. Grimes 		{
7625b81b6b3SRodney W. Grimes 			int descyl = bp->b_cylin * fd->ft->steptrac;
7635b81b6b3SRodney W. Grimes 			out_fdc(fdcu,NE7CMD_SENSEI);
7645b81b6b3SRodney W. Grimes 			i = in_fdc(fdcu);
7655b81b6b3SRodney W. Grimes 			cyl = in_fdc(fdcu);
7665b81b6b3SRodney W. Grimes 			if (cyl != descyl)
7675b81b6b3SRodney W. Grimes 			{
7685b81b6b3SRodney W. Grimes 				printf("fd%d: Seek to cyl %d failed; am at cyl %d (ST0 = 0x%x)\n", fdu,
7695b81b6b3SRodney W. Grimes 				descyl, cyl, i, NE7_ST0BITS);
7705b81b6b3SRodney W. Grimes 				return(retrier(fdcu));
7715b81b6b3SRodney W. Grimes 			}
7725b81b6b3SRodney W. Grimes 		}
7735b81b6b3SRodney W. Grimes 
7745b81b6b3SRodney W. Grimes 		fd->track = bp->b_cylin;
7755b81b6b3SRodney W. Grimes 		isa_dmastart(bp->b_flags, bp->b_un.b_addr+fd->skip,
7765b81b6b3SRodney W. Grimes 			FDBLK, fdc->dmachan);
7775b81b6b3SRodney W. Grimes 		blknum = (unsigned long)bp->b_blkno*DEV_BSIZE/FDBLK
7785b81b6b3SRodney W. Grimes 			+ fd->skip/FDBLK;
7795b81b6b3SRodney W. Grimes 		sectrac = fd->ft->sectrac;
7805b81b6b3SRodney W. Grimes 		sec = blknum %  (sectrac * fd->ft->heads);
7815b81b6b3SRodney W. Grimes 		head = sec / sectrac;
7825b81b6b3SRodney W. Grimes 		sec = sec % sectrac + 1;
7835b81b6b3SRodney W. Grimes /*XXX*/		fd->hddrv = ((head&1)<<2)+fdu;
7845b81b6b3SRodney W. Grimes 
7855b81b6b3SRodney W. Grimes 		if (read)
7865b81b6b3SRodney W. Grimes 		{
7875b81b6b3SRodney W. Grimes 			out_fdc(fdcu,NE7CMD_READ);	/* READ */
7885b81b6b3SRodney W. Grimes 		}
7895b81b6b3SRodney W. Grimes 		else
7905b81b6b3SRodney W. Grimes 		{
7915b81b6b3SRodney W. Grimes 			out_fdc(fdcu,NE7CMD_WRITE);	/* WRITE */
7925b81b6b3SRodney W. Grimes 		}
7935b81b6b3SRodney W. Grimes 		out_fdc(fdcu,head << 2 | fdu);	/* head & unit */
7945b81b6b3SRodney W. Grimes 		out_fdc(fdcu,fd->track);		/* track */
7955b81b6b3SRodney W. Grimes 		out_fdc(fdcu,head);
7965b81b6b3SRodney W. Grimes 		out_fdc(fdcu,sec);			/* sector XXX +1? */
7975b81b6b3SRodney W. Grimes 		out_fdc(fdcu,fd->ft->secsize);		/* sector size */
7985b81b6b3SRodney W. Grimes 		out_fdc(fdcu,sectrac);		/* sectors/track */
7995b81b6b3SRodney W. Grimes 		out_fdc(fdcu,fd->ft->gap);		/* gap size */
8005b81b6b3SRodney W. Grimes 		out_fdc(fdcu,fd->ft->datalen);		/* data length */
8015b81b6b3SRodney W. Grimes 		fdc->state = IOCOMPLETE;
8025b81b6b3SRodney W. Grimes 		timeout(fd_timeout,fdcu,2 * hz);
8035b81b6b3SRodney W. Grimes 		return(0);	/* will return later */
8045b81b6b3SRodney W. Grimes 	case IOCOMPLETE: /* IO DONE, post-analyze */
8055b81b6b3SRodney W. Grimes 		untimeout(fd_timeout,fdcu);
8065b81b6b3SRodney W. Grimes 		for(i=0;i<7;i++)
8075b81b6b3SRodney W. Grimes 		{
8085b81b6b3SRodney W. Grimes 			fdc->status[i] = in_fdc(fdcu);
8095b81b6b3SRodney W. Grimes 		}
8105b81b6b3SRodney W. Grimes 	case IOTIMEDOUT: /*XXX*/
8115b81b6b3SRodney W. Grimes 		isa_dmadone(bp->b_flags, bp->b_un.b_addr+fd->skip,
8125b81b6b3SRodney W. Grimes 			FDBLK, fdc->dmachan);
8135b81b6b3SRodney W. Grimes 		if (fdc->status[0]&0xF8)
8145b81b6b3SRodney W. Grimes 		{
8155b81b6b3SRodney W. Grimes 			return(retrier(fdcu));
8165b81b6b3SRodney W. Grimes 		}
8175b81b6b3SRodney W. Grimes 		/* All OK */
8185b81b6b3SRodney W. Grimes 		fd->skip += FDBLK;
8195b81b6b3SRodney W. Grimes 		if (fd->skip < bp->b_bcount)
8205b81b6b3SRodney W. Grimes 		{
8215b81b6b3SRodney W. Grimes 			/* set up next transfer */
8225b81b6b3SRodney W. Grimes 			blknum = (unsigned long)bp->b_blkno*DEV_BSIZE/FDBLK
8235b81b6b3SRodney W. Grimes 				+ fd->skip/FDBLK;
8245b81b6b3SRodney W. Grimes 			bp->b_cylin = (blknum / (fd->ft->sectrac * fd->ft->heads));
8255b81b6b3SRodney W. Grimes 			fdc->state = DOSEEK;
8265b81b6b3SRodney W. Grimes 		}
8275b81b6b3SRodney W. Grimes 		else
8285b81b6b3SRodney W. Grimes 		{
8295b81b6b3SRodney W. Grimes 			/* ALL DONE */
8305b81b6b3SRodney W. Grimes 			fd->skip = 0;
8315b81b6b3SRodney W. Grimes 			bp->b_resid = 0;
8325b81b6b3SRodney W. Grimes 			dp->b_actf = bp->av_forw;
8335b81b6b3SRodney W. Grimes 			biodone(bp);
8345b81b6b3SRodney W. Grimes 			fdc->fd = (fd_p) 0;
8355b81b6b3SRodney W. Grimes 			fdc->fdu = -1;
8365b81b6b3SRodney W. Grimes 			fdc->state = FINDWORK;
8375b81b6b3SRodney W. Grimes 		}
8385b81b6b3SRodney W. Grimes 		return(1);
8395b81b6b3SRodney W. Grimes 	case RESETCTLR:
8405b81b6b3SRodney W. Grimes 		/* Try a reset, keep motor on */
8415b81b6b3SRodney W. Grimes 		set_motor(fdcu,fd->fdsu,1);
8425b81b6b3SRodney W. Grimes 		DELAY(100);
8435b81b6b3SRodney W. Grimes 		set_motor(fdcu,fd->fdsu,0);
8445b81b6b3SRodney W. Grimes 		outb(fdc->baseport+fdctl,fd->ft->trans);
8455b81b6b3SRodney W. Grimes 		TRACE1("[0x%x->fdctl]",fd->ft->trans);
8465b81b6b3SRodney W. Grimes 		fdc->retry++;
8475b81b6b3SRodney W. Grimes 		fdc->state = STARTRECAL;
8485b81b6b3SRodney W. Grimes 		break;
8495b81b6b3SRodney W. Grimes 	case STARTRECAL:
8505b81b6b3SRodney W. Grimes 		out_fdc(fdcu,NE7CMD_SPECIFY); /* specify command */
8515b81b6b3SRodney W. Grimes 		out_fdc(fdcu,0xDF);
8525b81b6b3SRodney W. Grimes 		out_fdc(fdcu,2);
8535b81b6b3SRodney W. Grimes 		out_fdc(fdcu,NE7CMD_RECAL);	/* Recalibrate Function */
8545b81b6b3SRodney W. Grimes 		out_fdc(fdcu,fdu);
8555b81b6b3SRodney W. Grimes 		fdc->state = RECALWAIT;
8565b81b6b3SRodney W. Grimes 		return(0);	/* will return later */
8575b81b6b3SRodney W. Grimes 	case RECALWAIT:
8585b81b6b3SRodney W. Grimes 		/* allow heads to settle */
8595b81b6b3SRodney W. Grimes 		timeout(fd_pseudointr,fdcu,hz/30);
8605b81b6b3SRodney W. Grimes 		fdc->state = RECALCOMPLETE;
8615b81b6b3SRodney W. Grimes 		return(0);	/* will return later */
8625b81b6b3SRodney W. Grimes 	case RECALCOMPLETE:
8635b81b6b3SRodney W. Grimes 		out_fdc(fdcu,NE7CMD_SENSEI);
8645b81b6b3SRodney W. Grimes 		st0 = in_fdc(fdcu);
8655b81b6b3SRodney W. Grimes 		cyl = in_fdc(fdcu);
8665b81b6b3SRodney W. Grimes 		if (cyl != 0)
8675b81b6b3SRodney W. Grimes 		{
8685b81b6b3SRodney W. Grimes 			printf("fd%d: recal failed ST0 %b cyl %d\n", fdu,
8695b81b6b3SRodney W. Grimes 				st0, NE7_ST0BITS, cyl);
8705b81b6b3SRodney W. Grimes 			return(retrier(fdcu));
8715b81b6b3SRodney W. Grimes 		}
8725b81b6b3SRodney W. Grimes 		fd->track = 0;
8735b81b6b3SRodney W. Grimes 		/* Seek (probably) necessary */
8745b81b6b3SRodney W. Grimes 		fdc->state = DOSEEK;
8755b81b6b3SRodney W. Grimes 		return(1);	/* will return immediatly */
8765b81b6b3SRodney W. Grimes 	case	MOTORWAIT:
8775b81b6b3SRodney W. Grimes 		if(fd->flags & FD_MOTOR_WAIT)
8785b81b6b3SRodney W. Grimes 		{
8795b81b6b3SRodney W. Grimes 			return(0); /* time's not up yet */
8805b81b6b3SRodney W. Grimes 		}
8815b81b6b3SRodney W. Grimes 		fdc->state = DOSEEK;
8825b81b6b3SRodney W. Grimes 		return(1);	/* will return immediatly */
8835b81b6b3SRodney W. Grimes 	default:
8845b81b6b3SRodney W. Grimes 		printf("Unexpected FD int->");
8855b81b6b3SRodney W. Grimes 		out_fdc(fdcu,NE7CMD_SENSEI);
8865b81b6b3SRodney W. Grimes 		st0 = in_fdc(fdcu);
8875b81b6b3SRodney W. Grimes 		cyl = in_fdc(fdcu);
8885b81b6b3SRodney W. Grimes 		printf("ST0 = %lx, PCN = %lx\n",i,sec);
8895b81b6b3SRodney W. Grimes 		out_fdc(fdcu,0x4A);
8905b81b6b3SRodney W. Grimes 		out_fdc(fdcu,fd->fdsu);
8915b81b6b3SRodney W. Grimes 		for(i=0;i<7;i++) {
8925b81b6b3SRodney W. Grimes 			fdc->status[i] = in_fdc(fdcu);
8935b81b6b3SRodney W. Grimes 		}
8945b81b6b3SRodney W. Grimes 	printf("intr status :%lx %lx %lx %lx %lx %lx %lx ",
8955b81b6b3SRodney W. Grimes 		fdc->status[0],
8965b81b6b3SRodney W. Grimes 		fdc->status[1],
8975b81b6b3SRodney W. Grimes 		fdc->status[2],
8985b81b6b3SRodney W. Grimes 		fdc->status[3],
8995b81b6b3SRodney W. Grimes 		fdc->status[4],
9005b81b6b3SRodney W. Grimes 		fdc->status[5],
9015b81b6b3SRodney W. Grimes 		fdc->status[6] );
9025b81b6b3SRodney W. Grimes 		return(0);
9035b81b6b3SRodney W. Grimes 	}
9045b81b6b3SRodney W. Grimes 	return(1); /* Come back immediatly to new state */
9055b81b6b3SRodney W. Grimes }
9065b81b6b3SRodney W. Grimes 
907f5f7ba03SJordan K. Hubbard retrier(fdcu)
908f5f7ba03SJordan K. Hubbard 	fdcu_t fdcu;
9095b81b6b3SRodney W. Grimes {
9105b81b6b3SRodney W. Grimes 	fdc_p fdc = fdc_data + fdcu;
9115b81b6b3SRodney W. Grimes 	register struct buf *dp,*bp;
9125b81b6b3SRodney W. Grimes 
9135b81b6b3SRodney W. Grimes 	dp = &(fdc->head);
9145b81b6b3SRodney W. Grimes 	bp = dp->b_actf;
9155b81b6b3SRodney W. Grimes 
9165b81b6b3SRodney W. Grimes 	switch(fdc->retry)
9175b81b6b3SRodney W. Grimes 	{
9185b81b6b3SRodney W. Grimes 	case 0: case 1: case 2:
9195b81b6b3SRodney W. Grimes 		fdc->state = SEEKCOMPLETE;
9205b81b6b3SRodney W. Grimes 		break;
9215b81b6b3SRodney W. Grimes 	case 3: case 4: case 5:
9225b81b6b3SRodney W. Grimes 		fdc->state = STARTRECAL;
9235b81b6b3SRodney W. Grimes 		break;
9245b81b6b3SRodney W. Grimes 	case 6:
9255b81b6b3SRodney W. Grimes 		fdc->state = RESETCTLR;
9265b81b6b3SRodney W. Grimes 		break;
9275b81b6b3SRodney W. Grimes 	case 7:
9285b81b6b3SRodney W. Grimes 		break;
9295b81b6b3SRodney W. Grimes 	default:
9305b81b6b3SRodney W. Grimes 		{
9315b81b6b3SRodney W. Grimes 			printf("fd%d: hard error (ST0 %b ",
9325b81b6b3SRodney W. Grimes 				 fdc->fdu, fdc->status[0], NE7_ST0BITS);
9335b81b6b3SRodney W. Grimes 			printf(" ST1 %b ", fdc->status[1], NE7_ST1BITS);
9345b81b6b3SRodney W. Grimes 			printf(" ST2 %b ", fdc->status[2], NE7_ST2BITS);
9355b81b6b3SRodney W. Grimes 			printf(" ST3 %b ", fdc->status[3], NE7_ST3BITS);
9365b81b6b3SRodney W. Grimes 			printf("cyl %d hd %d sec %d)\n",
9375b81b6b3SRodney W. Grimes 				 fdc->status[4], fdc->status[5], fdc->status[6]);
9385b81b6b3SRodney W. Grimes 		}
9395b81b6b3SRodney W. Grimes 		bp->b_flags |= B_ERROR;
9405b81b6b3SRodney W. Grimes 		bp->b_error = EIO;
9415b81b6b3SRodney W. Grimes 		bp->b_resid = bp->b_bcount - fdc->fd->skip;
9425b81b6b3SRodney W. Grimes 		dp->b_actf = bp->av_forw;
9435b81b6b3SRodney W. Grimes 		fdc->fd->skip = 0;
9445b81b6b3SRodney W. Grimes 		biodone(bp);
945f5f7ba03SJordan K. Hubbard 		fdc->state = DEVIDLE;
9465b81b6b3SRodney W. Grimes 		fdc->fd = (fd_p) 0;
9475b81b6b3SRodney W. Grimes 		fdc->fdu = -1;
948f5f7ba03SJordan K. Hubbard 		/* XXX abort current command, if any.  */
949f5f7ba03SJordan K. Hubbard 		return(0);
9505b81b6b3SRodney W. Grimes 	}
9515b81b6b3SRodney W. Grimes 	fdc->retry++;
9525b81b6b3SRodney W. Grimes 	return(1);
9535b81b6b3SRodney W. Grimes }
9545b81b6b3SRodney W. Grimes 
955f5f7ba03SJordan K. Hubbard /*
956f5f7ba03SJordan K. Hubbard  * fdioctl() from jc@irbs.UUCP (John Capo)
957f5f7ba03SJordan K. Hubbard  * i386/i386/conf.c needs to have fdioctl() declared and remove the line that
958f5f7ba03SJordan K. Hubbard  * defines fdioctl to be enxio.
959f5f7ba03SJordan K. Hubbard  *
960f5f7ba03SJordan K. Hubbard  * TODO: Reformat.
961f5f7ba03SJordan K. Hubbard  *       Think about allocating buffer off stack.
962f5f7ba03SJordan K. Hubbard  *       Don't pass uncast 0's and NULL's to read/write/setdisklabel().
963f5f7ba03SJordan K. Hubbard  *       Watch out for NetBSD's different *disklabel() interface.
964f5f7ba03SJordan K. Hubbard  */
9655b81b6b3SRodney W. Grimes 
966f5f7ba03SJordan K. Hubbard int
967f5f7ba03SJordan K. Hubbard fdioctl (dev, cmd, addr, flag)
968f5f7ba03SJordan K. Hubbard dev_t dev;
969f5f7ba03SJordan K. Hubbard int cmd;
970f5f7ba03SJordan K. Hubbard caddr_t addr;
971f5f7ba03SJordan K. Hubbard int flag;
972f5f7ba03SJordan K. Hubbard {
973f5f7ba03SJordan K. Hubbard     struct fd_type *fdt;
974f5f7ba03SJordan K. Hubbard     struct disklabel *dl;
975f5f7ba03SJordan K. Hubbard     char buffer[DEV_BSIZE];
976f5f7ba03SJordan K. Hubbard     int error;
977f5f7ba03SJordan K. Hubbard 
978f5f7ba03SJordan K. Hubbard     error = 0;
979f5f7ba03SJordan K. Hubbard 
980f5f7ba03SJordan K. Hubbard     switch (cmd)
981f5f7ba03SJordan K. Hubbard     {
982f5f7ba03SJordan K. Hubbard     case DIOCGDINFO:
983f5f7ba03SJordan K. Hubbard         bzero(buffer, sizeof (buffer));
984f5f7ba03SJordan K. Hubbard         dl = (struct disklabel *)buffer;
985f5f7ba03SJordan K. Hubbard         dl->d_secsize = FDBLK;
986f5f7ba03SJordan K. Hubbard         fdt = &fd_types[FDUNIT(minor(dev))];
987f5f7ba03SJordan K. Hubbard         dl->d_secpercyl = fdt->size / fdt->tracks;
988f5f7ba03SJordan K. Hubbard         dl->d_type = DTYPE_FLOPPY;
989f5f7ba03SJordan K. Hubbard 
990f5f7ba03SJordan K. Hubbard         if (readdisklabel(dev, fdstrategy, dl, NULL, 0, 0) == NULL)
991f5f7ba03SJordan K. Hubbard             error = 0;
992f5f7ba03SJordan K. Hubbard         else
993f5f7ba03SJordan K. Hubbard             error = EINVAL;
994f5f7ba03SJordan K. Hubbard 
995f5f7ba03SJordan K. Hubbard         *(struct disklabel *)addr = *dl;
996f5f7ba03SJordan K. Hubbard         break;
997f5f7ba03SJordan K. Hubbard 
998f5f7ba03SJordan K. Hubbard     case DIOCSDINFO:
999f5f7ba03SJordan K. Hubbard 
1000f5f7ba03SJordan K. Hubbard         if ((flag & FWRITE) == 0)
1001f5f7ba03SJordan K. Hubbard             error = EBADF;
1002f5f7ba03SJordan K. Hubbard 
1003f5f7ba03SJordan K. Hubbard         break;
1004f5f7ba03SJordan K. Hubbard 
1005f5f7ba03SJordan K. Hubbard     case DIOCWLABEL:
1006f5f7ba03SJordan K. Hubbard         if ((flag & FWRITE) == 0)
1007f5f7ba03SJordan K. Hubbard             error = EBADF;
1008f5f7ba03SJordan K. Hubbard 
1009f5f7ba03SJordan K. Hubbard         break;
1010f5f7ba03SJordan K. Hubbard 
1011f5f7ba03SJordan K. Hubbard     case DIOCWDINFO:
1012f5f7ba03SJordan K. Hubbard         if ((flag & FWRITE) == 0)
1013f5f7ba03SJordan K. Hubbard         {
1014f5f7ba03SJordan K. Hubbard             error = EBADF;
1015f5f7ba03SJordan K. Hubbard             break;
1016f5f7ba03SJordan K. Hubbard         }
1017f5f7ba03SJordan K. Hubbard 
1018f5f7ba03SJordan K. Hubbard         dl = (struct disklabel *)addr;
1019f5f7ba03SJordan K. Hubbard 
1020f5f7ba03SJordan K. Hubbard         if (error = setdisklabel ((struct disklabel *)buffer, dl, 0, NULL))
1021f5f7ba03SJordan K. Hubbard             break;
1022f5f7ba03SJordan K. Hubbard 
1023f5f7ba03SJordan K. Hubbard         error = writedisklabel(dev, fdstrategy, (struct disklabel *)buffer, NULL);
1024f5f7ba03SJordan K. Hubbard         break;
1025f5f7ba03SJordan K. Hubbard 
1026f5f7ba03SJordan K. Hubbard      default:
1027f5f7ba03SJordan K. Hubbard         error = EINVAL;
1028f5f7ba03SJordan K. Hubbard         break;
1029f5f7ba03SJordan K. Hubbard     }
1030f5f7ba03SJordan K. Hubbard     return (error);
1031f5f7ba03SJordan K. Hubbard }
1032f5f7ba03SJordan K. Hubbard 
1033f5f7ba03SJordan K. Hubbard #endif
1034