fdc.c revision 76166
1/*
2 * Copyright (c) 1990 The Regents of the University of California.
3 * All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Don Ahn.
7 *
8 * Libretto PCMCIA floppy support by David Horwitt (dhorwitt@ucsd.edu)
9 * aided by the Linux floppy driver modifications from David Bateman
10 * (dbateman@eng.uts.edu.au).
11 *
12 * Copyright (c) 1993, 1994 by
13 *  jc@irbs.UUCP (John Capo)
14 *  vak@zebub.msk.su (Serge Vakulenko)
15 *  ache@astral.msk.su (Andrew A. Chernov)
16 *
17 * Copyright (c) 1993, 1994, 1995 by
18 *  joerg_wunsch@uriah.sax.de (Joerg Wunsch)
19 *  dufault@hda.com (Peter Dufault)
20 *
21 * Redistribution and use in source and binary forms, with or without
22 * modification, are permitted provided that the following conditions
23 * are met:
24 * 1. Redistributions of source code must retain the above copyright
25 *    notice, this list of conditions and the following disclaimer.
26 * 2. Redistributions in binary form must reproduce the above copyright
27 *    notice, this list of conditions and the following disclaimer in the
28 *    documentation and/or other materials provided with the distribution.
29 * 3. All advertising materials mentioning features or use of this software
30 *    must display the following acknowledgement:
31 *	This product includes software developed by the University of
32 *	California, Berkeley and its contributors.
33 * 4. Neither the name of the University nor the names of its contributors
34 *    may be used to endorse or promote products derived from this software
35 *    without specific prior written permission.
36 *
37 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
38 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
39 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
40 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
41 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
42 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
43 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
44 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
45 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
46 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47 * SUCH DAMAGE.
48 *
49 *	from:	@(#)fd.c	7.4 (Berkeley) 5/25/91
50 * $FreeBSD: head/sys/dev/fdc/fdc.c 76166 2001-05-01 08:13:21Z markm $
51 *
52 */
53
54#include "opt_fdc.h"
55#include "card.h"
56
57#include <sys/param.h>
58#include <sys/systm.h>
59#include <sys/bio.h>
60#include <sys/bus.h>
61#include <sys/conf.h>
62#include <sys/devicestat.h>
63#include <sys/disklabel.h>
64#include <sys/fcntl.h>
65#include <sys/kernel.h>
66#include <sys/lock.h>
67#include <sys/malloc.h>
68#include <sys/module.h>
69#include <sys/mutex.h>
70#include <sys/proc.h>
71#include <sys/syslog.h>
72
73#include <sys/bus.h>
74#include <machine/bus.h>
75#include <sys/rman.h>
76
77#include <machine/clock.h>
78#include <machine/ioctl_fd.h>
79#include <machine/resource.h>
80#include <machine/stdarg.h>
81
82#include <isa/isavar.h>
83#include <isa/isareg.h>
84#include <isa/fdreg.h>
85#include <isa/fdc.h>
86#include <isa/rtc.h>
87
88/* misuse a flag to identify format operation */
89
90/* configuration flags */
91#define FDC_PRETEND_D0	(1 << 0)	/* pretend drive 0 to be there */
92#define FDC_NO_FIFO	(1 << 2)	/* do not enable FIFO  */
93
94/* internally used only, not really from CMOS: */
95#define RTCFDT_144M_PRETENDED	0x1000
96
97/* error returns for fd_cmd() */
98#define FD_FAILED -1
99#define FD_NOT_VALID -2
100#define FDC_ERRMAX	100	/* do not log more */
101
102#define NUMTYPES 17
103#define NUMDENS  (NUMTYPES - 7)
104
105/* These defines (-1) must match index for fd_types */
106#define F_TAPE_TYPE	0x020	/* bit for fd_types to indicate tape */
107#define NO_TYPE		0	/* must match NO_TYPE in ft.c */
108#define FD_1720         1
109#define FD_1480         2
110#define FD_1440         3
111#define FD_1200         4
112#define FD_820          5
113#define FD_800          6
114#define FD_720          7
115#define FD_360          8
116#define FD_640          9
117#define FD_1232         10
118
119#define FD_1480in5_25   11
120#define FD_1440in5_25   12
121#define FD_820in5_25    13
122#define FD_800in5_25    14
123#define FD_720in5_25    15
124#define FD_360in5_25    16
125#define FD_640in5_25    17
126
127
128static struct fd_type fd_types[NUMTYPES] =
129{
130{ 21,2,0xFF,0x04,82,3444,1,FDC_500KBPS,2,0x0C,2 }, /* 1.72M in HD 3.5in */
131{ 18,2,0xFF,0x1B,82,2952,1,FDC_500KBPS,2,0x6C,1 }, /* 1.48M in HD 3.5in */
132{ 18,2,0xFF,0x1B,80,2880,1,FDC_500KBPS,2,0x6C,1 }, /* 1.44M in HD 3.5in */
133{ 15,2,0xFF,0x1B,80,2400,1,FDC_500KBPS,2,0x54,1 }, /*  1.2M in HD 5.25/3.5 */
134{ 10,2,0xFF,0x10,82,1640,1,FDC_250KBPS,2,0x2E,1 }, /*  820K in HD 3.5in */
135{ 10,2,0xFF,0x10,80,1600,1,FDC_250KBPS,2,0x2E,1 }, /*  800K in HD 3.5in */
136{  9,2,0xFF,0x20,80,1440,1,FDC_250KBPS,2,0x50,1 }, /*  720K in HD 3.5in */
137{  9,2,0xFF,0x2A,40, 720,1,FDC_250KBPS,2,0x50,1 }, /*  360K in DD 5.25in */
138{  8,2,0xFF,0x2A,80,1280,1,FDC_250KBPS,2,0x50,1 }, /*  640K in DD 5.25in */
139{  8,3,0xFF,0x35,77,1232,1,FDC_500KBPS,2,0x74,1 }, /* 1.23M in HD 5.25in */
140
141{ 18,2,0xFF,0x02,82,2952,1,FDC_500KBPS,2,0x02,2 }, /* 1.48M in HD 5.25in */
142{ 18,2,0xFF,0x02,80,2880,1,FDC_500KBPS,2,0x02,2 }, /* 1.44M in HD 5.25in */
143{ 10,2,0xFF,0x10,82,1640,1,FDC_300KBPS,2,0x2E,1 }, /*  820K in HD 5.25in */
144{ 10,2,0xFF,0x10,80,1600,1,FDC_300KBPS,2,0x2E,1 }, /*  800K in HD 5.25in */
145{  9,2,0xFF,0x20,80,1440,1,FDC_300KBPS,2,0x50,1 }, /*  720K in HD 5.25in */
146{  9,2,0xFF,0x23,40, 720,2,FDC_300KBPS,2,0x50,1 }, /*  360K in HD 5.25in */
147{  8,2,0xFF,0x2A,80,1280,1,FDC_300KBPS,2,0x50,1 }, /*  640K in HD 5.25in */
148};
149
150#define DRVS_PER_CTLR 2		/* 2 floppies */
151
152/***********************************************************************\
153* Per controller structure.						*
154\***********************************************************************/
155static devclass_t fdc_devclass;
156
157/***********************************************************************\
158* Per drive structure.							*
159* N per controller  (DRVS_PER_CTLR)					*
160\***********************************************************************/
161struct fd_data {
162	struct	fdc_data *fdc;	/* pointer to controller structure */
163	int	fdsu;		/* this units number on this controller */
164	int	type;		/* Drive type (FD_1440...) */
165	struct	fd_type *ft;	/* pointer to the type descriptor */
166	int	flags;
167#define	FD_OPEN		0x01	/* it's open		*/
168#define	FD_ACTIVE	0x02	/* it's active		*/
169#define	FD_MOTOR	0x04	/* motor should be on	*/
170#define	FD_MOTOR_WAIT	0x08	/* motor coming up	*/
171	int	skip;
172	int	hddrv;
173#define FD_NO_TRACK -2
174	int	track;		/* where we think the head is */
175	int	options;	/* user configurable options, see ioctl_fd.h */
176	struct	callout_handle toffhandle;
177	struct	callout_handle tohandle;
178	struct	devstat device_stats;
179	device_t dev;
180	fdu_t	fdu;
181};
182
183struct fdc_ivars {
184	int	fdunit;
185};
186static devclass_t fd_devclass;
187
188/***********************************************************************\
189* Throughout this file the following conventions will be used:		*
190* fd is a pointer to the fd_data struct for the drive in question	*
191* fdc is a pointer to the fdc_data struct for the controller		*
192* fdu is the floppy drive unit number					*
193* fdcu is the floppy controller unit number				*
194* fdsu is the floppy drive unit number on that controller. (sub-unit)	*
195\***********************************************************************/
196
197/* needed for ft driver, thus exported */
198int in_fdc(struct fdc_data *);
199int out_fdc(struct fdc_data *, int);
200
201/* internal functions */
202static	void fdc_intr(void *);
203static void set_motor(struct fdc_data *, int, int);
204#  define TURNON 1
205#  define TURNOFF 0
206static timeout_t fd_turnoff;
207static timeout_t fd_motor_on;
208static void fd_turnon(struct fd_data *);
209static void fdc_reset(fdc_p);
210static int fd_in(struct fdc_data *, int *);
211static void fdstart(struct fdc_data *);
212static timeout_t fd_iotimeout;
213static timeout_t fd_pseudointr;
214static int fdstate(struct fdc_data *);
215static int retrier(struct fdc_data *);
216static int fdformat(dev_t, struct fd_formb *, struct proc *);
217
218static int enable_fifo(fdc_p fdc);
219
220static int fifo_threshold = 8;	/* XXX: should be accessible via sysctl */
221
222
223#define DEVIDLE		0
224#define FINDWORK	1
225#define	DOSEEK		2
226#define SEEKCOMPLETE 	3
227#define	IOCOMPLETE	4
228#define RECALCOMPLETE	5
229#define	STARTRECAL	6
230#define	RESETCTLR	7
231#define	SEEKWAIT	8
232#define	RECALWAIT	9
233#define	MOTORWAIT	10
234#define	IOTIMEDOUT	11
235#define	RESETCOMPLETE	12
236#define PIOREAD		13
237
238#ifdef	FDC_DEBUG
239static char const * const fdstates[] =
240{
241"DEVIDLE",
242"FINDWORK",
243"DOSEEK",
244"SEEKCOMPLETE",
245"IOCOMPLETE",
246"RECALCOMPLETE",
247"STARTRECAL",
248"RESETCTLR",
249"SEEKWAIT",
250"RECALWAIT",
251"MOTORWAIT",
252"IOTIMEDOUT",
253"RESETCOMPLETE",
254"PIOREAD",
255};
256
257/* CAUTION: fd_debug causes huge amounts of logging output */
258static int volatile fd_debug = 0;
259#define TRACE0(arg) if(fd_debug) printf(arg)
260#define TRACE1(arg1, arg2) if(fd_debug) printf(arg1, arg2)
261#else /* FDC_DEBUG */
262#define TRACE0(arg)
263#define TRACE1(arg1, arg2)
264#endif /* FDC_DEBUG */
265
266static void
267fdout_wr(fdc_p fdc, u_int8_t v)
268{
269	bus_space_write_1(fdc->portt, fdc->porth, FDOUT+fdc->port_off, v);
270}
271
272static u_int8_t
273fdsts_rd(fdc_p fdc)
274{
275	return bus_space_read_1(fdc->portt, fdc->porth, FDSTS+fdc->port_off);
276}
277
278static void
279fddata_wr(fdc_p fdc, u_int8_t v)
280{
281	bus_space_write_1(fdc->portt, fdc->porth, FDDATA+fdc->port_off, v);
282}
283
284static u_int8_t
285fddata_rd(fdc_p fdc)
286{
287	return bus_space_read_1(fdc->portt, fdc->porth, FDDATA+fdc->port_off);
288}
289
290static void
291fdctl_wr_isa(fdc_p fdc, u_int8_t v)
292{
293	bus_space_write_1(fdc->ctlt, fdc->ctlh, 0, v);
294}
295
296#if NCARD > 0
297static void
298fdctl_wr_pcmcia(fdc_p fdc, u_int8_t v)
299{
300	bus_space_write_1(fdc->portt, fdc->porth, FDCTL+fdc->port_off, v);
301}
302#endif
303
304#if 0
305
306static u_int8_t
307fdin_rd(fdc_p fdc)
308{
309	return bus_space_read_1(fdc->portt, fdc->porth, FDIN);
310}
311
312#endif
313
314static	d_open_t	Fdopen;	/* NOTE, not fdopen */
315static	d_close_t	fdclose;
316static	d_ioctl_t	fdioctl;
317static	d_strategy_t	fdstrategy;
318
319#define CDEV_MAJOR 9
320
321static struct cdevsw fd_cdevsw = {
322	/* open */	Fdopen,
323	/* close */	fdclose,
324	/* read */	physread,
325	/* write */	physwrite,
326	/* ioctl */	fdioctl,
327	/* poll */	nopoll,
328	/* mmap */	nommap,
329	/* strategy */	fdstrategy,
330	/* name */	"fd",
331	/* maj */	CDEV_MAJOR,
332	/* dump */	nodump,
333	/* psize */	nopsize,
334	/* flags */	D_DISK,
335};
336
337static int
338fdc_err(struct fdc_data *fdc, const char *s)
339{
340	fdc->fdc_errs++;
341	if (s) {
342		if (fdc->fdc_errs < FDC_ERRMAX)
343			device_printf(fdc->fdc_dev, "%s", s);
344		else if (fdc->fdc_errs == FDC_ERRMAX)
345			device_printf(fdc->fdc_dev, "too many errors, not "
346						    "logging any more\n");
347	}
348
349	return FD_FAILED;
350}
351
352/*
353 * fd_cmd: Send a command to the chip.  Takes a varargs with this structure:
354 * Unit number,
355 * # of output bytes, output bytes as ints ...,
356 * # of input bytes, input bytes as ints ...
357 */
358static int
359fd_cmd(struct fdc_data *fdc, int n_out, ...)
360{
361	u_char cmd;
362	int n_in;
363	int n;
364	va_list ap;
365
366	va_start(ap, n_out);
367	cmd = (u_char)(va_arg(ap, int));
368	va_end(ap);
369	va_start(ap, n_out);
370	for (n = 0; n < n_out; n++)
371	{
372		if (out_fdc(fdc, va_arg(ap, int)) < 0)
373		{
374			char msg[50];
375			snprintf(msg, sizeof(msg),
376				"cmd %x failed at out byte %d of %d\n",
377				cmd, n + 1, n_out);
378			return fdc_err(fdc, msg);
379		}
380	}
381	n_in = va_arg(ap, int);
382	for (n = 0; n < n_in; n++)
383	{
384		int *ptr = va_arg(ap, int *);
385		if (fd_in(fdc, ptr) < 0)
386		{
387			char msg[50];
388			snprintf(msg, sizeof(msg),
389				"cmd %02x failed at in byte %d of %d\n",
390				cmd, n + 1, n_in);
391			return fdc_err(fdc, msg);
392		}
393	}
394
395	return 0;
396}
397
398static int
399enable_fifo(fdc_p fdc)
400{
401	int i, j;
402
403	if ((fdc->flags & FDC_HAS_FIFO) == 0) {
404
405		/*
406		 * XXX:
407		 * Cannot use fd_cmd the normal way here, since
408		 * this might be an invalid command. Thus we send the
409		 * first byte, and check for an early turn of data directon.
410		 */
411
412		if (out_fdc(fdc, I8207X_CONFIGURE) < 0)
413			return fdc_err(fdc, "Enable FIFO failed\n");
414
415		/* If command is invalid, return */
416		j = 100000;
417		while ((i = fdsts_rd(fdc) & (NE7_DIO | NE7_RQM))
418		       != NE7_RQM && j-- > 0)
419			if (i == (NE7_DIO | NE7_RQM)) {
420				fdc_reset(fdc);
421				return FD_FAILED;
422			}
423		if (j<0 ||
424		    fd_cmd(fdc, 3,
425			   0, (fifo_threshold - 1) & 0xf, 0, 0) < 0) {
426			fdc_reset(fdc);
427			return fdc_err(fdc, "Enable FIFO failed\n");
428		}
429		fdc->flags |= FDC_HAS_FIFO;
430		return 0;
431	}
432	if (fd_cmd(fdc, 4,
433		   I8207X_CONFIGURE, 0, (fifo_threshold - 1) & 0xf, 0, 0) < 0)
434		return fdc_err(fdc, "Re-enable FIFO failed\n");
435	return 0;
436}
437
438static int
439fd_sense_drive_status(fdc_p fdc, int *st3p)
440{
441	int st3;
442
443	if (fd_cmd(fdc, 2, NE7CMD_SENSED, fdc->fdu, 1, &st3))
444	{
445		return fdc_err(fdc, "Sense Drive Status failed\n");
446	}
447	if (st3p)
448		*st3p = st3;
449
450	return 0;
451}
452
453static int
454fd_sense_int(fdc_p fdc, int *st0p, int *cylp)
455{
456	int cyl, st0, ret;
457
458	ret = fd_cmd(fdc, 1, NE7CMD_SENSEI, 1, &st0);
459	if (ret) {
460		(void)fdc_err(fdc,
461			      "sense intr err reading stat reg 0\n");
462		return ret;
463	}
464
465	if (st0p)
466		*st0p = st0;
467
468	if ((st0 & NE7_ST0_IC) == NE7_ST0_IC_IV) {
469		/*
470		 * There doesn't seem to have been an interrupt.
471		 */
472		return FD_NOT_VALID;
473	}
474
475	if (fd_in(fdc, &cyl) < 0) {
476		return fdc_err(fdc, "can't get cyl num\n");
477	}
478
479	if (cylp)
480		*cylp = cyl;
481
482	return 0;
483}
484
485
486static int
487fd_read_status(fdc_p fdc, int fdsu)
488{
489	int i, ret;
490
491	for (i = 0; i < 7; i++) {
492		/*
493		 * XXX types are poorly chosen.  Only bytes can by read
494		 * from the hardware, but fdc->status[] wants u_ints and
495		 * fd_in() gives ints.
496		 */
497		int status;
498
499		ret = fd_in(fdc, &status);
500		fdc->status[i] = status;
501		if (ret != 0)
502			break;
503	}
504
505	if (ret == 0)
506		fdc->flags |= FDC_STAT_VALID;
507	else
508		fdc->flags &= ~FDC_STAT_VALID;
509
510	return ret;
511}
512
513/****************************************************************************/
514/*                      autoconfiguration stuff                             */
515/****************************************************************************/
516
517static int
518fdc_alloc_resources(struct fdc_data *fdc)
519{
520	device_t dev;
521	int ispnp, ispcmcia;
522
523	dev = fdc->fdc_dev;
524	ispnp = (fdc->flags & FDC_ISPNP) != 0;
525	ispcmcia = (fdc->flags & FDC_ISPCMCIA) != 0;
526	fdc->rid_ioport = fdc->rid_irq = fdc->rid_drq = 0;
527	fdc->res_ioport = fdc->res_irq = fdc->res_drq = 0;
528
529	/*
530	 * On standard ISA, we don't just use an 8 port range
531	 * (e.g. 0x3f0-0x3f7) since that covers an IDE control
532	 * register at 0x3f6.
533	 *
534	 * Isn't PC hardware wonderful.
535	 *
536	 * The Y-E Data PCMCIA FDC doesn't have this problem, it
537	 * uses the register with offset 6 for pseudo-DMA, and the
538	 * one with offset 7 as control register.
539	 */
540	fdc->res_ioport = bus_alloc_resource(dev, SYS_RES_IOPORT,
541					     &fdc->rid_ioport, 0ul, ~0ul,
542					     ispcmcia ? 8 : (ispnp ? 1 : 6),
543					     RF_ACTIVE);
544	if (fdc->res_ioport == 0) {
545		device_printf(dev, "cannot reserve I/O port range\n");
546		return ENXIO;
547	}
548	fdc->portt = rman_get_bustag(fdc->res_ioport);
549	fdc->porth = rman_get_bushandle(fdc->res_ioport);
550
551	if (!ispcmcia) {
552		/*
553		 * Some BIOSen report the device at 0x3f2-0x3f5,0x3f7
554		 * and some at 0x3f0-0x3f5,0x3f7. We detect the former
555		 * by checking the size and adjust the port address
556		 * accordingly.
557		 */
558		if (bus_get_resource_count(dev, SYS_RES_IOPORT, 0) == 4)
559			fdc->port_off = -2;
560
561		/*
562		 * Register the control port range as rid 1 if it
563		 * isn't there already. Most PnP BIOSen will have
564		 * already done this but non-PnP configurations don't.
565		 *
566		 * And some (!!) report 0x3f2-0x3f5 and completely
567		 * leave out the control register!  It seems that some
568		 * non-antique controller chips have a different
569		 * method of programming the transfer speed which
570		 * doesn't require the control register, but it's
571		 * mighty bogus as the chip still responds to the
572		 * address for the control register.
573		 */
574		if (bus_get_resource_count(dev, SYS_RES_IOPORT, 1) == 0) {
575			u_long ctlstart;
576
577			/* Find the control port, usually 0x3f7 */
578			ctlstart = rman_get_start(fdc->res_ioport) +
579				fdc->port_off + 7;
580
581			bus_set_resource(dev, SYS_RES_IOPORT, 1, ctlstart, 1);
582		}
583
584		/*
585		 * Now (finally!) allocate the control port.
586		 */
587		fdc->rid_ctl = 1;
588		fdc->res_ctl = bus_alloc_resource(dev, SYS_RES_IOPORT,
589						  &fdc->rid_ctl,
590						  0ul, ~0ul, 1, RF_ACTIVE);
591		if (fdc->res_ctl == 0) {
592			device_printf(dev,
593				      "cannot reserve control I/O port range\n");
594			return ENXIO;
595		}
596		fdc->ctlt = rman_get_bustag(fdc->res_ctl);
597		fdc->ctlh = rman_get_bushandle(fdc->res_ctl);
598	}
599
600	fdc->res_irq = bus_alloc_resource(dev, SYS_RES_IRQ,
601					  &fdc->rid_irq, 0ul, ~0ul, 1,
602					  RF_ACTIVE);
603	if (fdc->res_irq == 0) {
604		device_printf(dev, "cannot reserve interrupt line\n");
605		return ENXIO;
606	}
607
608	if ((fdc->flags & FDC_NODMA) == 0) {
609		fdc->res_drq = bus_alloc_resource(dev, SYS_RES_DRQ,
610						  &fdc->rid_drq, 0ul, ~0ul, 1,
611						  RF_ACTIVE);
612		if (fdc->res_drq == 0) {
613			device_printf(dev, "cannot reserve DMA request line\n");
614			return ENXIO;
615		}
616		fdc->dmachan = fdc->res_drq->r_start;
617	}
618
619	return 0;
620}
621
622static void
623fdc_release_resources(struct fdc_data *fdc)
624{
625	device_t dev;
626
627	dev = fdc->fdc_dev;
628	if (fdc->res_irq != 0) {
629		bus_deactivate_resource(dev, SYS_RES_IRQ, fdc->rid_irq,
630					fdc->res_irq);
631		bus_release_resource(dev, SYS_RES_IRQ, fdc->rid_irq,
632				     fdc->res_irq);
633	}
634	if (fdc->res_ctl != 0) {
635		bus_deactivate_resource(dev, SYS_RES_IOPORT, fdc->rid_ctl,
636					fdc->res_ctl);
637		bus_release_resource(dev, SYS_RES_IOPORT, fdc->rid_ctl,
638				     fdc->res_ctl);
639	}
640	if (fdc->res_ioport != 0) {
641		bus_deactivate_resource(dev, SYS_RES_IOPORT, fdc->rid_ioport,
642					fdc->res_ioport);
643		bus_release_resource(dev, SYS_RES_IOPORT, fdc->rid_ioport,
644				     fdc->res_ioport);
645	}
646	if (fdc->res_drq != 0) {
647		bus_deactivate_resource(dev, SYS_RES_DRQ, fdc->rid_drq,
648					fdc->res_drq);
649		bus_release_resource(dev, SYS_RES_DRQ, fdc->rid_drq,
650				     fdc->res_drq);
651	}
652}
653
654/****************************************************************************/
655/*                      autoconfiguration stuff                             */
656/****************************************************************************/
657
658static struct isa_pnp_id fdc_ids[] = {
659	{0x0007d041, "PC standard floppy disk controller"}, /* PNP0700 */
660	{0x0107d041, "Standard floppy controller supporting MS Device Bay Spec"}, /* PNP0701 */
661	{0}
662};
663
664static int
665fdc_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
666{
667	struct fdc_ivars *ivars = device_get_ivars(child);
668
669	switch (which) {
670	case FDC_IVAR_FDUNIT:
671		*result = ivars->fdunit;
672		break;
673	default:
674		return ENOENT;
675	}
676	return 0;
677}
678
679/*
680 * fdc controller section.
681 */
682static int
683fdc_probe(device_t dev)
684{
685	int	error, ic_type;
686	struct	fdc_data *fdc;
687
688	fdc = device_get_softc(dev);
689	bzero(fdc, sizeof *fdc);
690	fdc->fdc_dev = dev;
691	fdc->fdctl_wr = fdctl_wr_isa;
692
693	/* Check pnp ids */
694	error = ISA_PNP_PROBE(device_get_parent(dev), dev, fdc_ids);
695	if (error == ENXIO)
696		return ENXIO;
697	if (error == 0)
698		fdc->flags |= FDC_ISPNP;
699
700	/* Attempt to allocate our resources for the duration of the probe */
701	error = fdc_alloc_resources(fdc);
702	if (error)
703		goto out;
704
705	/* First - lets reset the floppy controller */
706	fdout_wr(fdc, 0);
707	DELAY(100);
708	fdout_wr(fdc, FDO_FRST);
709
710	/* see if it can handle a command */
711	if (fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(3, 240),
712		   NE7_SPEC_2(2, 0), 0)) {
713		error = ENXIO;
714		goto out;
715	}
716
717	if (fd_cmd(fdc, 1, NE7CMD_VERSION, 1, &ic_type) == 0) {
718		ic_type = (u_char)ic_type;
719		switch (ic_type) {
720		case 0x80:
721			device_set_desc(dev, "NEC 765 or clone");
722			fdc->fdct = FDC_NE765;
723			break;
724		case 0x81:
725			device_set_desc(dev, "Intel 82077 or clone");
726			fdc->fdct = FDC_I82077;
727			break;
728		case 0x90:
729			device_set_desc(dev, "NEC 72065B or clone");
730			fdc->fdct = FDC_NE72065;
731			break;
732		default:
733			device_set_desc(dev, "generic floppy controller");
734			fdc->fdct = FDC_UNKNOWN;
735			break;
736		}
737	}
738
739out:
740	fdc_release_resources(fdc);
741	return (error);
742}
743
744#if NCARD > 0
745
746static int
747fdc_pccard_probe(device_t dev)
748{
749	int	error;
750	struct	fdc_data *fdc;
751
752	fdc = device_get_softc(dev);
753	bzero(fdc, sizeof *fdc);
754	fdc->fdc_dev = dev;
755	fdc->fdctl_wr = fdctl_wr_pcmcia;
756
757	fdc->flags |= FDC_ISPCMCIA | FDC_NODMA;
758
759	/* Attempt to allocate our resources for the duration of the probe */
760	error = fdc_alloc_resources(fdc);
761	if (error)
762		goto out;
763
764	/* First - lets reset the floppy controller */
765	fdout_wr(fdc, 0);
766	DELAY(100);
767	fdout_wr(fdc, FDO_FRST);
768
769	/* see if it can handle a command */
770	if (fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(3, 240),
771		   NE7_SPEC_2(2, 0), 0)) {
772		error = ENXIO;
773		goto out;
774	}
775
776	device_set_desc(dev, "Y-E Data PCMCIA floppy");
777	fdc->fdct = FDC_NE765;
778
779out:
780	fdc_release_resources(fdc);
781	return (error);
782}
783
784static int
785fdc_pccard_detach(device_t dev)
786{
787	struct	fdc_data *fdc;
788	int	error;
789
790	fdc = device_get_softc(dev);
791
792	/* have our children detached first */
793	if ((error = bus_generic_detach(dev)))
794		return (error);
795
796	if ((fdc->flags & FDC_ATTACHED) == 0) {
797		device_printf(dev, "already unloaded\n");
798		return (0);
799	}
800	fdc->flags &= ~FDC_ATTACHED;
801
802	BUS_TEARDOWN_INTR(device_get_parent(dev), dev, fdc->res_irq,
803			  fdc->fdc_intr);
804	fdc_release_resources(fdc);
805	device_printf(dev, "unload\n");
806	return (0);
807}
808
809#endif /* NCARD > 0 */
810
811/*
812 * Add a child device to the fdc controller.  It will then be probed etc.
813 */
814static void
815fdc_add_child(device_t dev, const char *name, int unit)
816{
817	int	disabled;
818	struct fdc_ivars *ivar;
819	device_t child;
820
821	ivar = malloc(sizeof *ivar, M_DEVBUF /* XXX */, M_NOWAIT | M_ZERO);
822	if (ivar == NULL)
823		return;
824	if (resource_int_value(name, unit, "drive", &ivar->fdunit) != 0)
825		ivar->fdunit = 0;
826	child = device_add_child(dev, name, unit);
827	if (child == NULL)
828		return;
829	device_set_ivars(child, ivar);
830	if (resource_int_value(name, unit, "disabled", &disabled) == 0
831	    && disabled != 0)
832		device_disable(child);
833}
834
835static int
836fdc_attach(device_t dev)
837{
838	struct	fdc_data *fdc;
839	int	i, error;
840	const char *name;
841
842	fdc = device_get_softc(dev);
843	error = fdc_alloc_resources(fdc);
844	if (error) {
845		device_printf(dev, "cannot re-aquire resources\n");
846		return error;
847	}
848	error = BUS_SETUP_INTR(device_get_parent(dev), dev, fdc->res_irq,
849			       INTR_TYPE_BIO | INTR_ENTROPY, fdc_intr, fdc,
850			       &fdc->fdc_intr);
851	if (error) {
852		device_printf(dev, "cannot setup interrupt\n");
853		return error;
854	}
855	fdc->fdcu = device_get_unit(dev);
856	fdc->flags |= FDC_ATTACHED;
857
858	if ((fdc->flags & FDC_NODMA) == 0) {
859		/* Acquire the DMA channel forever, The driver will do the rest */
860				/* XXX should integrate with rman */
861		isa_dma_acquire(fdc->dmachan);
862		isa_dmainit(fdc->dmachan, 128 << 3 /* XXX max secsize */);
863	}
864	fdc->state = DEVIDLE;
865
866	/* reset controller, turn motor off, clear fdout mirror reg */
867	fdout_wr(fdc, ((fdc->fdout = 0)));
868	bioq_init(&fdc->head);
869
870	/*
871	 * Probe and attach any children.  We should probably detect
872	 * devices from the BIOS unless overridden.
873	 */
874	name = device_get_nameunit(dev);
875	i = -1;
876	while ((i = resource_query_string(i, "at", name)) != -1)
877		fdc_add_child(dev, resource_query_name(i),
878			       resource_query_unit(i));
879
880	return (bus_generic_attach(dev));
881}
882
883static int
884fdc_print_child(device_t me, device_t child)
885{
886	int retval = 0;
887
888	retval += bus_print_child_header(me, child);
889	retval += printf(" on %s drive %d\n", device_get_nameunit(me),
890	       fdc_get_fdunit(child));
891
892	return (retval);
893}
894
895static device_method_t fdc_methods[] = {
896	/* Device interface */
897	DEVMETHOD(device_probe,		fdc_probe),
898	DEVMETHOD(device_attach,	fdc_attach),
899	DEVMETHOD(device_detach,	bus_generic_detach),
900	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
901	DEVMETHOD(device_suspend,	bus_generic_suspend),
902	DEVMETHOD(device_resume,	bus_generic_resume),
903
904	/* Bus interface */
905	DEVMETHOD(bus_print_child,	fdc_print_child),
906	DEVMETHOD(bus_read_ivar,	fdc_read_ivar),
907	/* Our children never use any other bus interface methods. */
908
909	{ 0, 0 }
910};
911
912static driver_t fdc_driver = {
913	"fdc",
914	fdc_methods,
915	sizeof(struct fdc_data)
916};
917
918DRIVER_MODULE(fdc, isa, fdc_driver, fdc_devclass, 0, 0);
919
920#if NCARD > 0
921
922static device_method_t fdc_pccard_methods[] = {
923	/* Device interface */
924	DEVMETHOD(device_probe,		fdc_pccard_probe),
925	DEVMETHOD(device_attach,	fdc_attach),
926	DEVMETHOD(device_detach,	fdc_pccard_detach),
927	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
928	DEVMETHOD(device_suspend,	bus_generic_suspend),
929	DEVMETHOD(device_resume,	bus_generic_resume),
930
931	/* Bus interface */
932	DEVMETHOD(bus_print_child,	fdc_print_child),
933	DEVMETHOD(bus_read_ivar,	fdc_read_ivar),
934	/* Our children never use any other bus interface methods. */
935
936	{ 0, 0 }
937};
938
939static driver_t fdc_pccard_driver = {
940	"fdc",
941	fdc_pccard_methods,
942	sizeof(struct fdc_data)
943};
944
945DRIVER_MODULE(fdc, pccard, fdc_pccard_driver, fdc_devclass, 0, 0);
946
947#endif /* NCARD > 0 */
948
949static void fd_clone __P((void *arg, char *name, int namelen, dev_t *dev));
950
951static struct {
952	char *match;
953	int minor;
954	int link;
955} fd_suffix[] = {
956	{ "a",		0,	1 },
957	{ "b",		0,	1 },
958	{ "c",		0,	1 },
959	{ "d",		0,	1 },
960	{ "e",		0,	1 },
961	{ "f",		0,	1 },
962	{ "g",		0,	1 },
963	{ "h",		0,	1 },
964	{ ".1720",	1,	0 },
965	{ ".1480",	2,	0 },
966	{ ".1440",	3,	0 },
967	{ ".1200",	4,	0 },
968	{ ".820",	5,	0 },
969	{ ".800",	6,	0 },
970	{ ".720",	7,	0 },
971	{ ".360",	8,	0 },
972	{ ".640",	9,	0 },
973	{ ".1232",	10,	0 },
974	{ 0, 0 }
975};
976static void
977fd_clone(arg, name, namelen, dev)
978	void *arg;
979	char *name;
980	int namelen;
981	dev_t *dev;
982{
983	int u, d, i;
984	char *n;
985	dev_t pdev;
986
987	if (*dev != NODEV)
988		return;
989	if (dev_stdclone(name, &n, "fd", &u) != 2)
990		return;
991	for (i = 0; ; i++) {
992		if (fd_suffix[i].match == NULL)
993			return;
994		if (strcmp(n, fd_suffix[i].match))
995			continue;
996		d = fd_suffix[i].minor;
997		break;
998	}
999	if (fd_suffix[i].link == 0) {
1000		*dev = make_dev(&fd_cdevsw, (u << 6) + d,
1001			UID_ROOT, GID_OPERATOR, 0640, name);
1002	} else {
1003		pdev = makedev(fd_cdevsw.d_maj, (u << 6) + d);
1004		*dev = make_dev_alias(pdev, name);
1005	}
1006}
1007
1008/******************************************************************/
1009/*
1010 * devices attached to the controller section.
1011 */
1012static int
1013fd_probe(device_t dev)
1014{
1015	int	i;
1016	u_int	fdt, st0, st3;
1017	struct	fd_data *fd;
1018	struct	fdc_data *fdc;
1019	fdsu_t	fdsu;
1020	static int fd_fifo = 0;
1021
1022	fdsu = *(int *)device_get_ivars(dev); /* xxx cheat a bit... */
1023	fd = device_get_softc(dev);
1024	fdc = device_get_softc(device_get_parent(dev));
1025
1026	bzero(fd, sizeof *fd);
1027	fd->dev = dev;
1028	fd->fdc = fdc;
1029	fd->fdsu = fdsu;
1030	fd->fdu = device_get_unit(dev);
1031
1032#ifdef __i386__
1033	/* look up what bios thinks we have */
1034	switch (fd->fdu) {
1035	case 0:
1036		if ((fdc->flags & FDC_ISPCMCIA))
1037			fdt = RTCFDT_144M;
1038		else if (device_get_flags(fdc->fdc_dev) & FDC_PRETEND_D0)
1039			fdt = RTCFDT_144M | RTCFDT_144M_PRETENDED;
1040		else
1041			fdt = (rtcin(RTC_FDISKETTE) & 0xf0);
1042		break;
1043	case 1:
1044		fdt = ((rtcin(RTC_FDISKETTE) << 4) & 0xf0);
1045		break;
1046	default:
1047		fdt = RTCFDT_NONE;
1048		break;
1049	}
1050#else
1051	fdt = RTCFDT_144M;	/* XXX probably */
1052#endif
1053
1054	/* is there a unit? */
1055	if (fdt == RTCFDT_NONE)
1056		return (ENXIO);
1057
1058	/* select it */
1059	set_motor(fdc, fdsu, TURNON);
1060	DELAY(1000000);	/* 1 sec */
1061
1062	/* XXX This doesn't work before the first set_motor() */
1063	if (fd_fifo == 0 && fdc->fdct != FDC_NE765 && fdc->fdct != FDC_UNKNOWN
1064	    && (device_get_flags(fdc->fdc_dev) & FDC_NO_FIFO) == 0
1065	    && enable_fifo(fdc) == 0) {
1066		device_printf(device_get_parent(dev),
1067		    "FIFO enabled, %d bytes threshold\n", fifo_threshold);
1068	}
1069	fd_fifo = 1;
1070
1071	if ((fd_cmd(fdc, 2, NE7CMD_SENSED, fdsu, 1, &st3) == 0)
1072	    && (st3 & NE7_ST3_T0)) {
1073		/* if at track 0, first seek inwards */
1074		/* seek some steps: */
1075		fd_cmd(fdc, 3, NE7CMD_SEEK, fdsu, 10, 0);
1076		DELAY(300000); /* ...wait a moment... */
1077		fd_sense_int(fdc, 0, 0); /* make ctrlr happy */
1078	}
1079
1080	/* If we're at track 0 first seek inwards. */
1081	if ((fd_sense_drive_status(fdc, &st3) == 0) && (st3 & NE7_ST3_T0)) {
1082		/* Seek some steps... */
1083		if (fd_cmd(fdc, 3, NE7CMD_SEEK, fdsu, 10, 0) == 0) {
1084			/* ...wait a moment... */
1085			DELAY(300000);
1086			/* make ctrlr happy: */
1087			fd_sense_int(fdc, 0, 0);
1088		}
1089	}
1090
1091	for (i = 0; i < 2; i++) {
1092		/*
1093		 * we must recalibrate twice, just in case the
1094		 * heads have been beyond cylinder 76, since most
1095		 * FDCs still barf when attempting to recalibrate
1096		 * more than 77 steps
1097		 */
1098		/* go back to 0: */
1099		if (fd_cmd(fdc, 2, NE7CMD_RECAL, fdsu, 0) == 0) {
1100			/* a second being enough for full stroke seek*/
1101			DELAY(i == 0 ? 1000000 : 300000);
1102
1103			/* anything responding? */
1104			if (fd_sense_int(fdc, &st0, 0) == 0 &&
1105			    (st0 & NE7_ST0_EC) == 0)
1106				break; /* already probed succesfully */
1107		}
1108	}
1109
1110	set_motor(fdc, fdsu, TURNOFF);
1111
1112	if (st0 & NE7_ST0_EC) /* no track 0 -> no drive present */
1113		return (ENXIO);
1114
1115	fd->track = FD_NO_TRACK;
1116	fd->fdc = fdc;
1117	fd->fdsu = fdsu;
1118	fd->options = 0;
1119	callout_handle_init(&fd->toffhandle);
1120	callout_handle_init(&fd->tohandle);
1121
1122	switch (fdt) {
1123	case RTCFDT_12M:
1124		device_set_desc(dev, "1200-KB 5.25\" drive");
1125		fd->type = FD_1200;
1126		break;
1127	case RTCFDT_144M | RTCFDT_144M_PRETENDED:
1128		device_set_desc(dev, "config-pretended 1440-MB 3.5\" drive");
1129		fdt = RTCFDT_144M;
1130		fd->type = FD_1440;
1131	case RTCFDT_144M:
1132		device_set_desc(dev, "1440-KB 3.5\" drive");
1133		fd->type = FD_1440;
1134		break;
1135	case RTCFDT_288M:
1136	case RTCFDT_288M_1:
1137		device_set_desc(dev, "2880-KB 3.5\" drive (in 1440-KB mode)");
1138		fd->type = FD_1440;
1139		break;
1140	case RTCFDT_360K:
1141		device_set_desc(dev, "360-KB 5.25\" drive");
1142		fd->type = FD_360;
1143		break;
1144	case RTCFDT_720K:
1145		printf("720-KB 3.5\" drive");
1146		fd->type = FD_720;
1147		break;
1148	default:
1149		return (ENXIO);
1150	}
1151	return (0);
1152}
1153
1154static int
1155fd_attach(device_t dev)
1156{
1157	struct	fd_data *fd;
1158	static int cdevsw_add_done = 0;
1159
1160	fd = device_get_softc(dev);
1161
1162	if (!cdevsw_add_done) {
1163		cdevsw_add(&fd_cdevsw);	/* XXX */
1164		cdevsw_add_done++;
1165	}
1166	EVENTHANDLER_REGISTER(dev_clone, fd_clone, 0, 1000);
1167	make_dev(&fd_cdevsw, (fd->fdu << 6),
1168		UID_ROOT, GID_OPERATOR, 0640, "fd%d", fd->fdu);
1169
1170	/*
1171	 * Export the drive to the devstat interface.
1172	 */
1173	devstat_add_entry(&fd->device_stats, device_get_name(dev),
1174			  device_get_unit(dev), 512, DEVSTAT_NO_ORDERED_TAGS,
1175			  DEVSTAT_TYPE_FLOPPY | DEVSTAT_TYPE_IF_OTHER,
1176			  DEVSTAT_PRIORITY_FD);
1177	return (0);
1178}
1179
1180static int
1181fd_detach(device_t dev)
1182{
1183	struct	fd_data *fd;
1184
1185	fd = device_get_softc(dev);
1186	untimeout(fd_turnoff, fd, fd->toffhandle);
1187
1188	return (0);
1189}
1190
1191static device_method_t fd_methods[] = {
1192	/* Device interface */
1193	DEVMETHOD(device_probe,		fd_probe),
1194	DEVMETHOD(device_attach,	fd_attach),
1195	DEVMETHOD(device_detach,	fd_detach),
1196	DEVMETHOD(device_shutdown,	bus_generic_shutdown),
1197	DEVMETHOD(device_suspend,	bus_generic_suspend), /* XXX */
1198	DEVMETHOD(device_resume,	bus_generic_resume), /* XXX */
1199
1200	{ 0, 0 }
1201};
1202
1203static driver_t fd_driver = {
1204	"fd",
1205	fd_methods,
1206	sizeof(struct fd_data)
1207};
1208
1209DRIVER_MODULE(fd, fdc, fd_driver, fd_devclass, 0, 0);
1210
1211/****************************************************************************/
1212/*                            motor control stuff                           */
1213/*		remember to not deselect the drive we're working on         */
1214/****************************************************************************/
1215static void
1216set_motor(struct fdc_data *fdc, int fdsu, int turnon)
1217{
1218	int fdout = fdc->fdout;
1219	int needspecify = 0;
1220
1221	if(turnon) {
1222		fdout &= ~FDO_FDSEL;
1223		fdout |= (FDO_MOEN0 << fdsu) + fdsu;
1224	} else
1225		fdout &= ~(FDO_MOEN0 << fdsu);
1226
1227	if(!turnon
1228	   && (fdout & (FDO_MOEN0+FDO_MOEN1+FDO_MOEN2+FDO_MOEN3)) == 0)
1229		/* gonna turn off the last drive, put FDC to bed */
1230		fdout &= ~ (FDO_FRST|FDO_FDMAEN);
1231	else {
1232		/* make sure controller is selected and specified */
1233		if((fdout & (FDO_FRST|FDO_FDMAEN)) == 0)
1234			needspecify = 1;
1235		fdout |= (FDO_FRST|FDO_FDMAEN);
1236	}
1237
1238	fdout_wr(fdc, fdout);
1239	fdc->fdout = fdout;
1240	TRACE1("[0x%x->FDOUT]", fdout);
1241
1242	if (needspecify) {
1243		/*
1244		 * XXX
1245		 * special case: since we have just woken up the FDC
1246		 * from its sleep, we silently assume the command will
1247		 * be accepted, and do not test for a timeout
1248		 */
1249		(void)fd_cmd(fdc, 3, NE7CMD_SPECIFY,
1250			     NE7_SPEC_1(3, 240), NE7_SPEC_2(2, 0),
1251			     0);
1252		if (fdc->flags & FDC_HAS_FIFO)
1253			(void) enable_fifo(fdc);
1254	}
1255}
1256
1257static void
1258fd_turnoff(void *xfd)
1259{
1260	int	s;
1261	fd_p fd = xfd;
1262
1263	TRACE1("[fd%d: turnoff]", fd->fdu);
1264
1265	s = splbio();
1266	/*
1267	 * Don't turn off the motor yet if the drive is active.
1268	 *
1269	 * If we got here, this could only mean we missed an interrupt.
1270	 * This can e. g. happen on the Y-E Date PCMCIA floppy controller
1271	 * after a controller reset.  Just schedule a pseudo-interrupt
1272	 * so the state machine gets re-entered.
1273	 */
1274	if (fd->fdc->state != DEVIDLE && fd->fdc->fdu == fd->fdu) {
1275		fdc_intr(fd->fdc);
1276		splx(s);
1277		return;
1278	}
1279
1280	fd->flags &= ~FD_MOTOR;
1281	set_motor(fd->fdc, fd->fdsu, TURNOFF);
1282	splx(s);
1283}
1284
1285static void
1286fd_motor_on(void *xfd)
1287{
1288	int	s;
1289	fd_p fd = xfd;
1290
1291	s = splbio();
1292	fd->flags &= ~FD_MOTOR_WAIT;
1293	if((fd->fdc->fd == fd) && (fd->fdc->state == MOTORWAIT))
1294	{
1295		fdc_intr(fd->fdc);
1296	}
1297	splx(s);
1298}
1299
1300static void
1301fd_turnon(fd_p fd)
1302{
1303	if(!(fd->flags & FD_MOTOR))
1304	{
1305		fd->flags |= (FD_MOTOR + FD_MOTOR_WAIT);
1306		set_motor(fd->fdc, fd->fdsu, TURNON);
1307		timeout(fd_motor_on, fd, hz); /* in 1 sec its ok */
1308	}
1309}
1310
1311static void
1312fdc_reset(fdc_p fdc)
1313{
1314	/* Try a reset, keep motor on */
1315	fdout_wr(fdc, fdc->fdout & ~(FDO_FRST|FDO_FDMAEN));
1316	TRACE1("[0x%x->FDOUT]", fdc->fdout & ~(FDO_FRST|FDO_FDMAEN));
1317	DELAY(100);
1318	/* enable FDC, but defer interrupts a moment */
1319	fdout_wr(fdc, fdc->fdout & ~FDO_FDMAEN);
1320	TRACE1("[0x%x->FDOUT]", fdc->fdout & ~FDO_FDMAEN);
1321	DELAY(100);
1322	fdout_wr(fdc, fdc->fdout);
1323	TRACE1("[0x%x->FDOUT]", fdc->fdout);
1324
1325	/* XXX after a reset, silently believe the FDC will accept commands */
1326	(void)fd_cmd(fdc, 3, NE7CMD_SPECIFY,
1327		     NE7_SPEC_1(3, 240), NE7_SPEC_2(2, 0),
1328		     0);
1329	if (fdc->flags & FDC_HAS_FIFO)
1330		(void) enable_fifo(fdc);
1331}
1332
1333/****************************************************************************/
1334/*                             fdc in/out                                   */
1335/****************************************************************************/
1336int
1337in_fdc(struct fdc_data *fdc)
1338{
1339	int i, j = 100000;
1340	while ((i = fdsts_rd(fdc) & (NE7_DIO|NE7_RQM))
1341		!= (NE7_DIO|NE7_RQM) && j-- > 0)
1342		if (i == NE7_RQM)
1343			return fdc_err(fdc, "ready for output in input\n");
1344	if (j <= 0)
1345		return fdc_err(fdc, bootverbose? "input ready timeout\n": 0);
1346#ifdef	FDC_DEBUG
1347	i = fddata_rd(fdc);
1348	TRACE1("[FDDATA->0x%x]", (unsigned char)i);
1349	return(i);
1350#else	/* !FDC_DEBUG */
1351	return fddata_rd(fdc);
1352#endif	/* FDC_DEBUG */
1353}
1354
1355/*
1356 * fd_in: Like in_fdc, but allows you to see if it worked.
1357 */
1358static int
1359fd_in(struct fdc_data *fdc, int *ptr)
1360{
1361	int i, j = 100000;
1362	while ((i = fdsts_rd(fdc) & (NE7_DIO|NE7_RQM))
1363		!= (NE7_DIO|NE7_RQM) && j-- > 0)
1364		if (i == NE7_RQM)
1365			return fdc_err(fdc, "ready for output in input\n");
1366	if (j <= 0)
1367		return fdc_err(fdc, bootverbose? "input ready timeout\n": 0);
1368#ifdef	FDC_DEBUG
1369	i = fddata_rd(fdc);
1370	TRACE1("[FDDATA->0x%x]", (unsigned char)i);
1371	*ptr = i;
1372	return 0;
1373#else	/* !FDC_DEBUG */
1374	i = fddata_rd(fdc);
1375	if (ptr)
1376		*ptr = i;
1377	return 0;
1378#endif	/* FDC_DEBUG */
1379}
1380
1381int
1382out_fdc(struct fdc_data *fdc, int x)
1383{
1384	int i;
1385
1386	/* Check that the direction bit is set */
1387	i = 100000;
1388	while ((fdsts_rd(fdc) & NE7_DIO) && i-- > 0);
1389	if (i <= 0) return fdc_err(fdc, "direction bit not set\n");
1390
1391	/* Check that the floppy controller is ready for a command */
1392	i = 100000;
1393	while ((fdsts_rd(fdc) & NE7_RQM) == 0 && i-- > 0);
1394	if (i <= 0)
1395		return fdc_err(fdc, bootverbose? "output ready timeout\n": 0);
1396
1397	/* Send the command and return */
1398	fddata_wr(fdc, x);
1399	TRACE1("[0x%x->FDDATA]", x);
1400	return (0);
1401}
1402
1403/****************************************************************************/
1404/*                           fdopen/fdclose                                 */
1405/****************************************************************************/
1406int
1407Fdopen(dev_t dev, int flags, int mode, struct proc *p)
1408{
1409 	fdu_t fdu = FDUNIT(minor(dev));
1410	int type = FDTYPE(minor(dev));
1411	fd_p	fd;
1412	fdc_p	fdc;
1413
1414	/* check bounds */
1415	if ((fd = devclass_get_softc(fd_devclass, fdu)) == 0)
1416		return (ENXIO);
1417	fdc = fd->fdc;
1418	if ((fdc == NULL) || (fd->type == NO_TYPE))
1419		return (ENXIO);
1420	if (type > NUMDENS)
1421		return (ENXIO);
1422	if (type == 0)
1423		type = fd->type;
1424	else {
1425		/*
1426		 * For each type of basic drive, make sure we are trying
1427		 * to open a type it can do,
1428		 */
1429		if (type != fd->type) {
1430			switch (fd->type) {
1431			case FD_360:
1432				return (ENXIO);
1433			case FD_720:
1434				if (   type != FD_820
1435				    && type != FD_800
1436				    && type != FD_640
1437				   )
1438					return (ENXIO);
1439				break;
1440			case FD_1200:
1441				switch (type) {
1442				case FD_1480:
1443					type = FD_1480in5_25;
1444					break;
1445				case FD_1440:
1446					type = FD_1440in5_25;
1447					break;
1448				case FD_1232:
1449					break;
1450				case FD_820:
1451					type = FD_820in5_25;
1452					break;
1453				case FD_800:
1454					type = FD_800in5_25;
1455					break;
1456				case FD_720:
1457					type = FD_720in5_25;
1458					break;
1459				case FD_640:
1460					type = FD_640in5_25;
1461					break;
1462				case FD_360:
1463					type = FD_360in5_25;
1464					break;
1465				default:
1466					return(ENXIO);
1467				}
1468				break;
1469			case FD_1440:
1470				if (   type != FD_1720
1471				    && type != FD_1480
1472				    && type != FD_1200
1473				    && type != FD_820
1474				    && type != FD_800
1475				    && type != FD_720
1476				    && type != FD_640
1477				    )
1478					return(ENXIO);
1479				break;
1480			}
1481		}
1482	}
1483	fd->ft = fd_types + type - 1;
1484	fd->flags |= FD_OPEN;
1485
1486	return 0;
1487}
1488
1489int
1490fdclose(dev_t dev, int flags, int mode, struct proc *p)
1491{
1492 	fdu_t fdu = FDUNIT(minor(dev));
1493	struct fd_data *fd;
1494
1495	fd = devclass_get_softc(fd_devclass, fdu);
1496	fd->flags &= ~FD_OPEN;
1497	fd->options &= ~FDOPT_NORETRY;
1498
1499	return (0);
1500}
1501
1502/****************************************************************************/
1503/*                               fdstrategy                                 */
1504/****************************************************************************/
1505void
1506fdstrategy(struct bio *bp)
1507{
1508	unsigned nblocks, blknum, cando;
1509 	int	s;
1510 	fdu_t	fdu;
1511 	fdc_p	fdc;
1512 	fd_p	fd;
1513	size_t	fdblk;
1514
1515 	fdu = FDUNIT(minor(bp->bio_dev));
1516	fd = devclass_get_softc(fd_devclass, fdu);
1517	if (fd == 0)
1518		panic("fdstrategy: buf for nonexistent device (%#lx, %#lx)",
1519		      (u_long)major(bp->bio_dev), (u_long)minor(bp->bio_dev));
1520	fdc = fd->fdc;
1521	if (fd->type == NO_TYPE) {
1522		bp->bio_error = ENXIO;
1523		bp->bio_flags |= BIO_ERROR;
1524		goto bad;
1525	};
1526
1527	fdblk = 128 << (fd->ft->secsize);
1528	if (!(bp->bio_cmd & BIO_FORMAT)) {
1529		if (bp->bio_blkno < 0) {
1530			printf(
1531		"fd%d: fdstrat: bad request blkno = %lu, bcount = %ld\n",
1532			       fdu, (u_long)bp->bio_blkno, bp->bio_bcount);
1533			bp->bio_error = EINVAL;
1534			bp->bio_flags |= BIO_ERROR;
1535			goto bad;
1536		}
1537		if ((bp->bio_bcount % fdblk) != 0) {
1538			bp->bio_error = EINVAL;
1539			bp->bio_flags |= BIO_ERROR;
1540			goto bad;
1541		}
1542	}
1543
1544	/*
1545	 * Set up block calculations.
1546	 */
1547	if (bp->bio_blkno > 20000000) {
1548		/*
1549		 * Reject unreasonably high block number, prevent the
1550		 * multiplication below from overflowing.
1551		 */
1552		bp->bio_error = EINVAL;
1553		bp->bio_flags |= BIO_ERROR;
1554		goto bad;
1555	}
1556	blknum = (unsigned) bp->bio_blkno * DEV_BSIZE/fdblk;
1557 	nblocks = fd->ft->size;
1558	bp->bio_resid = 0;
1559	if (blknum + (bp->bio_bcount / fdblk) > nblocks) {
1560		if (blknum <= nblocks) {
1561			cando = (nblocks - blknum) * fdblk;
1562			bp->bio_resid = bp->bio_bcount - cando;
1563			if (cando == 0)
1564				goto bad;	/* not actually bad but EOF */
1565		} else {
1566			bp->bio_error = EINVAL;
1567			bp->bio_flags |= BIO_ERROR;
1568			goto bad;
1569		}
1570	}
1571 	bp->bio_pblkno = bp->bio_blkno;
1572	s = splbio();
1573	bioqdisksort(&fdc->head, bp);
1574	untimeout(fd_turnoff, fd, fd->toffhandle); /* a good idea */
1575
1576	/* Tell devstat we are starting on the transaction */
1577	devstat_start_transaction(&fd->device_stats);
1578	device_busy(fd->dev);
1579
1580	fdstart(fdc);
1581	splx(s);
1582	return;
1583
1584bad:
1585	biodone(bp);
1586}
1587
1588/***************************************************************\
1589*				fdstart				*
1590* We have just queued something.. if the controller is not busy	*
1591* then simulate the case where it has just finished a command	*
1592* So that it (the interrupt routine) looks on the queue for more*
1593* work to do and picks up what we just added.			*
1594* If the controller is already busy, we need do nothing, as it	*
1595* will pick up our work when the present work completes		*
1596\***************************************************************/
1597static void
1598fdstart(struct fdc_data *fdc)
1599{
1600	int s;
1601
1602	s = splbio();
1603	if(fdc->state == DEVIDLE)
1604	{
1605		fdc_intr(fdc);
1606	}
1607	splx(s);
1608}
1609
1610static void
1611fd_iotimeout(void *xfdc)
1612{
1613 	fdc_p fdc;
1614	int s;
1615
1616	fdc = xfdc;
1617	TRACE1("fd%d[fd_iotimeout()]", fdc->fdu);
1618
1619	/*
1620	 * Due to IBM's brain-dead design, the FDC has a faked ready
1621	 * signal, hardwired to ready == true. Thus, any command
1622	 * issued if there's no diskette in the drive will _never_
1623	 * complete, and must be aborted by resetting the FDC.
1624	 * Many thanks, Big Blue!
1625	 * The FDC must not be reset directly, since that would
1626	 * interfere with the state machine.  Instead, pretend that
1627	 * the command completed but was invalid.  The state machine
1628	 * will reset the FDC and retry once.
1629	 */
1630	s = splbio();
1631	fdc->status[0] = NE7_ST0_IC_IV;
1632	fdc->flags &= ~FDC_STAT_VALID;
1633	fdc->state = IOTIMEDOUT;
1634	fdc_intr(fdc);
1635	splx(s);
1636}
1637
1638/* just ensure it has the right spl */
1639static void
1640fd_pseudointr(void *xfdc)
1641{
1642	int	s;
1643
1644	s = splbio();
1645	fdc_intr(xfdc);
1646	splx(s);
1647}
1648
1649/***********************************************************************\
1650*                                 fdintr				*
1651* keep calling the state machine until it returns a 0			*
1652* ALWAYS called at SPLBIO 						*
1653\***********************************************************************/
1654static void
1655fdc_intr(void *xfdc)
1656{
1657	fdc_p fdc = xfdc;
1658	while(fdstate(fdc))
1659		;
1660}
1661
1662/*
1663 * magic pseudo-DMA initialization for YE FDC. Sets count and
1664 * direction
1665 */
1666#define SET_BCDR(fdc,wr,cnt,port) \
1667	bus_space_write_1(fdc->portt, fdc->porth, fdc->port_off + port,	 \
1668	    ((cnt)-1) & 0xff);						 \
1669	bus_space_write_1(fdc->portt, fdc->porth, fdc->port_off + port + 1, \
1670	    ((wr ? 0x80 : 0) | ((((cnt)-1) >> 8) & 0x7f)));
1671
1672/*
1673 * fdcpio(): perform programmed IO read/write for YE PCMCIA floppy
1674 */
1675static int fdcpio(fdc_p fdc, long flags, caddr_t addr, u_int count)
1676{
1677	u_char *cptr = (u_char *)addr;
1678
1679	if (flags == BIO_READ) {
1680		if (fdc->state != PIOREAD) {
1681			fdc->state = PIOREAD;
1682			return(0);
1683		};
1684		SET_BCDR(fdc, 0, count, 0);
1685		bus_space_read_multi_1(fdc->portt, fdc->porth, fdc->port_off +
1686		    FDC_YE_DATAPORT, cptr, count);
1687	} else {
1688		bus_space_write_multi_1(fdc->portt, fdc->porth, fdc->port_off +
1689		    FDC_YE_DATAPORT, cptr, count);
1690		SET_BCDR(fdc, 0, count, 0);
1691	};
1692	return(1);
1693}
1694
1695/***********************************************************************\
1696* The controller state machine.						*
1697* if it returns a non zero value, it should be called again immediatly	*
1698\***********************************************************************/
1699static int
1700fdstate(fdc_p fdc)
1701{
1702	int read, format, head, i, sec = 0, sectrac, st0, cyl, st3, idf;
1703	unsigned blknum = 0, b_cylinder = 0;
1704	fdu_t fdu = fdc->fdu;
1705	fd_p fd;
1706	register struct bio *bp;
1707	struct fd_formb *finfo = NULL;
1708	size_t fdblk;
1709
1710	bp = fdc->bp;
1711	if (bp == NULL) {
1712		bp = bioq_first(&fdc->head);
1713		if (bp != NULL) {
1714			bioq_remove(&fdc->head, bp);
1715			fdc->bp = bp;
1716		}
1717	}
1718	if (bp == NULL) {
1719		/***********************************************\
1720		* nothing left for this controller to do	*
1721		* Force into the IDLE state,			*
1722		\***********************************************/
1723		fdc->state = DEVIDLE;
1724		if (fdc->fd) {
1725			device_printf(fdc->fdc_dev,
1726			    "unexpected valid fd pointer\n");
1727			fdc->fd = (fd_p) 0;
1728			fdc->fdu = -1;
1729		}
1730		TRACE1("[fdc%d IDLE]", fdc->fdcu);
1731 		return (0);
1732	}
1733	fdu = FDUNIT(minor(bp->bio_dev));
1734	fd = devclass_get_softc(fd_devclass, fdu);
1735	fdblk = 128 << fd->ft->secsize;
1736	if (fdc->fd && (fd != fdc->fd))
1737		device_printf(fd->dev, "confused fd pointers\n");
1738	read = bp->bio_cmd == BIO_READ;
1739	if (read)
1740		idf = ISADMA_READ;
1741	else
1742		idf = ISADMA_WRITE;
1743	format = bp->bio_cmd & BIO_FORMAT;
1744	if (format) {
1745		finfo = (struct fd_formb *)bp->bio_data;
1746		fd->skip = (char *)&(finfo->fd_formb_cylno(0))
1747			- (char *)finfo;
1748	}
1749	if (fdc->state == DOSEEK || fdc->state == SEEKCOMPLETE) {
1750		blknum = (unsigned) bp->bio_pblkno * DEV_BSIZE/fdblk +
1751			fd->skip/fdblk;
1752		b_cylinder = blknum / (fd->ft->sectrac * fd->ft->heads);
1753	}
1754	TRACE1("fd%d", fdu);
1755	TRACE1("[%s]", fdstates[fdc->state]);
1756	TRACE1("(0x%x)", fd->flags);
1757	untimeout(fd_turnoff, fd, fd->toffhandle);
1758	fd->toffhandle = timeout(fd_turnoff, fd, 4 * hz);
1759	switch (fdc->state)
1760	{
1761	case DEVIDLE:
1762	case FINDWORK:	/* we have found new work */
1763		fdc->retry = 0;
1764		fd->skip = 0;
1765		fdc->fd = fd;
1766		fdc->fdu = fdu;
1767		fdc->fdctl_wr(fdc, fd->ft->trans);
1768		TRACE1("[0x%x->FDCTL]", fd->ft->trans);
1769		/*******************************************************\
1770		* If the next drive has a motor startup pending, then	*
1771		* it will start up in its own good time		*
1772		\*******************************************************/
1773		if(fd->flags & FD_MOTOR_WAIT) {
1774			fdc->state = MOTORWAIT;
1775			return (0); /* come back later */
1776		}
1777		/*******************************************************\
1778		* Maybe if it's not starting, it SHOULD be starting	*
1779		\*******************************************************/
1780		if (!(fd->flags & FD_MOTOR))
1781		{
1782			fdc->state = MOTORWAIT;
1783			fd_turnon(fd);
1784			return (0);
1785		}
1786		else	/* at least make sure we are selected */
1787		{
1788			set_motor(fdc, fd->fdsu, TURNON);
1789		}
1790		if (fdc->flags & FDC_NEEDS_RESET) {
1791			fdc->state = RESETCTLR;
1792			fdc->flags &= ~FDC_NEEDS_RESET;
1793		} else
1794			fdc->state = DOSEEK;
1795		break;
1796	case DOSEEK:
1797		if (b_cylinder == (unsigned)fd->track)
1798		{
1799			fdc->state = SEEKCOMPLETE;
1800			break;
1801		}
1802		if (fd_cmd(fdc, 3, NE7CMD_SEEK,
1803			   fd->fdsu, b_cylinder * fd->ft->steptrac,
1804			   0))
1805		{
1806			/*
1807			 * seek command not accepted, looks like
1808			 * the FDC went off to the Saints...
1809			 */
1810			fdc->retry = 6;	/* try a reset */
1811			return(retrier(fdc));
1812		}
1813		fd->track = FD_NO_TRACK;
1814		fdc->state = SEEKWAIT;
1815		return(0);	/* will return later */
1816	case SEEKWAIT:
1817		/* allow heads to settle */
1818		timeout(fd_pseudointr, fdc, hz / 16);
1819		fdc->state = SEEKCOMPLETE;
1820		return(0);	/* will return later */
1821	case SEEKCOMPLETE : /* SEEK DONE, START DMA */
1822		/* Make sure seek really happened*/
1823		if(fd->track == FD_NO_TRACK) {
1824			int descyl = b_cylinder * fd->ft->steptrac;
1825			do {
1826				/*
1827				 * This might be a "ready changed" interrupt,
1828				 * which cannot really happen since the
1829				 * RDY pin is hardwired to + 5 volts.  This
1830				 * generally indicates a "bouncing" intr
1831				 * line, so do one of the following:
1832				 *
1833				 * When running on an enhanced FDC that is
1834				 * known to not go stuck after responding
1835				 * with INVALID, fetch all interrupt states
1836				 * until seeing either an INVALID or a
1837				 * real interrupt condition.
1838				 *
1839				 * When running on a dumb old NE765, give
1840				 * up immediately.  The controller will
1841				 * provide up to four dummy RC interrupt
1842				 * conditions right after reset (for the
1843				 * corresponding four drives), so this is
1844				 * our only chance to get notice that it
1845				 * was not the FDC that caused the interrupt.
1846				 */
1847				if (fd_sense_int(fdc, &st0, &cyl)
1848				    == FD_NOT_VALID)
1849					return 0;
1850				if(fdc->fdct == FDC_NE765
1851				   && (st0 & NE7_ST0_IC) == NE7_ST0_IC_RC)
1852					return 0; /* hope for a real intr */
1853			} while ((st0 & NE7_ST0_IC) == NE7_ST0_IC_RC);
1854
1855			if (0 == descyl) {
1856				int failed = 0;
1857				/*
1858				 * seek to cyl 0 requested; make sure we are
1859				 * really there
1860				 */
1861				if (fd_sense_drive_status(fdc, &st3))
1862					failed = 1;
1863				if ((st3 & NE7_ST3_T0) == 0) {
1864					printf(
1865		"fd%d: Seek to cyl 0, but not really there (ST3 = %b)\n",
1866					       fdu, st3, NE7_ST3BITS);
1867					failed = 1;
1868				}
1869
1870				if (failed) {
1871					if(fdc->retry < 3)
1872						fdc->retry = 3;
1873					return (retrier(fdc));
1874				}
1875			}
1876
1877			if (cyl != descyl) {
1878				printf(
1879		"fd%d: Seek to cyl %d failed; am at cyl %d (ST0 = 0x%x)\n",
1880				       fdu, descyl, cyl, st0);
1881				if (fdc->retry < 3)
1882					fdc->retry = 3;
1883				return (retrier(fdc));
1884			}
1885		}
1886
1887		fd->track = b_cylinder;
1888		if (!(fdc->flags & FDC_NODMA))
1889			isa_dmastart(idf, bp->bio_data+fd->skip,
1890				format ? bp->bio_bcount : fdblk, fdc->dmachan);
1891		sectrac = fd->ft->sectrac;
1892		sec = blknum %  (sectrac * fd->ft->heads);
1893		head = sec / sectrac;
1894		sec = sec % sectrac + 1;
1895		fd->hddrv = ((head&1)<<2)+fdu;
1896
1897		if(format || !read)
1898		{
1899			/* make sure the drive is writable */
1900			if(fd_sense_drive_status(fdc, &st3) != 0)
1901			{
1902				/* stuck controller? */
1903				if (!(fdc->flags & FDC_NODMA))
1904					isa_dmadone(idf,
1905						    bp->bio_data + fd->skip,
1906						    format ? bp->bio_bcount : fdblk,
1907						    fdc->dmachan);
1908				fdc->retry = 6;	/* reset the beast */
1909				return (retrier(fdc));
1910			}
1911			if(st3 & NE7_ST3_WP)
1912			{
1913				/*
1914				 * XXX YES! this is ugly.
1915				 * in order to force the current operation
1916				 * to fail, we will have to fake an FDC
1917				 * error - all error handling is done
1918				 * by the retrier()
1919				 */
1920				fdc->status[0] = NE7_ST0_IC_AT;
1921				fdc->status[1] = NE7_ST1_NW;
1922				fdc->status[2] = 0;
1923				fdc->status[3] = fd->track;
1924				fdc->status[4] = head;
1925				fdc->status[5] = sec;
1926				fdc->retry = 8;	/* break out immediately */
1927				fdc->state = IOTIMEDOUT; /* not really... */
1928				return (1);
1929			}
1930		}
1931
1932		if (format) {
1933			if (fdc->flags & FDC_NODMA) {
1934				/*
1935				 * This seems to be necessary for
1936				 * whatever obscure reason; if we omit
1937				 * it, we end up filling the sector ID
1938				 * fields of the newly formatted track
1939				 * entirely with garbage, causing
1940				 * `wrong cylinder' errors all over
1941				 * the place when trying to read them
1942				 * back.
1943				 *
1944				 * Umpf.
1945				 */
1946				SET_BCDR(fdc, 1, bp->bio_bcount, 0);
1947
1948				(void)fdcpio(fdc,bp->bio_cmd,
1949					bp->bio_data+fd->skip,
1950					bp->bio_bcount);
1951
1952			}
1953			/* formatting */
1954			if(fd_cmd(fdc, 6,  NE7CMD_FORMAT, head << 2 | fdu,
1955				  finfo->fd_formb_secshift,
1956				  finfo->fd_formb_nsecs,
1957				  finfo->fd_formb_gaplen,
1958				  finfo->fd_formb_fillbyte, 0)) {
1959				/* controller fell over */
1960				if (!(fdc->flags & FDC_NODMA))
1961					isa_dmadone(idf,
1962						    bp->bio_data + fd->skip,
1963						    format ? bp->bio_bcount : fdblk,
1964						    fdc->dmachan);
1965				fdc->retry = 6;
1966				return (retrier(fdc));
1967			}
1968		} else {
1969			if (fdc->flags & FDC_NODMA) {
1970				/*
1971				 * this seems to be necessary even when
1972				 * reading data
1973				 */
1974				SET_BCDR(fdc, 1, fdblk, 0);
1975
1976				/*
1977				 * perform the write pseudo-DMA before
1978				 * the WRITE command is sent
1979				 */
1980				if (!read)
1981					(void)fdcpio(fdc,bp->bio_cmd,
1982					    bp->bio_data+fd->skip,
1983					    fdblk);
1984			}
1985			if (fd_cmd(fdc, 9,
1986				   (read ? NE7CMD_READ : NE7CMD_WRITE),
1987				   head << 2 | fdu,  /* head & unit */
1988				   fd->track,        /* track */
1989				   head,
1990				   sec,              /* sector + 1 */
1991				   fd->ft->secsize,  /* sector size */
1992				   sectrac,          /* sectors/track */
1993				   fd->ft->gap,      /* gap size */
1994				   fd->ft->datalen,  /* data length */
1995				   0)) {
1996				/* the beast is sleeping again */
1997				if (!(fdc->flags & FDC_NODMA))
1998					isa_dmadone(idf,
1999						    bp->bio_data + fd->skip,
2000						    format ? bp->bio_bcount : fdblk,
2001						    fdc->dmachan);
2002				fdc->retry = 6;
2003				return (retrier(fdc));
2004			}
2005		}
2006		if (fdc->flags & FDC_NODMA)
2007			/*
2008			 * if this is a read, then simply await interrupt
2009			 * before performing PIO
2010			 */
2011			if (read && !fdcpio(fdc,bp->bio_cmd,
2012			    bp->bio_data+fd->skip,fdblk)) {
2013				fd->tohandle = timeout(fd_iotimeout, fdc, hz);
2014				return(0);      /* will return later */
2015			};
2016
2017		/*
2018		 * write (or format) operation will fall through and
2019		 * await completion interrupt
2020		 */
2021		fdc->state = IOCOMPLETE;
2022		fd->tohandle = timeout(fd_iotimeout, fdc, hz);
2023		return (0);	/* will return later */
2024	case PIOREAD:
2025		/*
2026		 * actually perform the PIO read.  The IOCOMPLETE case
2027		 * removes the timeout for us.
2028		 */
2029		(void)fdcpio(fdc,bp->bio_cmd,bp->bio_data+fd->skip,fdblk);
2030		fdc->state = IOCOMPLETE;
2031		/* FALLTHROUGH */
2032	case IOCOMPLETE: /* IO DONE, post-analyze */
2033		untimeout(fd_iotimeout, fdc, fd->tohandle);
2034
2035		if (fd_read_status(fdc, fd->fdsu)) {
2036			if (!(fdc->flags & FDC_NODMA))
2037				isa_dmadone(idf, bp->bio_data + fd->skip,
2038					    format ? bp->bio_bcount : fdblk,
2039					    fdc->dmachan);
2040			if (fdc->retry < 6)
2041				fdc->retry = 6;	/* force a reset */
2042			return (retrier(fdc));
2043  		}
2044
2045		fdc->state = IOTIMEDOUT;
2046
2047		/* FALLTHROUGH */
2048
2049	case IOTIMEDOUT:
2050		if (!(fdc->flags & FDC_NODMA))
2051			isa_dmadone(idf, bp->bio_data + fd->skip,
2052				format ? bp->bio_bcount : fdblk, fdc->dmachan);
2053		if (fdc->status[0] & NE7_ST0_IC) {
2054                        if ((fdc->status[0] & NE7_ST0_IC) == NE7_ST0_IC_AT
2055			    && fdc->status[1] & NE7_ST1_OR) {
2056                                /*
2057				 * DMA overrun. Someone hogged the bus
2058				 * and didn't release it in time for the
2059				 * next FDC transfer.
2060				 * Just restart it, don't increment retry
2061				 * count. (vak)
2062                                 */
2063                                fdc->state = SEEKCOMPLETE;
2064                                return (1);
2065                        }
2066			else if((fdc->status[0] & NE7_ST0_IC) == NE7_ST0_IC_IV
2067				&& fdc->retry < 6)
2068				fdc->retry = 6;	/* force a reset */
2069			else if((fdc->status[0] & NE7_ST0_IC) == NE7_ST0_IC_AT
2070				&& fdc->status[2] & NE7_ST2_WC
2071				&& fdc->retry < 3)
2072				fdc->retry = 3;	/* force recalibrate */
2073			return (retrier(fdc));
2074		}
2075		/* All OK */
2076		fd->skip += fdblk;
2077		if (!format && fd->skip < bp->bio_bcount - bp->bio_resid) {
2078			/* set up next transfer */
2079			fdc->state = DOSEEK;
2080		} else {
2081			/* ALL DONE */
2082			fd->skip = 0;
2083			fdc->bp = NULL;
2084			device_unbusy(fd->dev);
2085			devstat_end_transaction_bio(&fd->device_stats, bp);
2086			biodone(bp);
2087			fdc->fd = (fd_p) 0;
2088			fdc->fdu = -1;
2089			fdc->state = FINDWORK;
2090		}
2091		return (1);
2092	case RESETCTLR:
2093		fdc_reset(fdc);
2094		fdc->retry++;
2095		fdc->state = RESETCOMPLETE;
2096		return (0);
2097	case RESETCOMPLETE:
2098		/*
2099		 * Discard all the results from the reset so that they
2100		 * can't cause an unexpected interrupt later.
2101		 */
2102		for (i = 0; i < 4; i++)
2103			(void)fd_sense_int(fdc, &st0, &cyl);
2104		fdc->state = STARTRECAL;
2105		/* Fall through. */
2106	case STARTRECAL:
2107		if(fd_cmd(fdc, 2, NE7CMD_RECAL, fdu, 0)) {
2108			/* arrgl */
2109			fdc->retry = 6;
2110			return (retrier(fdc));
2111		}
2112		fdc->state = RECALWAIT;
2113		return (0);	/* will return later */
2114	case RECALWAIT:
2115		/* allow heads to settle */
2116		timeout(fd_pseudointr, fdc, hz / 8);
2117		fdc->state = RECALCOMPLETE;
2118		return (0);	/* will return later */
2119	case RECALCOMPLETE:
2120		do {
2121			/*
2122			 * See SEEKCOMPLETE for a comment on this:
2123			 */
2124			if (fd_sense_int(fdc, &st0, &cyl) == FD_NOT_VALID)
2125				return 0;
2126			if(fdc->fdct == FDC_NE765
2127			   && (st0 & NE7_ST0_IC) == NE7_ST0_IC_RC)
2128				return 0; /* hope for a real intr */
2129		} while ((st0 & NE7_ST0_IC) == NE7_ST0_IC_RC);
2130		if ((st0 & NE7_ST0_IC) != NE7_ST0_IC_NT || cyl != 0)
2131		{
2132			if(fdc->retry > 3)
2133				/*
2134				 * a recalibrate from beyond cylinder 77
2135				 * will "fail" due to the FDC limitations;
2136				 * since people used to complain much about
2137				 * the failure message, try not logging
2138				 * this one if it seems to be the first
2139				 * time in a line
2140				 */
2141				printf("fd%d: recal failed ST0 %b cyl %d\n",
2142				       fdu, st0, NE7_ST0BITS, cyl);
2143			if(fdc->retry < 3) fdc->retry = 3;
2144			return (retrier(fdc));
2145		}
2146		fd->track = 0;
2147		/* Seek (probably) necessary */
2148		fdc->state = DOSEEK;
2149		return (1);	/* will return immediatly */
2150	case MOTORWAIT:
2151		if(fd->flags & FD_MOTOR_WAIT)
2152		{
2153			return (0); /* time's not up yet */
2154		}
2155		if (fdc->flags & FDC_NEEDS_RESET) {
2156			fdc->state = RESETCTLR;
2157			fdc->flags &= ~FDC_NEEDS_RESET;
2158		} else {
2159			/*
2160			 * If all motors were off, then the controller was
2161			 * reset, so it has lost track of the current
2162			 * cylinder.  Recalibrate to handle this case.
2163			 * But first, discard the results of the reset.
2164			 */
2165			fdc->state = RESETCOMPLETE;
2166		}
2167		return (1);	/* will return immediatly */
2168	default:
2169		device_printf(fdc->fdc_dev, "unexpected FD int->");
2170		if (fd_read_status(fdc, fd->fdsu) == 0)
2171			printf("FDC status :%x %x %x %x %x %x %x   ",
2172			       fdc->status[0],
2173			       fdc->status[1],
2174			       fdc->status[2],
2175			       fdc->status[3],
2176			       fdc->status[4],
2177			       fdc->status[5],
2178			       fdc->status[6] );
2179		else
2180			printf("No status available   ");
2181		if (fd_sense_int(fdc, &st0, &cyl) != 0)
2182		{
2183			printf("[controller is dead now]\n");
2184			return (0);
2185		}
2186		printf("ST0 = %x, PCN = %x\n", st0, cyl);
2187		return (0);
2188	}
2189	/*XXX confusing: some branches return immediately, others end up here*/
2190	return (1); /* Come back immediatly to new state */
2191}
2192
2193static int
2194retrier(struct fdc_data *fdc)
2195{
2196	struct bio *bp;
2197	struct fd_data *fd;
2198	int fdu;
2199
2200	bp = fdc->bp;
2201
2202	/* XXX shouldn't this be cached somewhere?  */
2203	fdu = FDUNIT(minor(bp->bio_dev));
2204	fd = devclass_get_softc(fd_devclass, fdu);
2205	if (fd->options & FDOPT_NORETRY)
2206		goto fail;
2207
2208	switch (fdc->retry) {
2209	case 0: case 1: case 2:
2210		fdc->state = SEEKCOMPLETE;
2211		break;
2212	case 3: case 4: case 5:
2213		fdc->state = STARTRECAL;
2214		break;
2215	case 6:
2216		fdc->state = RESETCTLR;
2217		break;
2218	case 7:
2219		break;
2220	default:
2221	fail:
2222		{
2223			dev_t sav_bio_dev = bp->bio_dev;
2224			/* Trick diskerr */
2225			bp->bio_dev = makedev(major(bp->bio_dev),
2226				    (FDUNIT(minor(bp->bio_dev))<<3)|RAW_PART);
2227			diskerr(bp, "hard error", fdc->fd->skip / DEV_BSIZE,
2228				(struct disklabel *)NULL);
2229			bp->bio_dev = sav_bio_dev;
2230			if (fdc->flags & FDC_STAT_VALID)
2231			{
2232				printf(
2233			" (ST0 %b ST1 %b ST2 %b cyl %u hd %u sec %u)\n",
2234				       fdc->status[0], NE7_ST0BITS,
2235				       fdc->status[1], NE7_ST1BITS,
2236				       fdc->status[2], NE7_ST2BITS,
2237				       fdc->status[3], fdc->status[4],
2238				       fdc->status[5]);
2239			}
2240			else
2241				printf(" (No status)\n");
2242		}
2243		bp->bio_flags |= BIO_ERROR;
2244		bp->bio_error = EIO;
2245		bp->bio_resid += bp->bio_bcount - fdc->fd->skip;
2246		fdc->bp = NULL;
2247		fdc->fd->skip = 0;
2248		device_unbusy(fd->dev);
2249		devstat_end_transaction_bio(&fdc->fd->device_stats, bp);
2250		biodone(bp);
2251		fdc->state = FINDWORK;
2252		fdc->flags |= FDC_NEEDS_RESET;
2253		fdc->fd = (fd_p) 0;
2254		fdc->fdu = -1;
2255		return (1);
2256	}
2257	fdc->retry++;
2258	return (1);
2259}
2260
2261static void
2262fdbiodone(struct bio *bp)
2263{
2264	wakeup(bp);
2265}
2266
2267static int
2268fdformat(dev, finfo, p)
2269	dev_t dev;
2270	struct fd_formb *finfo;
2271	struct proc *p;
2272{
2273 	fdu_t	fdu;
2274 	fd_p	fd;
2275
2276	struct bio *bp;
2277	int rv = 0, s;
2278	size_t fdblk;
2279
2280 	fdu	= FDUNIT(minor(dev));
2281	fd	= devclass_get_softc(fd_devclass, fdu);
2282	fdblk = 128 << fd->ft->secsize;
2283
2284	/* set up a buffer header for fdstrategy() */
2285	bp = (struct bio *)malloc(sizeof(struct bio), M_TEMP, M_NOWAIT);
2286	if(bp == 0)
2287		return ENOMEM;
2288	/*
2289	 * keep the process from being swapped
2290	 */
2291	PHOLD(p);
2292	bzero((void *)bp, sizeof(*bp));
2293	bp->bio_cmd = BIO_FORMAT;
2294
2295	/*
2296	 * calculate a fake blkno, so fdstrategy() would initiate a
2297	 * seek to the requested cylinder
2298	 */
2299	bp->bio_blkno = (finfo->cyl * (fd->ft->sectrac * fd->ft->heads)
2300		+ finfo->head * fd->ft->sectrac) * fdblk / DEV_BSIZE;
2301
2302	bp->bio_bcount = sizeof(struct fd_idfield_data) * finfo->fd_formb_nsecs;
2303	bp->bio_data = (caddr_t)finfo;
2304
2305	/* now do the format */
2306	bp->bio_dev = dev;
2307	bp->bio_done = fdbiodone;
2308	fdstrategy(bp);
2309
2310	/* ...and wait for it to complete */
2311	s = splbio();
2312	while(!(bp->bio_flags & BIO_DONE)) {
2313		rv = tsleep((caddr_t)bp, PRIBIO, "fdform", 20 * hz);
2314		if (rv == EWOULDBLOCK)
2315			break;
2316	}
2317	splx(s);
2318
2319	if (rv == EWOULDBLOCK) {
2320		/* timed out */
2321		rv = EIO;
2322		device_unbusy(fd->dev);
2323	}
2324	if (bp->bio_flags & BIO_ERROR)
2325		rv = bp->bio_error;
2326	/*
2327	 * allow the process to be swapped
2328	 */
2329	PRELE(p);
2330	free(bp, M_TEMP);
2331	return rv;
2332}
2333
2334/*
2335 * TODO: don't allocate buffer on stack.
2336 */
2337
2338static int
2339fdioctl(dev, cmd, addr, flag, p)
2340	dev_t dev;
2341	u_long cmd;
2342	caddr_t addr;
2343	int flag;
2344	struct proc *p;
2345{
2346 	fdu_t	fdu = FDUNIT(minor(dev));
2347 	fd_p	fd = devclass_get_softc(fd_devclass, fdu);
2348	size_t fdblk;
2349
2350	struct fd_type *fdt;
2351	struct disklabel *dl;
2352	char buffer[DEV_BSIZE];
2353	int error = 0;
2354
2355	fdblk = 128 << fd->ft->secsize;
2356
2357	switch (cmd) {
2358	case DIOCGDINFO:
2359		bzero(buffer, sizeof (buffer));
2360		dl = (struct disklabel *)buffer;
2361		dl->d_secsize = fdblk;
2362		fdt = fd->ft;
2363		dl->d_secpercyl = fdt->size / fdt->tracks;
2364		dl->d_type = DTYPE_FLOPPY;
2365
2366		if (readdisklabel(dkmodpart(dev, RAW_PART), dl)
2367		    == NULL)
2368			error = 0;
2369		else
2370			error = EINVAL;
2371
2372		*(struct disklabel *)addr = *dl;
2373		break;
2374
2375	case DIOCSDINFO:
2376		if ((flag & FWRITE) == 0)
2377			error = EBADF;
2378		break;
2379
2380	case DIOCWLABEL:
2381		if ((flag & FWRITE) == 0)
2382			error = EBADF;
2383		break;
2384
2385	case DIOCWDINFO:
2386		if ((flag & FWRITE) == 0) {
2387			error = EBADF;
2388			break;
2389		}
2390
2391		dl = (struct disklabel *)addr;
2392
2393		if ((error = setdisklabel((struct disklabel *)buffer, dl,
2394					  (u_long)0)) != 0)
2395			break;
2396
2397		error = writedisklabel(dev, (struct disklabel *)buffer);
2398		break;
2399	case FD_FORM:
2400		if ((flag & FWRITE) == 0)
2401			error = EBADF;	/* must be opened for writing */
2402		else if (((struct fd_formb *)addr)->format_version !=
2403			FD_FORMAT_VERSION)
2404			error = EINVAL;	/* wrong version of formatting prog */
2405		else
2406			error = fdformat(dev, (struct fd_formb *)addr, p);
2407		break;
2408
2409	case FD_GTYPE:                  /* get drive type */
2410		*(struct fd_type *)addr = *fd->ft;
2411		break;
2412
2413	case FD_STYPE:                  /* set drive type */
2414		/* this is considered harmful; only allow for superuser */
2415		if (suser(p) != 0)
2416			return EPERM;
2417		*fd->ft = *(struct fd_type *)addr;
2418		break;
2419
2420	case FD_GOPTS:			/* get drive options */
2421		*(int *)addr = fd->options;
2422		break;
2423
2424	case FD_SOPTS:			/* set drive options */
2425		fd->options = *(int *)addr;
2426		break;
2427
2428	default:
2429		error = ENOTTY;
2430		break;
2431	}
2432	return (error);
2433}
2434
2435/*
2436 * Hello emacs, these are the
2437 * Local Variables:
2438 *  c-indent-level:               8
2439 *  c-continued-statement-offset: 8
2440 *  c-continued-brace-offset:     0
2441 *  c-brace-offset:              -8
2442 *  c-brace-imaginary-offset:     0
2443 *  c-argdecl-indent:             8
2444 *  c-label-offset:              -8
2445 *  c++-hanging-braces:           1
2446 *  c++-access-specifier-offset: -8
2447 *  c++-empty-arglist-indent:     8
2448 *  c++-friend-offset:            0
2449 * End:
2450 */
2451