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