]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/pc98/cbus/fdc.c
This commit was generated by cvs2svn to compensate for changes in r164219,
[FreeBSD/FreeBSD.git] / sys / pc98 / cbus / fdc.c
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  * Copyright (c) 2001 Joerg Wunsch,
22  *  joerg_wunsch@uriah.heep.sax.de (Joerg Wunsch)
23  *
24  * Redistribution and use in source and binary forms, with or without
25  * modification, are permitted provided that the following conditions
26  * are met:
27  * 1. Redistributions of source code must retain the above copyright
28  *    notice, this list of conditions and the following disclaimer.
29  * 2. Redistributions in binary form must reproduce the above copyright
30  *    notice, this list of conditions and the following disclaimer in the
31  *    documentation and/or other materials provided with the distribution.
32  * 3. All advertising materials mentioning features or use of this software
33  *    must display the following acknowledgement:
34  *      This product includes software developed by the University of
35  *      California, Berkeley and its contributors.
36  * 4. Neither the name of the University nor the names of its contributors
37  *    may be used to endorse or promote products derived from this software
38  *    without specific prior written permission.
39  *
40  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
41  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
44  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50  * SUCH DAMAGE.
51  *
52  *      from:   @(#)fd.c        7.4 (Berkeley) 5/25/91
53  * $FreeBSD$
54  */
55
56 #include "opt_fdc.h"
57
58 #include <sys/param.h>
59 #include <sys/bio.h>
60 #include <sys/bus.h>
61 #include <sys/devicestat.h>
62 #include <sys/disk.h>
63 #include <sys/fcntl.h>
64 #include <sys/fdcio.h>
65 #include <sys/filio.h>
66 #include <sys/kernel.h>
67 #include <sys/lock.h>
68 #include <sys/malloc.h>
69 #include <sys/module.h>
70 #include <sys/mutex.h>
71 #include <sys/priv.h>
72 #include <sys/proc.h>
73 #include <sys/rman.h>
74 #include <sys/systm.h>
75
76 #include <machine/bus.h>
77 #include <machine/stdarg.h>
78
79 #ifdef PC98
80 #include <isa/isavar.h>
81 #include <pc98/cbus/fdcreg.h>
82 #include <pc98/cbus/fdcvar.h>
83 #include <pc98/pc98/pc98_machdep.h>
84 #else
85 #include <isa/isavar.h>
86 #include <isa/isareg.h>
87 #include <dev/fdc/fdcreg.h>
88 #include <dev/fdc/fdcvar.h>
89 #include <isa/rtc.h>
90 #endif
91
92 #define FDBIO_FORMAT    BIO_CMD2
93
94 /* configuration flags for fdc */
95 #define FDC_NO_FIFO     (1 << 2)        /* do not enable FIFO  */
96
97 /*
98  * Stop retrying after this many DMA overruns.  Since each retry takes
99  * one revolution, with 300 rpm., 25 retries take approximately 5
100  * seconds which the read attempt will block in case the DMA overrun
101  * is persistent.
102  */
103 #define FDC_DMAOV_MAX   25
104
105 /*
106  * Timeout value for the PIO loops to wait until the FDC main status
107  * register matches our expectations (request for master, direction
108  * bit).  This is supposed to be a number of microseconds, although
109  * timing might actually not be very accurate.
110  *
111  * Timeouts of 100 msec are believed to be required for some broken
112  * (old) hardware.
113  */
114 #define FDSTS_TIMEOUT   100000
115
116 /*
117  * Number of subdevices that can be used for different density types.
118  */
119 #ifdef PC98
120 #define NUMDENS         12
121 #else
122 #define NUMDENS         16
123 #endif
124
125 #define FDBIO_RDSECTID  BIO_CMD1
126
127 /*
128  * List of native drive densities.  Order must match enum fd_drivetype
129  * in <sys/fdcio.h>.  Upon attaching the drive, each of the
130  * programmable subdevices is initialized with the native density
131  * definition.
132  */
133 #ifdef PC98
134 static struct fd_type fd_native_types[] =
135 {
136 { 0 },                                          /* FDT_NONE */
137 { 0 },                                          /* FDT_360K */
138 { 15,2,0xFF,0x1B,80,2400,0,2,0x54,1,0,FL_MFM }, /* FDT_12M  */
139 { 0 },                                          /* FDT_720K */
140 { 18,2,0xFF,0x1B,80,2880,2,2,0x54,1,0,FL_MFM }, /* FDT_144M */
141 { 0 },                                          /* FDT_288M */
142 };
143
144 static struct fd_type fd_searchlist_12m[] = {
145 { 15,2,0xFF,0x1B,80,2400,0,2,0x54,1,0,FL_MFM }, /* 1.2M */
146 #if 0
147 { 10,2,0xFF,0x10,82,1640,1,2,0x30,1,0,FL_MFM }, /* 820K */
148 { 10,2,0xFF,0x10,80,1600,1,2,0x30,1,0,FL_MFM }, /* 800K */
149 #endif
150 {  9,2,0xFF,0x20,80,1440,1,2,0x50,1,0,FL_MFM }, /* 720K */
151 {  9,2,0xFF,0x20,40, 720,1,2,0x50,1,0,FL_MFM|FL_2STEP },/* 360K */
152 {  8,2,0xFF,0x2A,80,1280,1,2,0x50,1,0,FL_MFM }, /* 640K */
153 {  8,3,0xFF,0x35,77,1232,0,2,0x74,1,0,FL_MFM }, /* 1.23M 1024/sec */
154 #if 0
155 {  8,3,0xFF,0x35,80,1280,0,2,0x74,1,0,FL_MFM }, /* 1.28M 1024/sec */
156 #endif
157 };
158 static struct fd_type fd_searchlist_144m[] = {
159 #if 0
160 { 21,2,0xFF,0x04,82,3444,2,2,0x0C,2,0,FL_MFM }, /* 1.72M in 3mode */
161 { 18,2,0xFF,0x1B,82,2952,2,2,0x54,1,0,FL_MFM }, /* 1.48M in 3mode */
162 #endif
163 { 18,2,0xFF,0x1B,80,2880,2,2,0x54,1,0,FL_MFM }, /* 1.44M in 3mode */
164 { 15,2,0xFF,0x1B,80,2400,0,2,0x54,1,0,FL_MFM }, /* 1.2M */
165 #if 0
166 { 10,2,0xFF,0x10,82,1640,1,2,0x30,1,0,FL_MFM }, /* 820K */
167 { 10,2,0xFF,0x10,80,1600,1,2,0x30,1,0,FL_MFM }, /* 800K */
168 #endif
169 {  9,2,0xFF,0x20,80,1440,1,2,0x50,1,0,FL_MFM }, /* 720K */
170 {  9,2,0xFF,0x20,40, 720,1,2,0x50,1,0,FL_MFM|FL_2STEP },/* 360K */
171 {  8,2,0xFF,0x2A,80,1280,1,2,0x50,1,0,FL_MFM }, /* 640K */
172 {  8,3,0xFF,0x35,77,1232,0,2,0x74,1,0,FL_MFM }, /* 1.23M 1024/sec */
173 #if 0
174 {  8,3,0xFF,0x35,80,1280,0,2,0x74,1,0,FL_MFM }, /* 1.28M 1024/sec */
175 {  9,3,0xFF,0x35,82,1476,0,2,0x47,1,0,FL_MFM }, /* 1.48M 1024/sec 9sec */
176 { 10,3,0xFF,0x1B,82,1640,2,2,0x54,1,0,FL_MFM }, /* 1.64M in 3mode - Reserve */
177 #endif
178 };
179 #else /* PC98 */
180 static struct fd_type fd_native_types[] =
181 {
182 { 0 },                          /* FDT_NONE */
183 {  9,2,0xFF,0x2A,40, 720,FDC_250KBPS,2,0x50,1,0,FL_MFM }, /* FDT_360K */
184 { 15,2,0xFF,0x1B,80,2400,FDC_500KBPS,2,0x54,1,0,FL_MFM }, /* FDT_12M  */
185 {  9,2,0xFF,0x20,80,1440,FDC_250KBPS,2,0x50,1,0,FL_MFM }, /* FDT_720K */
186 { 18,2,0xFF,0x1B,80,2880,FDC_500KBPS,2,0x6C,1,0,FL_MFM }, /* FDT_144M */
187 #if 0                           /* we currently don't handle 2.88 MB */
188 { 36,2,0xFF,0x1B,80,5760,FDC_1MBPS,  2,0x4C,1,1,FL_MFM|FL_PERPND } /*FDT_288M*/
189 #else
190 { 18,2,0xFF,0x1B,80,2880,FDC_500KBPS,2,0x6C,1,0,FL_MFM }, /* FDT_144M */
191 #endif
192 };
193
194 /*
195  * 360 KB 5.25" and 720 KB 3.5" drives don't have automatic density
196  * selection, they just start out with their native density (or lose).
197  * So 1.2 MB 5.25", 1.44 MB 3.5", and 2.88 MB 3.5" drives have their
198  * respective lists of densities to search for.
199  */
200 static struct fd_type fd_searchlist_12m[] = {
201 { 15,2,0xFF,0x1B,80,2400,FDC_500KBPS,2,0x54,1,0,FL_MFM }, /* 1.2M */
202 {  9,2,0xFF,0x23,40, 720,FDC_300KBPS,2,0x50,1,0,FL_MFM|FL_2STEP }, /* 360K */
203 {  9,2,0xFF,0x20,80,1440,FDC_300KBPS,2,0x50,1,0,FL_MFM }, /* 720K */
204 };
205
206 static struct fd_type fd_searchlist_144m[] = {
207 { 18,2,0xFF,0x1B,80,2880,FDC_500KBPS,2,0x6C,1,0,FL_MFM }, /* 1.44M */
208 {  9,2,0xFF,0x20,80,1440,FDC_250KBPS,2,0x50,1,0,FL_MFM }, /* 720K */
209 };
210
211 /* We search for 1.44M first since this is the most common case. */
212 static struct fd_type fd_searchlist_288m[] = {
213 { 18,2,0xFF,0x1B,80,2880,FDC_500KBPS,2,0x6C,1,0,FL_MFM }, /* 1.44M */
214 #if 0
215 { 36,2,0xFF,0x1B,80,5760,FDC_1MBPS,  2,0x4C,1,1,FL_MFM|FL_PERPND } /* 2.88M */
216 #endif
217 {  9,2,0xFF,0x20,80,1440,FDC_250KBPS,2,0x50,1,0,FL_MFM }, /* 720K */
218 };
219 #endif /* PC98 */
220
221 #define MAX_SEC_SIZE    (128 << 3)
222 #define MAX_CYLINDER    85      /* some people really stress their drives
223                                  * up to cyl 82 */
224 #define MAX_HEAD        1
225
226 devclass_t fdc_devclass;
227
228 /*
229  * Per drive structure (softc).
230  */
231 struct fd_data {
232         struct  fdc_data *fdc;  /* pointer to controller structure */
233         int     fdsu;           /* this units number on this controller */
234         enum    fd_drivetype type; /* drive type */
235         struct  fd_type *ft;    /* pointer to current type descriptor */
236         struct  fd_type fts[NUMDENS]; /* type descriptors */
237         int     flags;
238 #define FD_OPEN         0x01    /* it's open            */
239 #define FD_NONBLOCK     0x02    /* O_NONBLOCK set       */
240 #define FD_ACTIVE       0x04    /* it's active          */
241 #define FD_MOTOR        0x08    /* motor should be on   */
242 #define FD_MOTOR_WAIT   0x10    /* motor coming up      */
243 #define FD_UA           0x20    /* force unit attention */
244         int     skip;
245         int     hddrv;
246 #define FD_NO_TRACK -2
247         int     track;          /* where we think the head is */
248         int     options;        /* user configurable options, see fdcio.h */
249         struct  callout_handle toffhandle;
250         struct  callout_handle tohandle;
251         struct  devstat *device_stats;
252         struct cdev *masterdev;
253         device_t dev;
254         fdu_t   fdu;
255 #ifdef PC98
256         int     pc98_trans;
257 #endif
258 };
259
260 struct fdc_ivars {
261         int     fdunit;
262         int     fdtype;
263 };
264
265 static devclass_t fd_devclass;
266
267 /* configuration flags for fd */
268 #define FD_TYPEMASK     0x0f    /* drive type, matches enum
269                                  * fd_drivetype; on i386 machines, if
270                                  * given as 0, use RTC type for fd0
271                                  * and fd1 */
272 #define FD_DTYPE(flags) ((flags) & FD_TYPEMASK)
273 #define FD_NO_CHLINE    0x10    /* drive does not support changeline
274                                  * aka. unit attention */
275 #define FD_NO_PROBE     0x20    /* don't probe drive (seek test), just
276                                  * assume it is there */
277
278 /*
279  * Throughout this file the following conventions will be used:
280  *
281  * fd is a pointer to the fd_data struct for the drive in question
282  * fdc is a pointer to the fdc_data struct for the controller
283  * fdu is the floppy drive unit number
284  * fdcu is the floppy controller unit number
285  * fdsu is the floppy drive unit number on that controller. (sub-unit)
286  */
287
288 /*
289  * Function declarations, same (chaotic) order as they appear in the
290  * file.  Re-ordering is too late now, it would only obfuscate the
291  * diffs against old and offspring versions (like the PC98 one).
292  *
293  * Anyone adding functions here, please keep this sequence the same
294  * as below -- makes locating a particular function in the body much
295  * easier.
296  */
297 static u_int8_t fdsts_rd(fdc_p);
298 static void fddata_wr(fdc_p, u_int8_t);
299 static u_int8_t fddata_rd(fdc_p);
300 static int fdc_err(struct fdc_data *, const char *);
301 static int enable_fifo(fdc_p fdc);
302 static int fd_sense_drive_status(fdc_p, int *);
303 static int fd_sense_int(fdc_p, int *, int *);
304 static int fd_read_status(fdc_p);
305 static int fd_probe(device_t);
306 static int fd_attach(device_t);
307 static int fd_detach(device_t);
308 static void set_motor(struct fdc_data *, int, int);
309 #  define TURNON 1
310 #  define TURNOFF 0
311 static timeout_t fd_turnoff;
312 static timeout_t fd_motor_on;
313 static void fd_turnon(struct fd_data *);
314 static void fdc_reset(fdc_p);
315 static int fd_in(struct fdc_data *, int *);
316 static int out_fdc(struct fdc_data *, int);
317 static  d_open_t        fdopen;
318 static  d_close_t       fdclose;
319 static  d_strategy_t    fdstrategy;
320 static void fdstart(struct fdc_data *);
321 static timeout_t fd_iotimeout;
322 static timeout_t fd_pseudointr;
323 static driver_intr_t fdc_intr;
324 static int fdcpio(fdc_p, long, caddr_t, u_int);
325 static int fdautoselect(struct cdev *);
326 static int fdstate(struct fdc_data *);
327 static int retrier(struct fdc_data *);
328 static void fdbiodone(struct bio *);
329 static int fdmisccmd(struct cdev *, u_int, void *);
330 static  d_ioctl_t       fdioctl;
331
332 static int fifo_threshold = 8;  /* XXX: should be accessible via sysctl */
333
334 #ifdef  FDC_DEBUG
335 /* CAUTION: fd_debug causes huge amounts of logging output */
336 static int volatile fd_debug = 0;
337 #define TRACE0(arg) do { if (fd_debug) printf(arg); } while (0)
338 #define TRACE1(arg1, arg2) do { if (fd_debug) printf(arg1, arg2); } while (0)
339 #else /* FDC_DEBUG */
340 #define TRACE0(arg) do { } while (0)
341 #define TRACE1(arg1, arg2) do { } while (0)
342 #endif /* FDC_DEBUG */
343
344 /*
345  * Bus space handling (access to low-level IO).
346  */
347 #ifndef PC98
348 void
349 fdout_wr(fdc_p fdc, u_int8_t v)
350 {
351         bus_space_write_1(fdc->portt, fdc->porth, FDOUT+fdc->port_off, v);
352 }
353 #endif
354
355 static u_int8_t
356 fdsts_rd(fdc_p fdc)
357 {
358         return bus_space_read_1(fdc->portt, fdc->porth, FDSTS+fdc->port_off);
359 }
360
361 static void
362 fddata_wr(fdc_p fdc, u_int8_t v)
363 {
364         bus_space_write_1(fdc->portt, fdc->porth, FDDATA+fdc->port_off, v);
365 }
366
367 static u_int8_t
368 fddata_rd(fdc_p fdc)
369 {
370         return bus_space_read_1(fdc->portt, fdc->porth, FDDATA+fdc->port_off);
371 }
372
373 #ifdef PC98
374 static void
375 fdctl_wr(fdc_p fdc, u_int8_t v)
376 {
377         bus_space_write_1(fdc->portt, fdc->porth, FDCTL, v);
378 }
379 #endif
380
381 #ifndef PC98
382 static u_int8_t
383 fdin_rd(fdc_p fdc)
384 {
385         return bus_space_read_1(fdc->portt, fdc->porth, FDIN);
386 }
387 #endif /* PC98 */
388
389 static struct cdevsw fd_cdevsw = {
390         .d_version =    D_VERSION,
391         .d_open =       fdopen,
392         .d_close =      fdclose,
393         .d_read =       physread,
394         .d_write =      physwrite,
395         .d_ioctl =      fdioctl,
396         .d_strategy =   fdstrategy,
397         .d_name =       "fd",
398         .d_flags =      D_DISK | D_NEEDGIANT,
399 };
400
401 /*
402  * Auxiliary functions.  Well, some only.  Others are scattered
403  * throughout the entire file.
404  */
405 static int
406 fdc_err(struct fdc_data *fdc, const char *s)
407 {
408         fdc->fdc_errs++;
409         if (s) {
410                 if (fdc->fdc_errs < FDC_ERRMAX)
411                         device_printf(fdc->fdc_dev, "%s", s);
412                 else if (fdc->fdc_errs == FDC_ERRMAX)
413                         device_printf(fdc->fdc_dev, "too many errors, not "
414                                                     "logging any more\n");
415         }
416
417         return FD_FAILED;
418 }
419
420 /*
421  * fd_cmd: Send a command to the chip.  Takes a varargs with this structure:
422  * Unit number,
423  * # of output bytes, output bytes as ints ...,
424  * # of input bytes, input bytes as ints ...
425  */
426 int
427 fd_cmd(struct fdc_data *fdc, int n_out, ...)
428 {
429         u_char cmd;
430         int n_in;
431         int n;
432         va_list ap;
433
434         va_start(ap, n_out);
435         cmd = (u_char)(va_arg(ap, int));
436         va_end(ap);
437         va_start(ap, n_out);
438         for (n = 0; n < n_out; n++)
439         {
440                 if (out_fdc(fdc, va_arg(ap, int)) < 0)
441                 {
442                         char msg[50];
443                         snprintf(msg, sizeof(msg),
444                                 "cmd %x failed at out byte %d of %d\n",
445                                 cmd, n + 1, n_out);
446                         return fdc_err(fdc, msg);
447                 }
448         }
449         n_in = va_arg(ap, int);
450         for (n = 0; n < n_in; n++)
451         {
452                 int *ptr = va_arg(ap, int *);
453                 if (fd_in(fdc, ptr) < 0)
454                 {
455                         char msg[50];
456                         snprintf(msg, sizeof(msg),
457                                 "cmd %02x failed at in byte %d of %d\n",
458                                 cmd, n + 1, n_in);
459                         return fdc_err(fdc, msg);
460                 }
461         }
462
463         return 0;
464 }
465
466 static int 
467 enable_fifo(fdc_p fdc)
468 {
469         int i, j;
470
471         if ((fdc->flags & FDC_HAS_FIFO) == 0) {
472                 
473                 /*
474                  * Cannot use fd_cmd the normal way here, since
475                  * this might be an invalid command. Thus we send the
476                  * first byte, and check for an early turn of data directon.
477                  */
478                 
479                 if (out_fdc(fdc, I8207X_CONFIG) < 0)
480                         return fdc_err(fdc, "Enable FIFO failed\n");
481                 
482                 /* If command is invalid, return */
483                 j = FDSTS_TIMEOUT;
484                 while ((i = fdsts_rd(fdc) & (NE7_DIO | NE7_RQM))
485                        != NE7_RQM && j-- > 0) {
486                         if (i == (NE7_DIO | NE7_RQM)) {
487                                 fdc_reset(fdc);
488                                 return FD_FAILED;
489                         }
490                         DELAY(1);
491                 }
492                 if (j<0 || 
493                     fd_cmd(fdc, 3,
494                            0, (fifo_threshold - 1) & 0xf, 0, 0) < 0) {
495                         fdc_reset(fdc);
496                         return fdc_err(fdc, "Enable FIFO failed\n");
497                 }
498                 fdc->flags |= FDC_HAS_FIFO;
499                 return 0;
500         }
501         if (fd_cmd(fdc, 4,
502                    I8207X_CONFIG, 0, (fifo_threshold - 1) & 0xf, 0, 0) < 0)
503                 return fdc_err(fdc, "Re-enable FIFO failed\n");
504         return 0;
505 }
506
507 static int
508 fd_sense_drive_status(fdc_p fdc, int *st3p)
509 {
510         int st3;
511
512         if (fd_cmd(fdc, 2, NE7CMD_SENSED, fdc->fdu, 1, &st3))
513         {
514                 return fdc_err(fdc, "Sense Drive Status failed\n");
515         }
516         if (st3p)
517                 *st3p = st3;
518
519         return 0;
520 }
521
522 static int
523 fd_sense_int(fdc_p fdc, int *st0p, int *cylp)
524 {
525         int cyl, st0, ret;
526
527         ret = fd_cmd(fdc, 1, NE7CMD_SENSEI, 1, &st0);
528         if (ret) {
529                 (void)fdc_err(fdc,
530                               "sense intr err reading stat reg 0\n");
531                 return ret;
532         }
533
534         if (st0p)
535                 *st0p = st0;
536
537         if ((st0 & NE7_ST0_IC) == NE7_ST0_IC_IV) {
538                 /*
539                  * There doesn't seem to have been an interrupt.
540                  */
541                 return FD_NOT_VALID;
542         }
543
544         if (fd_in(fdc, &cyl) < 0) {
545                 return fdc_err(fdc, "can't get cyl num\n");
546         }
547
548         if (cylp)
549                 *cylp = cyl;
550
551         return 0;
552 }
553
554
555 static int
556 fd_read_status(fdc_p fdc)
557 {
558         int i, ret;
559
560         for (i = ret = 0; i < 7; i++) {
561                 /*
562                  * XXX types are poorly chosen.  Only bytes can be read
563                  * from the hardware, but fdc->status[] wants u_ints and
564                  * fd_in() gives ints.
565                  */
566                 int status;
567
568                 ret = fd_in(fdc, &status);
569                 fdc->status[i] = status;
570                 if (ret != 0)
571                         break;
572         }
573
574         if (ret == 0)
575                 fdc->flags |= FDC_STAT_VALID;
576         else
577                 fdc->flags &= ~FDC_STAT_VALID;
578
579         return ret;
580 }
581
582 #ifdef PC98
583 static int pc98_trans = 0; /* 0 : HD , 1 : DD , 2 : 1.44 */
584 static int pc98_trans_prev = -1;
585
586 static void set_density(fdc_p fdc)
587 {
588         /* always motor on */
589         bus_space_write_1(fdc->sc_fdsiot, fdc->sc_fdsioh, 0,
590                           (pc98_trans != 1 ? FDP_FDDEXC : 0) | FDP_PORTEXC);
591         DELAY(100);
592         fdctl_wr(fdc, FDC_RST | FDC_DMAE);
593         /* in the case of note W, always inhibit 100ms timer */
594 }
595
596 static int pc98_fd_check_ready(fdu_t fdu)
597 {
598         fd_p fd = devclass_get_softc(fd_devclass, fdu);
599         struct fdc_data *fdc = fd->fdc;
600         int retry = 0, status;
601
602         while (retry++ < 30000) {
603                 set_motor(fdc, fd->fdsu, TURNON);
604                 out_fdc(fdc, NE7CMD_SENSED); /* Sense Drive Status */
605                 DELAY(100);
606                 out_fdc(fdc, fdu); /* Drive number */
607                 DELAY(100);
608                 if ((fd_in(fdc, &status) == 0) && (status & NE7_ST3_RD)) {
609                         fdctl_wr(fdc, FDC_DMAE | FDC_MTON);
610                         DELAY(10);
611                         return 0;
612                 }
613         }
614         return -1;
615 }
616
617 static void pc98_fd_check_type(struct fd_data *fd)
618 {
619         struct fdc_data *fdc;
620
621         if (fd->type != FDT_NONE || fd->fdu < 0 || fd->fdu > 3)
622                 return;
623
624         fdc = fd->fdc;
625
626         /* Look up what the BIOS thinks we have. */
627         if (!((PC98_SYSTEM_PARAMETER(0x55c) >> fd->fdu) & 0x01)) {
628                 fd->type = FDT_NONE;
629                 return;
630         }
631         if ((PC98_SYSTEM_PARAMETER(0x5ae) >> fd->fdu) & 0x01) {
632                 /* Check 3mode I/F */
633                 fd->pc98_trans = 0;
634                 bus_space_write_1(fdc->sc_fdemsiot, fdc->sc_fdemsioh, 0,
635                                   (fd->fdu << 5) | 0x10);
636                 if (!(bus_space_read_1(fdc->sc_fdemsiot, fdc->sc_fdemsioh, 0) &
637                     0x01)) {
638                         fd->type = FDT_144M;
639                         return;
640                 }
641                 device_printf(fd->dev,
642                               "Warning: can't control 3mode I/F, fallback to 2mode.\n");
643         }
644
645         fd->type = FDT_12M;
646 }
647 #endif /* PC98 */
648
649 void
650 fdc_release_resources(struct fdc_data *fdc)
651 {
652         device_t dev;
653
654         dev = fdc->fdc_dev;
655         if (fdc->fdc_intr) {
656                 bus_teardown_intr(dev, fdc->res_irq, fdc->fdc_intr);
657                 fdc->fdc_intr = NULL;
658         }
659         if (fdc->res_irq != 0) {
660                 bus_deactivate_resource(dev, SYS_RES_IRQ, fdc->rid_irq,
661                                         fdc->res_irq);
662                 bus_release_resource(dev, SYS_RES_IRQ, fdc->rid_irq,
663                                      fdc->res_irq);
664                 fdc->res_irq = NULL;
665         }
666 #ifndef PC98
667         if (fdc->res_ctl != 0) {
668                 bus_deactivate_resource(dev, SYS_RES_IOPORT, fdc->rid_ctl,
669                                         fdc->res_ctl);
670                 bus_release_resource(dev, SYS_RES_IOPORT, fdc->rid_ctl,
671                                      fdc->res_ctl);
672                 fdc->res_ctl = NULL;
673         }
674 #endif
675 #ifdef PC98
676         if (fdc->res_fdsio != 0) {
677                 bus_deactivate_resource(dev, SYS_RES_IOPORT, 3,
678                                         fdc->res_fdsio);
679                 bus_release_resource(dev, SYS_RES_IOPORT, 3, fdc->res_fdsio);
680                 fdc->res_fdsio = NULL;
681         }
682         if (fdc->res_fdemsio != 0) {
683                 bus_deactivate_resource(dev, SYS_RES_IOPORT, 4,
684                                         fdc->res_fdemsio);
685                 bus_release_resource(dev, SYS_RES_IOPORT, 4, fdc->res_fdemsio);
686                 fdc->res_fdemsio = NULL;
687         }
688 #endif
689         if (fdc->res_ioport != 0) {
690                 bus_deactivate_resource(dev, SYS_RES_IOPORT, fdc->rid_ioport,
691                                         fdc->res_ioport);
692                 bus_release_resource(dev, SYS_RES_IOPORT, fdc->rid_ioport,
693                                      fdc->res_ioport);
694                 fdc->res_ioport = NULL;
695         }
696         if (fdc->res_drq != 0) {
697                 bus_deactivate_resource(dev, SYS_RES_DRQ, fdc->rid_drq,
698                                         fdc->res_drq);
699                 bus_release_resource(dev, SYS_RES_DRQ, fdc->rid_drq,
700                                      fdc->res_drq);
701                 fdc->res_drq = NULL;
702         }
703 }
704
705 /*
706  * Configuration/initialization stuff, per controller.
707  */
708
709 int
710 fdc_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
711 {
712         struct fdc_ivars *ivars = device_get_ivars(child);
713
714         switch (which) {
715         case FDC_IVAR_FDUNIT:
716                 *result = ivars->fdunit;
717                 break;
718         case FDC_IVAR_FDTYPE:
719                 *result = ivars->fdtype;
720                 break;
721         default:
722                 return (ENOENT);
723         }
724         return (0);
725 }
726
727 int
728 fdc_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
729 {
730         struct fdc_ivars *ivars = device_get_ivars(child);
731
732         switch (which) {
733         case FDC_IVAR_FDUNIT:
734                 ivars->fdunit = value;
735                 break;
736         case FDC_IVAR_FDTYPE:
737                 ivars->fdtype = value;
738                 break;
739         default:
740                 return (ENOENT);
741         }
742         return (0);
743 }
744
745 int
746 fdc_initial_reset(struct fdc_data *fdc)
747 {
748 #ifdef PC98
749         /* see if it can handle a command */
750         if (fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(4, 240), 
751                    NE7_SPEC_2(2, 0), 0))
752                 return (ENXIO);
753 #else
754         /* First, reset the floppy controller. */
755         fdout_wr(fdc, 0);
756         DELAY(100);
757         fdout_wr(fdc, FDO_FRST);
758
759         /* Then, see if it can handle a command. */
760         if (fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(3, 240), 
761             NE7_SPEC_2(2, 0), 0))
762                 return (ENXIO);
763 #endif
764         return (0);
765 }
766
767 int
768 fdc_detach(device_t dev)
769 {
770         struct  fdc_data *fdc;
771         int     error;
772
773         fdc = device_get_softc(dev);
774
775         /* have our children detached first */
776         if ((error = bus_generic_detach(dev)))
777                 return (error);
778
779 #ifdef PC98
780         /* reset controller, turn motor off */
781         fdc_reset(fdc);
782 #else
783         /* reset controller, turn motor off */
784         fdout_wr(fdc, 0);
785 #endif
786
787         fdc_release_resources(fdc);
788         return (0);
789 }
790
791 /*
792  * Add a child device to the fdc controller.  It will then be probed etc.
793  */
794 device_t
795 fdc_add_child(device_t dev, const char *name, int unit)
796 {
797         struct fdc_ivars *ivar;
798         device_t child;
799
800         ivar = malloc(sizeof *ivar, M_DEVBUF /* XXX */, M_NOWAIT | M_ZERO);
801         if (ivar == NULL)
802                 return (NULL);
803         child = device_add_child(dev, name, unit);
804         if (child == NULL) {
805                 free(ivar, M_DEVBUF);
806                 return (NULL);
807         }
808         device_set_ivars(child, ivar);
809         ivar->fdunit = unit;
810         ivar->fdtype = FDT_NONE;
811         if (resource_disabled(name, unit))
812                 device_disable(child);
813         return (child);
814 }
815
816 int
817 fdc_attach(device_t dev)
818 {
819         struct  fdc_data *fdc;
820         int     error;
821
822         fdc = device_get_softc(dev);
823         fdc->fdc_dev = dev;
824         error = bus_setup_intr(dev, fdc->res_irq,
825                                INTR_TYPE_BIO | INTR_ENTROPY, fdc_intr, fdc,
826                                &fdc->fdc_intr);
827         if (error) {
828                 device_printf(dev, "cannot setup interrupt\n");
829                 return error;
830         }
831         fdc->fdcu = device_get_unit(dev);
832         fdc->flags |= FDC_NEEDS_RESET;
833
834         fdc->state = DEVIDLE;
835
836 #ifdef PC98
837         /* reset controller, turn motor off, clear fdout mirror reg */
838         fdc_reset(fdc);
839 #else
840         /* reset controller, turn motor off, clear fdout mirror reg */
841         fdout_wr(fdc, fdc->fdout = 0);
842 #endif
843         bioq_init(&fdc->head);
844
845         return (0);
846 }
847
848 int
849 fdc_hints_probe(device_t dev)
850 {
851         const char *name, *dname;
852         int i, error, dunit;
853
854         /*
855          * Probe and attach any children.  We should probably detect
856          * devices from the BIOS unless overridden.
857          */
858         name = device_get_nameunit(dev);
859         i = 0;
860         while ((resource_find_match(&i, &dname, &dunit, "at", name)) == 0) {
861                 resource_int_value(dname, dunit, "drive", &dunit);
862                 fdc_add_child(dev, dname, dunit);
863         }
864
865         if ((error = bus_generic_attach(dev)) != 0)
866                 return (error);
867         return (0);
868 }
869
870 int
871 fdc_print_child(device_t me, device_t child)
872 {
873         int retval = 0, flags;
874
875         retval += bus_print_child_header(me, child);
876         retval += printf(" on %s drive %d", device_get_nameunit(me),
877                fdc_get_fdunit(child));
878         if ((flags = device_get_flags(me)) != 0)
879                 retval += printf(" flags %#x", flags);
880         retval += printf("\n");
881         
882         return (retval);
883 }
884
885 /*
886  * Configuration/initialization, per drive.
887  */
888 static int
889 fd_probe(device_t dev)
890 {
891         int     i;
892 #ifndef PC98
893         u_int   st0, st3;
894 #endif
895         struct  fd_data *fd;
896         struct  fdc_data *fdc;
897         fdsu_t  fdsu;
898         int     flags, type;
899
900         fdsu = fdc_get_fdunit(dev);
901         fd = device_get_softc(dev);
902         fdc = device_get_softc(device_get_parent(dev));
903         flags = device_get_flags(dev);
904
905         fd->dev = dev;
906         fd->fdc = fdc;
907         fd->fdsu = fdsu;
908         fd->fdu = device_get_unit(dev);
909
910         /* Auto-probe if fdinfo is present, but always allow override. */
911         type = FD_DTYPE(flags);
912         if (type == FDT_NONE && (type = fdc_get_fdtype(dev)) != FDT_NONE) {
913                 fd->type = type;
914                 goto done;
915         } else {
916                 /* make sure fdautoselect() will be called */
917                 fd->flags = FD_UA;
918                 fd->type = type;
919         }
920
921 #ifdef PC98
922         pc98_fd_check_type(fd);
923 #else
924 /*
925  * XXX I think using __i386__ is wrong here since we actually want to probe
926  * for the machine type, not the CPU type (so non-PC arch's like the PC98 will
927  * fail the probe).
928  */
929 #ifdef __i386__
930         if (fd->type == FDT_NONE && (fd->fdu == 0 || fd->fdu == 1)) {
931                 /* Look up what the BIOS thinks we have. */
932                 if (fd->fdu == 0) {
933                         if ((fdc->flags & FDC_ISPCMCIA))
934                                 /*
935                                  * Somewhat special.  No need to force the
936                                  * user to set device flags, since the Y-E
937                                  * Data PCMCIA floppy is always a 1.44 MB
938                                  * device.
939                                  */
940                                 fd->type = FDT_144M;
941                         else
942                                 fd->type = (rtcin(RTC_FDISKETTE) & 0xf0) >> 4;
943                 } else {
944                         fd->type = rtcin(RTC_FDISKETTE) & 0x0f;
945                 }
946                 if (fd->type == FDT_288M_1)
947                         fd->type = FDT_288M;
948         }
949 #endif /* __i386__ */
950 #endif /* PC98 */
951
952         /* is there a unit? */
953         if (fd->type == FDT_NONE)
954                 return (ENXIO);
955
956 #ifndef PC98
957         /* select it */
958         set_motor(fdc, fdsu, TURNON);
959         fdc_reset(fdc);         /* XXX reset, then unreset, etc. */
960         DELAY(1000000); /* 1 sec */
961
962         if ((flags & FD_NO_PROBE) == 0) {
963                 /* If we're at track 0 first seek inwards. */
964                 if ((fd_sense_drive_status(fdc, &st3) == 0) &&
965                     (st3 & NE7_ST3_T0)) {
966                         /* Seek some steps... */
967                         if (fd_cmd(fdc, 3, NE7CMD_SEEK, fdsu, 10, 0) == 0) {
968                                 /* ...wait a moment... */
969                                 DELAY(300000);
970                                 /* make ctrlr happy: */
971                                 fd_sense_int(fdc, 0, 0);
972                         }
973                 }
974
975                 for (i = 0; i < 2; i++) {
976                         /*
977                          * we must recalibrate twice, just in case the
978                          * heads have been beyond cylinder 76, since
979                          * most FDCs still barf when attempting to
980                          * recalibrate more than 77 steps
981                          */
982                         /* go back to 0: */
983                         if (fd_cmd(fdc, 2, NE7CMD_RECAL, fdsu, 0) == 0) {
984                                 /* a second being enough for full stroke seek*/
985                                 DELAY(i == 0 ? 1000000 : 300000);
986
987                                 /* anything responding? */
988                                 if (fd_sense_int(fdc, &st0, 0) == 0 &&
989                                     (st0 & NE7_ST0_EC) == 0)
990                                         break; /* already probed succesfully */
991                         }
992                 }
993         }
994
995         set_motor(fdc, fdsu, TURNOFF);
996
997         if ((flags & FD_NO_PROBE) == 0 &&
998             (st0 & NE7_ST0_EC) != 0) /* no track 0 -> no drive present */
999                 return (ENXIO);
1000 #endif /* PC98 */
1001
1002 done:
1003 #ifndef PC98
1004         /* This doesn't work before the first reset. */
1005         if ((fdc->flags & FDC_HAS_FIFO) == 0 &&
1006             fdc->fdct == FDC_ENHANCED &&
1007             (device_get_flags(fdc->fdc_dev) & FDC_NO_FIFO) == 0 &&
1008             enable_fifo(fdc) == 0) {
1009                 device_printf(device_get_parent(dev),
1010                     "FIFO enabled, %d bytes threshold\n", fifo_threshold);
1011         }
1012 #endif /* PC98 */
1013
1014 #ifdef PC98
1015         switch (fd->type) {
1016         case FDT_144M:
1017                 device_set_desc(dev, "1.44M FDD");
1018                 break;
1019         case FDT_12M:
1020                 device_set_desc(dev, "1M/640K FDD");
1021                 break;
1022         default:
1023                 return (ENXIO);
1024         }
1025 #else
1026         switch (fd->type) {
1027         case FDT_12M:
1028                 device_set_desc(dev, "1200-KB 5.25\" drive");
1029                 break;
1030         case FDT_144M:
1031                 device_set_desc(dev, "1440-KB 3.5\" drive");
1032                 break;
1033         case FDT_288M:
1034                 device_set_desc(dev, "2880-KB 3.5\" drive (in 1440-KB mode)");
1035                 break;
1036         case FDT_360K:
1037                 device_set_desc(dev, "360-KB 5.25\" drive");
1038                 break;
1039         case FDT_720K:
1040                 device_set_desc(dev, "720-KB 3.5\" drive");
1041                 break;
1042         default:
1043                 return (ENXIO);
1044         }
1045 #endif
1046         fd->track = FD_NO_TRACK;
1047         fd->fdc = fdc;
1048         fd->fdsu = fdsu;
1049         fd->options = 0;
1050 #ifdef PC98
1051         fd->pc98_trans = 0;
1052 #endif
1053         callout_handle_init(&fd->toffhandle);
1054         callout_handle_init(&fd->tohandle);
1055
1056         /* initialize densities for subdevices */
1057 #ifdef PC98
1058         for (i = 0; i < NUMDENS; i++)
1059                 memcpy(fd->fts + i, fd_searchlist_144m + i,
1060                        sizeof(struct fd_type));
1061 #else
1062         for (i = 0; i < NUMDENS; i++)
1063                 memcpy(fd->fts + i, fd_native_types + fd->type,
1064                        sizeof(struct fd_type));
1065 #endif
1066         return (0);
1067 }
1068
1069 static int
1070 fd_attach(device_t dev)
1071 {
1072         struct  fd_data *fd;
1073
1074         fd = device_get_softc(dev);
1075         fd->masterdev = make_dev(&fd_cdevsw, fd->fdu,
1076                                  UID_ROOT, GID_OPERATOR, 0640, "fd%d", fd->fdu);
1077         fd->masterdev->si_drv1 = fd;
1078         fd->device_stats = devstat_new_entry(device_get_name(dev), 
1079                           device_get_unit(dev), 0, DEVSTAT_NO_ORDERED_TAGS,
1080                           DEVSTAT_TYPE_FLOPPY | DEVSTAT_TYPE_IF_OTHER,
1081                           DEVSTAT_PRIORITY_FD);
1082         return (0);
1083 }
1084
1085 static int
1086 fd_detach(device_t dev)
1087 {
1088         struct  fd_data *fd;
1089
1090         fd = device_get_softc(dev);
1091         untimeout(fd_turnoff, fd, fd->toffhandle);
1092         devstat_remove_entry(fd->device_stats);
1093         destroy_dev(fd->masterdev);
1094
1095         return (0);
1096 }
1097
1098 static device_method_t fd_methods[] = {
1099         /* Device interface */
1100         DEVMETHOD(device_probe,         fd_probe),
1101         DEVMETHOD(device_attach,        fd_attach),
1102         DEVMETHOD(device_detach,        fd_detach),
1103         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
1104         DEVMETHOD(device_suspend,       bus_generic_suspend), /* XXX */
1105         DEVMETHOD(device_resume,        bus_generic_resume), /* XXX */
1106
1107         { 0, 0 }
1108 };
1109
1110 static driver_t fd_driver = {
1111         "fd",
1112         fd_methods,
1113         sizeof(struct fd_data)
1114 };
1115
1116 DRIVER_MODULE(fd, fdc, fd_driver, fd_devclass, 0, 0);
1117
1118 /*
1119  * More auxiliary functions.
1120  */
1121 /*
1122  * Motor control stuff.
1123  * Remember to not deselect the drive we're working on.
1124  */
1125 static void
1126 set_motor(struct fdc_data *fdc, int fdsu, int turnon)
1127 {
1128 #ifdef PC98
1129         bus_space_write_1(fdc->sc_fdsiot, fdc->sc_fdsioh, 0,
1130                           (pc98_trans != 1 ? FDP_FDDEXC : 0) | FDP_PORTEXC);
1131         DELAY(10);
1132         fdctl_wr(fdc, FDC_DMAE | FDC_MTON);
1133 #else
1134         int fdout;
1135
1136         fdout = fdc->fdout;
1137         if (turnon) {
1138                 fdout &= ~FDO_FDSEL;
1139                 fdout |= (FDO_MOEN0 << fdsu) | FDO_FDMAEN | FDO_FRST | fdsu;
1140         } else
1141                 fdout &= ~(FDO_MOEN0 << fdsu);
1142         fdc->fdout = fdout;
1143         fdout_wr(fdc, fdout);
1144         TRACE1("[0x%x->FDOUT]", fdout);
1145 #endif
1146 }
1147
1148 static void
1149 fd_turnoff(void *xfd)
1150 {
1151         int     s;
1152         fd_p fd = xfd;
1153
1154         TRACE1("[fd%d: turnoff]", fd->fdu);
1155
1156         s = splbio();
1157         /*
1158          * Don't turn off the motor yet if the drive is active.
1159          *
1160          * If we got here, this could only mean we missed an interrupt.
1161          * This can e. g. happen on the Y-E Date PCMCIA floppy controller
1162          * after a controller reset.  Just schedule a pseudo-interrupt
1163          * so the state machine gets re-entered.
1164          */
1165         if (fd->fdc->state != DEVIDLE && fd->fdc->fdu == fd->fdu) {
1166                 fdc_intr(fd->fdc);
1167                 splx(s);
1168                 return;
1169         }
1170
1171         fd->flags &= ~FD_MOTOR;
1172         set_motor(fd->fdc, fd->fdsu, TURNOFF);
1173         splx(s);
1174 }
1175
1176 static void
1177 fd_motor_on(void *xfd)
1178 {
1179         int     s;
1180         fd_p fd = xfd;
1181
1182         s = splbio();
1183         fd->flags &= ~FD_MOTOR_WAIT;
1184         if((fd->fdc->fd == fd) && (fd->fdc->state == MOTORWAIT))
1185         {
1186                 fdc_intr(fd->fdc);
1187         }
1188         splx(s);
1189 }
1190
1191 static void
1192 fd_turnon(fd_p fd)
1193 {
1194         if(!(fd->flags & FD_MOTOR))
1195         {
1196                 fd->flags |= (FD_MOTOR + FD_MOTOR_WAIT);
1197                 set_motor(fd->fdc, fd->fdsu, TURNON);
1198                 timeout(fd_motor_on, fd, hz); /* in 1 sec its ok */
1199         }
1200 }
1201
1202 static void
1203 fdc_reset(fdc_p fdc)
1204 {
1205         /* Try a reset, keep motor on */
1206 #ifdef PC98
1207         set_density(fdc);
1208         if (pc98_machine_type & M_EPSON_PC98)
1209                 fdctl_wr(fdc, FDC_RST | FDC_RDY | FDC_DD | FDC_MTON);
1210         else
1211                 fdctl_wr(fdc, FDC_RST | FDC_RDY | FDC_DMAE | FDC_MTON);
1212         DELAY(200);
1213         fdctl_wr(fdc, FDC_DMAE | FDC_MTON);
1214         DELAY(10);
1215 #else
1216         fdout_wr(fdc, fdc->fdout & ~(FDO_FRST|FDO_FDMAEN));
1217         TRACE1("[0x%x->FDOUT]", fdc->fdout & ~(FDO_FRST|FDO_FDMAEN));
1218         DELAY(100);
1219         /* enable FDC, but defer interrupts a moment */
1220         fdout_wr(fdc, fdc->fdout & ~FDO_FDMAEN);
1221         TRACE1("[0x%x->FDOUT]", fdc->fdout & ~FDO_FDMAEN);
1222         DELAY(100);
1223         fdout_wr(fdc, fdc->fdout);
1224         TRACE1("[0x%x->FDOUT]", fdc->fdout);
1225 #endif
1226
1227         /* XXX after a reset, silently believe the FDC will accept commands */
1228 #ifdef PC98
1229         (void)fd_cmd(fdc, 3, NE7CMD_SPECIFY,
1230                      NE7_SPEC_1(4, 240), NE7_SPEC_2(2, 0),
1231                      0);
1232 #else
1233         (void)fd_cmd(fdc, 3, NE7CMD_SPECIFY,
1234                      NE7_SPEC_1(3, 240), NE7_SPEC_2(2, 0),
1235                      0);
1236 #endif
1237         if (fdc->flags & FDC_HAS_FIFO)
1238                 (void) enable_fifo(fdc);
1239 }
1240
1241 /*
1242  * FDC IO functions, take care of the main status register, timeout
1243  * in case the desired status bits are never set.
1244  *
1245  * These PIO loops initially start out with short delays between
1246  * each iteration in the expectation that the required condition
1247  * is usually met quickly, so it can be handled immediately.  After
1248  * about 1 ms, stepping is increased to achieve a better timing
1249  * accuracy in the calls to DELAY().
1250  */
1251 static int
1252 fd_in(struct fdc_data *fdc, int *ptr)
1253 {
1254         int i, j, step;
1255
1256         for (j = 0, step = 1;
1257             (i = fdsts_rd(fdc) & (NE7_DIO|NE7_RQM)) != (NE7_DIO|NE7_RQM) &&
1258             j < FDSTS_TIMEOUT;
1259             j += step) {
1260                 if (i == NE7_RQM)
1261                         return (fdc_err(fdc, "ready for output in input\n"));
1262                 if (j == 1000)
1263                         step = 1000;
1264                 DELAY(step);
1265         }
1266         if (j >= FDSTS_TIMEOUT)
1267                 return (fdc_err(fdc, bootverbose? "input ready timeout\n": 0));
1268 #ifdef  FDC_DEBUG
1269         i = fddata_rd(fdc);
1270         TRACE1("[FDDATA->0x%x]", (unsigned char)i);
1271         *ptr = i;
1272         return (0);
1273 #else   /* !FDC_DEBUG */
1274         i = fddata_rd(fdc);
1275         if (ptr)
1276                 *ptr = i;
1277         return (0);
1278 #endif  /* FDC_DEBUG */
1279 }
1280
1281 static int
1282 out_fdc(struct fdc_data *fdc, int x)
1283 {
1284         int i, j, step;
1285
1286         for (j = 0, step = 1;
1287             (i = fdsts_rd(fdc) & (NE7_DIO|NE7_RQM)) != NE7_RQM &&
1288             j < FDSTS_TIMEOUT;
1289             j += step) {
1290                 if (i == (NE7_DIO|NE7_RQM))
1291                         return (fdc_err(fdc, "ready for input in output\n"));
1292                 if (j == 1000)
1293                         step = 1000;
1294                 DELAY(step);
1295         }
1296         if (j >= FDSTS_TIMEOUT)
1297                 return (fdc_err(fdc, bootverbose? "output ready timeout\n": 0));
1298
1299         /* Send the command and return */
1300         fddata_wr(fdc, x);
1301         TRACE1("[0x%x->FDDATA]", x);
1302         return (0);
1303 }
1304
1305 /*
1306  * Block device driver interface functions (interspersed with even more
1307  * auxiliary functions).
1308  */
1309 static int
1310 fdopen(struct cdev *dev, int flags, int mode, struct thread *td)
1311 {
1312         fd_p    fd;
1313         fdc_p   fdc;
1314 #ifdef PC98
1315         fdu_t   fdu;
1316 #endif
1317         int rv, unitattn, dflags;
1318
1319         fd = dev->si_drv1;
1320         if (fd == NULL)
1321                 return (ENXIO);
1322         fdc = fd->fdc;
1323         if ((fdc == NULL) || (fd->type == FDT_NONE))
1324                 return (ENXIO);
1325 #ifdef PC98
1326         fdu = fd->fdu;
1327 #endif
1328         dflags = device_get_flags(fd->dev);
1329         /*
1330          * This is a bit bogus.  It's still possible that e. g. a
1331          * descriptor gets inherited to a child, but then it's at
1332          * least for the same subdevice.  By checking FD_OPEN here, we
1333          * can ensure that a device isn't attempted to be opened with
1334          * different densities at the same time where the second open
1335          * could clobber the settings from the first one.
1336          */
1337         if (fd->flags & FD_OPEN)
1338                 return (EBUSY);
1339
1340 #ifdef PC98
1341         if (pc98_fd_check_ready(fdu) == -1)
1342                 return(EIO);
1343 #endif
1344
1345         if (flags & FNONBLOCK) {
1346                 /*
1347                  * Unfortunately, physio(9) discards its ioflag
1348                  * argument, thus preventing us from seeing the
1349                  * O_NONBLOCK bit.  So we need to keep track
1350                  * ourselves.
1351                  */
1352                 fd->flags |= FD_NONBLOCK;
1353                 fd->ft = 0;
1354         } else {
1355                 /*
1356                  * Figure out a unit attention condition.
1357                  *
1358                  * If UA has been forced, proceed.
1359                  *
1360                  * If the drive has no changeline support,
1361                  * or if the drive parameters have been lost
1362                  * due to previous non-blocking access,
1363                  * assume a forced UA condition.
1364                  *
1365                  * If motor is off, turn it on for a moment
1366                  * and select our drive, in order to read the
1367                  * UA hardware signal.
1368                  *
1369                  * If motor is on, and our drive is currently
1370                  * selected, just read the hardware bit.
1371                  *
1372                  * If motor is on, but active for another
1373                  * drive on that controller, we are lost.  We
1374                  * cannot risk to deselect the other drive, so
1375                  * we just assume a forced UA condition to be
1376                  * on the safe side.
1377                  */
1378                 unitattn = 0;
1379                 if ((dflags & FD_NO_CHLINE) != 0 ||
1380                     (fd->flags & FD_UA) != 0 ||
1381                     fd->ft == 0) {
1382                         unitattn = 1;
1383                         fd->flags &= ~FD_UA;
1384 #ifndef PC98
1385                 } else if (fdc->fdout & (FDO_MOEN0 | FDO_MOEN1 |
1386                                          FDO_MOEN2 | FDO_MOEN3)) {
1387                         if ((fdc->fdout & FDO_FDSEL) == fd->fdsu)
1388                                 unitattn = fdin_rd(fdc) & FDI_DCHG;
1389                         else
1390                                 unitattn = 1;
1391                 } else {
1392                         set_motor(fdc, fd->fdsu, TURNON);
1393                         unitattn = fdin_rd(fdc) & FDI_DCHG;
1394                         set_motor(fdc, fd->fdsu, TURNOFF);
1395 #endif /* PC98 */
1396                 }
1397                 if (unitattn && (rv = fdautoselect(dev)) != 0)
1398                         return (rv);
1399         }
1400         fd->flags |= FD_OPEN;
1401
1402         if ((fdc->flags & FDC_NODMA) == 0) {
1403                 if (fdc->dmacnt++ == 0) {
1404                         isa_dma_acquire(fdc->dmachan);
1405                         isa_dmainit(fdc->dmachan, MAX_SEC_SIZE);
1406                 }
1407         }
1408
1409         /*
1410          * Clearing the DMA overrun counter at open time is a bit messy.
1411          * Since we're only managing one counter per controller, opening
1412          * the second drive could mess it up.  Anyway, if the DMA overrun
1413          * condition is really persistent, it will eventually time out
1414          * still.  OTOH, clearing it here will ensure we'll at least start
1415          * trying again after a previous (maybe even long ago) failure.
1416          * Also, this is merely a stop-gap measure only that should not
1417          * happen during normal operation, so we can tolerate it to be a
1418          * bit sloppy about this.
1419          */
1420         fdc->dma_overruns = 0;
1421
1422         return 0;
1423 }
1424
1425 static int
1426 fdclose(struct cdev *dev, int flags, int mode, struct thread *td)
1427 {
1428         struct fd_data *fd;
1429         fdc_p   fdc;
1430
1431         fd = dev->si_drv1;
1432         fdc = fd->fdc;
1433         fd->flags &= ~(FD_OPEN | FD_NONBLOCK);
1434         fd->options &= ~(FDOPT_NORETRY | FDOPT_NOERRLOG | FDOPT_NOERROR);
1435
1436         if ((fdc->flags & FDC_NODMA) == 0)
1437                 if (--fdc->dmacnt == 0)
1438                         isa_dma_release(fdc->dmachan);
1439
1440         return (0);
1441 }
1442
1443 static void
1444 fdstrategy(struct bio *bp)
1445 {
1446         long blknum, nblocks;
1447         int     s;
1448         fdu_t   fdu;
1449         fdc_p   fdc;
1450         fd_p    fd;
1451         size_t  fdblk;
1452
1453         fd = bp->bio_dev->si_drv1;
1454         fdu = fd->fdu;
1455         fdc = fd->fdc;
1456         bp->bio_resid = bp->bio_bcount;
1457         if (fd->type == FDT_NONE || fd->ft == 0) {
1458                 if (fd->type != FDT_NONE && (fd->flags & FD_NONBLOCK))
1459                         bp->bio_error = EAGAIN;
1460                 else
1461                         bp->bio_error = ENXIO;
1462                 bp->bio_flags |= BIO_ERROR;
1463                 goto bad;
1464         }
1465         fdblk = 128 << (fd->ft->secsize);
1466         if (bp->bio_cmd != FDBIO_FORMAT && bp->bio_cmd != FDBIO_RDSECTID) {
1467                 if (fd->flags & FD_NONBLOCK) {
1468                         bp->bio_error = EAGAIN;
1469                         bp->bio_flags |= BIO_ERROR;
1470                         goto bad;
1471                 }
1472                 if (bp->bio_offset < 0) {
1473                         printf(
1474                 "fd%d: fdstrat: bad request offset = %ju, bcount = %ld\n",
1475                                fdu, (intmax_t)bp->bio_offset, bp->bio_bcount);
1476                         bp->bio_error = EINVAL;
1477                         bp->bio_flags |= BIO_ERROR;
1478                         goto bad;
1479                 }
1480                 if ((bp->bio_bcount % fdblk) != 0) {
1481                         bp->bio_error = EINVAL;
1482                         bp->bio_flags |= BIO_ERROR;
1483                         goto bad;
1484                 }
1485         }
1486
1487         /*
1488          * Set up block calculations.
1489          */
1490 #ifndef PC98
1491         if (bp->bio_offset >= ((off_t)128 << fd->ft->secsize) * fd->ft->size) {
1492                 bp->bio_error = EINVAL;
1493                 bp->bio_flags |= BIO_ERROR;
1494                 goto bad;
1495         }
1496 #endif
1497         blknum = bp->bio_offset / fdblk;
1498         nblocks = fd->ft->size;
1499         if (blknum + bp->bio_bcount / fdblk > nblocks) {
1500                 if (blknum >= nblocks) {
1501                         if (bp->bio_cmd != BIO_READ) {
1502                                 bp->bio_error = ENOSPC;
1503                                 bp->bio_flags |= BIO_ERROR;
1504                         }
1505                         goto bad;       /* not always bad, but EOF */
1506                 }
1507                 bp->bio_bcount = (nblocks - blknum) * fdblk;
1508         }
1509         bp->bio_pblkno = blknum;
1510         s = splbio();
1511         bioq_disksort(&fdc->head, bp);
1512         untimeout(fd_turnoff, fd, fd->toffhandle); /* a good idea */
1513         devstat_start_transaction_bio(fd->device_stats, bp);
1514         device_busy(fd->dev);
1515         fdstart(fdc);
1516         splx(s);
1517         return;
1518
1519 bad:
1520         biodone(bp);
1521 }
1522
1523 /*
1524  * fdstart
1525  *
1526  * We have just queued something.  If the controller is not busy
1527  * then simulate the case where it has just finished a command
1528  * So that it (the interrupt routine) looks on the queue for more
1529  * work to do and picks up what we just added.
1530  *
1531  * If the controller is already busy, we need do nothing, as it
1532  * will pick up our work when the present work completes.
1533  */
1534 static void
1535 fdstart(struct fdc_data *fdc)
1536 {
1537         int s;
1538
1539         s = splbio();
1540         if(fdc->state == DEVIDLE)
1541         {
1542                 fdc_intr(fdc);
1543         }
1544         splx(s);
1545 }
1546
1547 static void
1548 fd_iotimeout(void *xfdc)
1549 {
1550         fdc_p fdc;
1551         int s;
1552
1553         fdc = xfdc;
1554         TRACE1("fd%d[fd_iotimeout()]", fdc->fdu);
1555
1556         /*
1557          * Due to IBM's brain-dead design, the FDC has a faked ready
1558          * signal, hardwired to ready == true. Thus, any command
1559          * issued if there's no diskette in the drive will _never_
1560          * complete, and must be aborted by resetting the FDC.
1561          * Many thanks, Big Blue!
1562          * The FDC must not be reset directly, since that would
1563          * interfere with the state machine.  Instead, pretend that
1564          * the command completed but was invalid.  The state machine
1565          * will reset the FDC and retry once.
1566          */
1567         s = splbio();
1568         fdc->status[0] = NE7_ST0_IC_IV;
1569         fdc->flags &= ~FDC_STAT_VALID;
1570         fdc->state = IOTIMEDOUT;
1571         fdc_intr(fdc);
1572         splx(s);
1573 }
1574
1575 /* Just ensure it has the right spl. */
1576 static void
1577 fd_pseudointr(void *xfdc)
1578 {
1579         int     s;
1580
1581         s = splbio();
1582         fdc_intr(xfdc);
1583         splx(s);
1584 }
1585
1586 /*
1587  * fdc_intr
1588  *
1589  * Keep calling the state machine until it returns a 0.
1590  * Always called at splbio.
1591  */
1592 static void
1593 fdc_intr(void *xfdc)
1594 {
1595         fdc_p fdc = xfdc;
1596         while(fdstate(fdc))
1597                 ;
1598 }
1599
1600 /*
1601  * Magic pseudo-DMA initialization for YE FDC. Sets count and
1602  * direction.
1603  */
1604 #define SET_BCDR(fdc,wr,cnt,port) \
1605         bus_space_write_1(fdc->portt, fdc->porth, fdc->port_off + port,  \
1606             ((cnt)-1) & 0xff);                                           \
1607         bus_space_write_1(fdc->portt, fdc->porth, fdc->port_off + port + 1, \
1608             ((wr ? 0x80 : 0) | ((((cnt)-1) >> 8) & 0x7f)));
1609
1610 /*
1611  * fdcpio(): perform programmed IO read/write for YE PCMCIA floppy.
1612  */
1613 static int
1614 fdcpio(fdc_p fdc, long flags, caddr_t addr, u_int count)
1615 {
1616         u_char *cptr = (u_char *)addr;
1617
1618         if (flags == BIO_READ) {
1619                 if (fdc->state != PIOREAD) {
1620                         fdc->state = PIOREAD;
1621                         return(0);
1622                 }
1623                 SET_BCDR(fdc, 0, count, 0);
1624                 bus_space_read_multi_1(fdc->portt, fdc->porth, fdc->port_off +
1625                     FDC_YE_DATAPORT, cptr, count);
1626         } else {
1627                 bus_space_write_multi_1(fdc->portt, fdc->porth, fdc->port_off +
1628                     FDC_YE_DATAPORT, cptr, count);
1629                 SET_BCDR(fdc, 0, count, 0);
1630         }
1631         return(1);
1632 }
1633
1634 /*
1635  * Try figuring out the density of the media present in our device.
1636  */
1637 static int
1638 fdautoselect(struct cdev *dev)
1639 {
1640         fd_p fd;
1641         struct fd_type *fdtp;
1642         struct fdc_readid id;
1643         int i, n, oopts, rv;
1644
1645         fd = dev->si_drv1;
1646
1647         switch (fd->type) {
1648         default:
1649                 return (ENXIO);
1650
1651 #ifndef PC98
1652         case FDT_360K:
1653         case FDT_720K:
1654                 /* no autoselection on those drives */
1655                 fd->ft = fd_native_types + fd->type;
1656                 return (0);
1657 #endif
1658
1659         case FDT_12M:
1660                 fdtp = fd_searchlist_12m;
1661                 n = sizeof fd_searchlist_12m / sizeof(struct fd_type);
1662                 break;
1663
1664         case FDT_144M:
1665                 fdtp = fd_searchlist_144m;
1666                 n = sizeof fd_searchlist_144m / sizeof(struct fd_type);
1667                 break;
1668
1669 #ifndef PC98
1670         case FDT_288M:
1671                 fdtp = fd_searchlist_288m;
1672                 n = sizeof fd_searchlist_288m / sizeof(struct fd_type);
1673                 break;
1674 #endif
1675         }
1676
1677         /*
1678          * Try reading sector ID fields, first at cylinder 0, head 0,
1679          * then at cylinder 2, head N.  We don't probe cylinder 1,
1680          * since for 5.25in DD media in a HD drive, there are no data
1681          * to read (2 step pulses per media cylinder required).  For
1682          * two-sided media, the second probe always goes to head 1, so
1683          * we can tell them apart from single-sided media.  As a
1684          * side-effect this means that single-sided media should be
1685          * mentioned in the search list after two-sided media of an
1686          * otherwise identical density.  Media with a different number
1687          * of sectors per track but otherwise identical parameters
1688          * cannot be distinguished at all.
1689          *
1690          * If we successfully read an ID field on both cylinders where
1691          * the recorded values match our expectation, we are done.
1692          * Otherwise, we try the next density entry from the table.
1693          *
1694          * Stepping to cylinder 2 has the side-effect of clearing the
1695          * unit attention bit.
1696          */
1697         oopts = fd->options;
1698         fd->options |= FDOPT_NOERRLOG | FDOPT_NORETRY;
1699         for (i = 0; i < n; i++, fdtp++) {
1700                 fd->ft = fdtp;
1701
1702                 id.cyl = id.head = 0;
1703                 rv = fdmisccmd(dev, FDBIO_RDSECTID, &id);
1704                 if (rv != 0)
1705                         continue;
1706                 if (id.cyl != 0 || id.head != 0 ||
1707                     id.secshift != fdtp->secsize)
1708                         continue;
1709                 id.cyl = 2;
1710                 id.head = fd->ft->heads - 1;
1711                 rv = fdmisccmd(dev, FDBIO_RDSECTID, &id);
1712                 if (id.cyl != 2 || id.head != fdtp->heads - 1 ||
1713                     id.secshift != fdtp->secsize)
1714                         continue;
1715                 if (rv == 0)
1716                         break;
1717         }
1718
1719         fd->options = oopts;
1720         if (i == n) {
1721                 if (bootverbose)
1722                         device_printf(fd->dev, "autoselection failed\n");
1723                 fd->ft = 0;
1724                 return (EIO);
1725         } else {
1726                 if (bootverbose)
1727                         device_printf(fd->dev, "autoselected %d KB medium\n",
1728 #ifdef PC98
1729                                       (128 << (fd->ft->secsize)) *
1730                                       fd->ft->size / 1024);
1731 #else
1732                                       fd->ft->size / 2);
1733 #endif
1734                 return (0);
1735         }
1736 }
1737
1738
1739 /*
1740  * The controller state machine.
1741  *
1742  * If it returns a non zero value, it should be called again immediately.
1743  */
1744 static int
1745 fdstate(fdc_p fdc)
1746 {
1747         struct fdc_readid *idp;
1748         int read, format, rdsectid, cylinder, head, i, sec = 0, sectrac;
1749         int st0, cyl, st3, idf, ne7cmd, mfm, steptrac;
1750         unsigned long blknum;
1751         fdu_t fdu = fdc->fdu;
1752         fd_p fd;
1753         register struct bio *bp;
1754         struct fd_formb *finfo = NULL;
1755         size_t fdblk;
1756
1757         bp = fdc->bp;
1758         if (bp == NULL) {
1759                 bp = bioq_takefirst(&fdc->head);
1760                 if (bp != NULL)
1761                         fdc->bp = bp;
1762         }
1763         if (bp == NULL) {
1764                 /*
1765                  * Nothing left for this controller to do,
1766                  * force into the IDLE state.
1767                  */
1768                 fdc->state = DEVIDLE;
1769                 if (fdc->fd) {
1770                         device_printf(fdc->fdc_dev,
1771                             "unexpected valid fd pointer\n");
1772                         fdc->fd = (fd_p) 0;
1773                         fdc->fdu = -1;
1774                 }
1775                 TRACE1("[fdc%d IDLE]", fdc->fdcu);
1776                 return (0);
1777         }
1778         fd = bp->bio_dev->si_drv1;
1779         fdu = fd->fdu;
1780         fdblk = 128 << fd->ft->secsize;
1781         if (fdc->fd && (fd != fdc->fd))
1782                 device_printf(fd->dev, "confused fd pointers\n");
1783         read = bp->bio_cmd == BIO_READ;
1784         mfm = (fd->ft->flags & FL_MFM)? NE7CMD_MFM: 0;
1785         steptrac = (fd->ft->flags & FL_2STEP)? 2: 1;
1786         if (read)
1787                 idf = ISADMA_READ;
1788         else
1789                 idf = ISADMA_WRITE;
1790         format = bp->bio_cmd == FDBIO_FORMAT;
1791         rdsectid = bp->bio_cmd == FDBIO_RDSECTID;
1792         if (format)
1793                 finfo = (struct fd_formb *)bp->bio_data;
1794         TRACE1("fd%d", fdu);
1795         TRACE1("[%s]", fdstates[fdc->state]);
1796         TRACE1("(0x%x)", fd->flags);
1797         untimeout(fd_turnoff, fd, fd->toffhandle);
1798         fd->toffhandle = timeout(fd_turnoff, fd, 4 * hz);
1799         switch (fdc->state)
1800         {
1801         case DEVIDLE:
1802         case FINDWORK:  /* we have found new work */
1803                 fdc->retry = 0;
1804                 fd->skip = 0;
1805                 fdc->fd = fd;
1806                 fdc->fdu = fdu;
1807 #ifdef PC98
1808                 pc98_trans = fd->ft->trans;
1809                 if (pc98_trans_prev != pc98_trans) {
1810                         int i;
1811                         set_density(fdc);
1812                         for (i = 0; i < 10; i++) {
1813                                 outb(0x5f, 0);
1814                                 outb(0x5f, 0);
1815                         }
1816                         pc98_trans_prev = pc98_trans;
1817                 }
1818                 if (pc98_trans != fd->pc98_trans) {
1819                         if (fd->type == FDT_144M) {
1820                                 bus_space_write_1(fdc->sc_fdemsiot,
1821                                                   fdc->sc_fdemsioh,
1822                                                   0,
1823                                                   (fdu << 5) | 0x10 |
1824                                                   (pc98_trans >> 1));
1825                                 outb(0x5f, 0);
1826                                 outb(0x5f, 0);
1827                         }
1828                         fd->pc98_trans = pc98_trans;
1829                 }
1830 #else
1831                 fdc->fdctl_wr(fdc, fd->ft->trans);
1832 #endif
1833                 TRACE1("[0x%x->FDCTL]", fd->ft->trans);
1834                 /*
1835                  * If the next drive has a motor startup pending, then
1836                  * it will start up in its own good time.
1837                  */
1838                 if(fd->flags & FD_MOTOR_WAIT) {
1839                         fdc->state = MOTORWAIT;
1840                         return (0); /* will return later */
1841                 }
1842                 /*
1843                  * Maybe if it's not starting, it SHOULD be starting.
1844                  */
1845                 if (!(fd->flags & FD_MOTOR))
1846                 {
1847                         fdc->state = MOTORWAIT;
1848                         fd_turnon(fd);
1849                         return (0); /* will return later */
1850                 }
1851                 else    /* at least make sure we are selected */
1852                 {
1853                         set_motor(fdc, fd->fdsu, TURNON);
1854                 }
1855                 if (fdc->flags & FDC_NEEDS_RESET) {
1856                         fdc->state = RESETCTLR;
1857                         fdc->flags &= ~FDC_NEEDS_RESET;
1858                 } else
1859                         fdc->state = DOSEEK;
1860                 return (1);     /* will return immediately */
1861
1862         case DOSEEK:
1863                 blknum = bp->bio_pblkno + fd->skip / fdblk;
1864                 cylinder = blknum / (fd->ft->sectrac * fd->ft->heads);
1865                 if (cylinder == fd->track)
1866                 {
1867                         fdc->state = SEEKCOMPLETE;
1868                         return (1); /* will return immediately */
1869                 }
1870 #ifdef PC98
1871                 pc98_fd_check_ready(fdu);
1872 #endif
1873                 if (fd_cmd(fdc, 3, NE7CMD_SEEK,
1874                            fd->fdsu, cylinder * steptrac, 0))
1875                 {
1876                         /*
1877                          * Seek command not accepted, looks like
1878                          * the FDC went off to the Saints...
1879                          */
1880                         fdc->retry = 6; /* try a reset */
1881                         return(retrier(fdc));
1882                 }
1883                 fd->track = FD_NO_TRACK;
1884                 fdc->state = SEEKWAIT;
1885                 return(0);      /* will return later */
1886
1887         case SEEKWAIT:
1888                 /* allow heads to settle */
1889                 timeout(fd_pseudointr, fdc, hz / 16);
1890                 fdc->state = SEEKCOMPLETE;
1891                 return(0);      /* will return later */
1892
1893         case SEEKCOMPLETE : /* seek done, start DMA */
1894                 blknum = bp->bio_pblkno + fd->skip / fdblk;
1895                 cylinder = blknum / (fd->ft->sectrac * fd->ft->heads);
1896
1897                 /* Make sure seek really happened. */
1898                 if(fd->track == FD_NO_TRACK) {
1899                         int descyl = cylinder * steptrac;
1900                         do {
1901                                 /*
1902                                  * This might be a "ready changed" interrupt,
1903                                  * which cannot really happen since the
1904                                  * RDY pin is hardwired to + 5 volts.  This
1905                                  * generally indicates a "bouncing" intr
1906                                  * line, so do one of the following:
1907                                  *
1908                                  * When running on an enhanced FDC that is
1909                                  * known to not go stuck after responding
1910                                  * with INVALID, fetch all interrupt states
1911                                  * until seeing either an INVALID or a
1912                                  * real interrupt condition.
1913                                  *
1914                                  * When running on a dumb old NE765, give
1915                                  * up immediately.  The controller will
1916                                  * provide up to four dummy RC interrupt
1917                                  * conditions right after reset (for the
1918                                  * corresponding four drives), so this is
1919                                  * our only chance to get notice that it
1920                                  * was not the FDC that caused the interrupt.
1921                                  */
1922                                 if (fd_sense_int(fdc, &st0, &cyl)
1923                                     == FD_NOT_VALID)
1924                                         return (0); /* will return later */
1925                                 if(fdc->fdct == FDC_NE765
1926                                    && (st0 & NE7_ST0_IC) == NE7_ST0_IC_RC)
1927                                         return (0); /* hope for a real intr */
1928                         } while ((st0 & NE7_ST0_IC) == NE7_ST0_IC_RC);
1929
1930                         if (0 == descyl) {
1931                                 int failed = 0;
1932                                 /*
1933                                  * seek to cyl 0 requested; make sure we are
1934                                  * really there
1935                                  */
1936                                 if (fd_sense_drive_status(fdc, &st3))
1937                                         failed = 1;
1938                                 if ((st3 & NE7_ST3_T0) == 0) {
1939                                         printf(
1940                 "fd%d: Seek to cyl 0, but not really there (ST3 = %b)\n",
1941                                                fdu, st3, NE7_ST3BITS);
1942                                         failed = 1;
1943                                 }
1944
1945                                 if (failed) {
1946                                         if(fdc->retry < 3)
1947                                                 fdc->retry = 3;
1948                                         return (retrier(fdc));
1949                                 }
1950                         }
1951
1952                         if (cyl != descyl) {
1953                                 printf(
1954                 "fd%d: Seek to cyl %d failed; am at cyl %d (ST0 = 0x%x)\n",
1955                                        fdu, descyl, cyl, st0);
1956                                 if (fdc->retry < 3)
1957                                         fdc->retry = 3;
1958                                 return (retrier(fdc));
1959                         }
1960                 }
1961
1962                 fd->track = cylinder;
1963                 if (format)
1964                         fd->skip = (char *)&(finfo->fd_formb_cylno(0))
1965                             - (char *)finfo;
1966                 if (!rdsectid && !(fdc->flags & FDC_NODMA))
1967                         isa_dmastart(idf, bp->bio_data+fd->skip,
1968                                 format ? bp->bio_bcount : fdblk, fdc->dmachan);
1969                 blknum = bp->bio_pblkno + fd->skip / fdblk;
1970                 sectrac = fd->ft->sectrac;
1971                 sec = blknum %  (sectrac * fd->ft->heads);
1972                 head = sec / sectrac;
1973                 sec = sec % sectrac + 1;
1974                 if (head != 0 && fd->ft->offset_side2 != 0)
1975                         sec += fd->ft->offset_side2;
1976                 fd->hddrv = ((head&1)<<2)+fdu;
1977
1978                 if(format || !(read || rdsectid))
1979                 {
1980                         /* make sure the drive is writable */
1981                         if(fd_sense_drive_status(fdc, &st3) != 0)
1982                         {
1983                                 /* stuck controller? */
1984                                 if (!(fdc->flags & FDC_NODMA))
1985                                         isa_dmadone(idf,
1986                                                     bp->bio_data + fd->skip,
1987                                                     format ? bp->bio_bcount : fdblk,
1988                                                     fdc->dmachan);
1989                                 fdc->retry = 6; /* reset the beast */
1990                                 return (retrier(fdc));
1991                         }
1992                         if(st3 & NE7_ST3_WP)
1993                         {
1994                                 /*
1995                                  * XXX YES! this is ugly.
1996                                  * in order to force the current operation
1997                                  * to fail, we will have to fake an FDC
1998                                  * error - all error handling is done
1999                                  * by the retrier()
2000                                  */
2001                                 fdc->status[0] = NE7_ST0_IC_AT;
2002                                 fdc->status[1] = NE7_ST1_NW;
2003                                 fdc->status[2] = 0;
2004                                 fdc->status[3] = fd->track;
2005                                 fdc->status[4] = head;
2006                                 fdc->status[5] = sec;
2007                                 fdc->retry = 8; /* break out immediately */
2008                                 fdc->state = IOTIMEDOUT; /* not really... */
2009                                 return (1); /* will return immediately */
2010                         }
2011                 }
2012
2013                 if (format) {
2014                         ne7cmd = NE7CMD_FORMAT | mfm;
2015                         if (fdc->flags & FDC_NODMA) {
2016                                 /*
2017                                  * This seems to be necessary for
2018                                  * whatever obscure reason; if we omit
2019                                  * it, we end up filling the sector ID
2020                                  * fields of the newly formatted track
2021                                  * entirely with garbage, causing
2022                                  * `wrong cylinder' errors all over
2023                                  * the place when trying to read them
2024                                  * back.
2025                                  *
2026                                  * Umpf.
2027                                  */
2028                                 SET_BCDR(fdc, 1, bp->bio_bcount, 0);
2029
2030                                 (void)fdcpio(fdc,bp->bio_cmd,
2031                                         bp->bio_data+fd->skip,
2032                                         bp->bio_bcount);
2033
2034                         }
2035                         /* formatting */
2036                         if(fd_cmd(fdc, 6,  ne7cmd, head << 2 | fdu,
2037                                   finfo->fd_formb_secshift,
2038                                   finfo->fd_formb_nsecs,
2039                                   finfo->fd_formb_gaplen,
2040                                   finfo->fd_formb_fillbyte, 0)) {
2041                                 /* controller fell over */
2042                                 if (!(fdc->flags & FDC_NODMA))
2043                                         isa_dmadone(idf,
2044                                                     bp->bio_data + fd->skip,
2045                                                     format ? bp->bio_bcount : fdblk,
2046                                                     fdc->dmachan);
2047                                 fdc->retry = 6;
2048                                 return (retrier(fdc));
2049                         }
2050                 } else if (rdsectid) {
2051                         ne7cmd = NE7CMD_READID | mfm;
2052                         if (fd_cmd(fdc, 2, ne7cmd, head << 2 | fdu, 0)) {
2053                                 /* controller jamming */
2054                                 fdc->retry = 6;
2055                                 return (retrier(fdc));
2056                         }
2057                 } else {
2058                         /* read or write operation */
2059                         ne7cmd = (read ? NE7CMD_READ | NE7CMD_SK : NE7CMD_WRITE) | mfm;
2060                         if (fdc->flags & FDC_NODMA) {
2061                                 /*
2062                                  * This seems to be necessary even when
2063                                  * reading data.
2064                                  */
2065                                 SET_BCDR(fdc, 1, fdblk, 0);
2066
2067                                 /*
2068                                  * Perform the write pseudo-DMA before
2069                                  * the WRITE command is sent.
2070                                  */
2071                                 if (!read)
2072                                         (void)fdcpio(fdc,bp->bio_cmd,
2073                                             bp->bio_data+fd->skip,
2074                                             fdblk);
2075                         }
2076                         if (fd_cmd(fdc, 9,
2077                                    ne7cmd,
2078                                    head << 2 | fdu,  /* head & unit */
2079                                    fd->track,        /* track */
2080                                    head,
2081                                    sec,              /* sector + 1 */
2082                                    fd->ft->secsize,  /* sector size */
2083                                    sectrac,          /* sectors/track */
2084                                    fd->ft->gap,      /* gap size */
2085                                    fd->ft->datalen,  /* data length */
2086                                    0)) {
2087                                 /* the beast is sleeping again */
2088                                 if (!(fdc->flags & FDC_NODMA))
2089                                         isa_dmadone(idf,
2090                                                     bp->bio_data + fd->skip,
2091                                                     format ? bp->bio_bcount : fdblk,
2092                                                     fdc->dmachan);
2093                                 fdc->retry = 6;
2094                                 return (retrier(fdc));
2095                         }
2096                 }
2097                 if (!rdsectid && (fdc->flags & FDC_NODMA))
2098                         /*
2099                          * If this is a read, then simply await interrupt
2100                          * before performing PIO.
2101                          */
2102                         if (read && !fdcpio(fdc,bp->bio_cmd,
2103                             bp->bio_data+fd->skip,fdblk)) {
2104                                 fd->tohandle = timeout(fd_iotimeout, fdc, hz);
2105                                 return(0);      /* will return later */
2106                         }
2107
2108                 /*
2109                  * Write (or format) operation will fall through and
2110                  * await completion interrupt.
2111                  */
2112                 fdc->state = IOCOMPLETE;
2113                 fd->tohandle = timeout(fd_iotimeout, fdc, hz);
2114                 return (0);     /* will return later */
2115
2116         case PIOREAD:
2117                 /* 
2118                  * Actually perform the PIO read.  The IOCOMPLETE case
2119                  * removes the timeout for us.
2120                  */
2121                 (void)fdcpio(fdc,bp->bio_cmd,bp->bio_data+fd->skip,fdblk);
2122                 fdc->state = IOCOMPLETE;
2123                 /* FALLTHROUGH */
2124         case IOCOMPLETE: /* IO done, post-analyze */
2125                 untimeout(fd_iotimeout, fdc, fd->tohandle);
2126
2127                 if (fd_read_status(fdc)) {
2128                         if (!rdsectid && !(fdc->flags & FDC_NODMA))
2129                                 isa_dmadone(idf, bp->bio_data + fd->skip,
2130                                             format ? bp->bio_bcount : fdblk,
2131                                             fdc->dmachan);
2132                         if (fdc->retry < 6)
2133                                 fdc->retry = 6; /* force a reset */
2134                         return (retrier(fdc));
2135                 }
2136
2137                 fdc->state = IOTIMEDOUT;
2138
2139                 /* FALLTHROUGH */
2140         case IOTIMEDOUT:
2141                 if (!rdsectid && !(fdc->flags & FDC_NODMA))
2142                         isa_dmadone(idf, bp->bio_data + fd->skip,
2143                                 format ? bp->bio_bcount : fdblk, fdc->dmachan);
2144                 if (fdc->status[0] & NE7_ST0_IC) {
2145                         if ((fdc->status[0] & NE7_ST0_IC) == NE7_ST0_IC_AT
2146                             && fdc->status[1] & NE7_ST1_OR) {
2147                                 /*
2148                                  * DMA overrun. Someone hogged the bus and
2149                                  * didn't release it in time for the next
2150                                  * FDC transfer.
2151                                  *
2152                                  * We normally restart this without bumping
2153                                  * the retry counter.  However, in case
2154                                  * something is seriously messed up (like
2155                                  * broken hardware), we rather limit the
2156                                  * number of retries so the IO operation
2157                                  * doesn't block indefinately.
2158                                  */
2159                                 if (fdc->dma_overruns++ < FDC_DMAOV_MAX) {
2160                                         fdc->state = SEEKCOMPLETE;
2161                                         return (1);/* will return immediately */
2162                                 } /* else fall through */
2163                         }
2164                         if((fdc->status[0] & NE7_ST0_IC) == NE7_ST0_IC_IV
2165                                 && fdc->retry < 6)
2166                                 fdc->retry = 6; /* force a reset */
2167                         else if((fdc->status[0] & NE7_ST0_IC) == NE7_ST0_IC_AT
2168                                 && fdc->status[2] & NE7_ST2_WC
2169                                 && fdc->retry < 3)
2170                                 fdc->retry = 3; /* force recalibrate */
2171                         return (retrier(fdc));
2172                 }
2173                 /* All OK */
2174                 if (rdsectid) {
2175                         /* copy out ID field contents */
2176                         idp = (struct fdc_readid *)bp->bio_data;
2177                         idp->cyl = fdc->status[3];
2178                         idp->head = fdc->status[4];
2179                         idp->sec = fdc->status[5];
2180                         idp->secshift = fdc->status[6];
2181                 }
2182                 /* Operation successful, retry DMA overruns again next time. */
2183                 fdc->dma_overruns = 0;
2184                 fd->skip += fdblk;
2185                 if (!rdsectid && !format && fd->skip < bp->bio_bcount) {
2186                         /* set up next transfer */
2187                         fdc->state = DOSEEK;
2188                 } else {
2189                         /* ALL DONE */
2190                         fd->skip = 0;
2191                         bp->bio_resid = 0;
2192                         fdc->bp = NULL;
2193                         device_unbusy(fd->dev);
2194                         biofinish(bp, fd->device_stats, 0);
2195                         fdc->fd = (fd_p) 0;
2196                         fdc->fdu = -1;
2197                         fdc->state = FINDWORK;
2198                 }
2199                 return (1);     /* will return immediately */
2200
2201         case RESETCTLR:
2202                 fdc_reset(fdc);
2203                 fdc->retry++;
2204                 fdc->state = RESETCOMPLETE;
2205                 return (0);     /* will return later */
2206
2207         case RESETCOMPLETE:
2208                 /*
2209                  * Discard all the results from the reset so that they
2210                  * can't cause an unexpected interrupt later.
2211                  */
2212                 for (i = 0; i < 4; i++)
2213                         (void)fd_sense_int(fdc, &st0, &cyl);
2214                 fdc->state = STARTRECAL;
2215                 /* FALLTHROUGH */
2216         case STARTRECAL:
2217 #ifdef PC98
2218                 pc98_fd_check_ready(fdu);
2219 #endif
2220                 if(fd_cmd(fdc, 2, NE7CMD_RECAL, fdu, 0)) {
2221                         /* arrgl */
2222                         fdc->retry = 6;
2223                         return (retrier(fdc));
2224                 }
2225                 fdc->state = RECALWAIT;
2226                 return (0);     /* will return later */
2227
2228         case RECALWAIT:
2229                 /* allow heads to settle */
2230                 timeout(fd_pseudointr, fdc, hz / 8);
2231                 fdc->state = RECALCOMPLETE;
2232                 return (0);     /* will return later */
2233
2234         case RECALCOMPLETE:
2235                 do {
2236                         /*
2237                          * See SEEKCOMPLETE for a comment on this:
2238                          */
2239                         if (fd_sense_int(fdc, &st0, &cyl) == FD_NOT_VALID)
2240                                 return (0); /* will return later */
2241                         if(fdc->fdct == FDC_NE765
2242                            && (st0 & NE7_ST0_IC) == NE7_ST0_IC_RC)
2243                                 return (0); /* hope for a real intr */
2244                 } while ((st0 & NE7_ST0_IC) == NE7_ST0_IC_RC);
2245                 if ((st0 & NE7_ST0_IC) != NE7_ST0_IC_NT || cyl != 0)
2246                 {
2247                         if(fdc->retry > 3)
2248                                 /*
2249                                  * A recalibrate from beyond cylinder 77
2250                                  * will "fail" due to the FDC limitations;
2251                                  * since people used to complain much about
2252                                  * the failure message, try not logging
2253                                  * this one if it seems to be the first
2254                                  * time in a line.
2255                                  */
2256                                 printf("fd%d: recal failed ST0 %b cyl %d\n",
2257                                        fdu, st0, NE7_ST0BITS, cyl);
2258                         if(fdc->retry < 3) fdc->retry = 3;
2259                         return (retrier(fdc));
2260                 }
2261                 fd->track = 0;
2262                 /* Seek (probably) necessary */
2263                 fdc->state = DOSEEK;
2264                 return (1);     /* will return immediately */
2265
2266         case MOTORWAIT:
2267                 if(fd->flags & FD_MOTOR_WAIT)
2268                 {
2269                         return (0); /* time's not up yet */
2270                 }
2271                 if (fdc->flags & FDC_NEEDS_RESET) {
2272                         fdc->state = RESETCTLR;
2273                         fdc->flags &= ~FDC_NEEDS_RESET;
2274                 } else
2275                         fdc->state = DOSEEK;
2276                 return (1);     /* will return immediately */
2277
2278         default:
2279                 device_printf(fdc->fdc_dev, "unexpected FD int->");
2280                 if (fd_read_status(fdc) == 0)
2281                         printf("FDC status :%x %x %x %x %x %x %x   ",
2282                                fdc->status[0],
2283                                fdc->status[1],
2284                                fdc->status[2],
2285                                fdc->status[3],
2286                                fdc->status[4],
2287                                fdc->status[5],
2288                                fdc->status[6] );
2289                 else
2290                         printf("No status available   ");
2291                 if (fd_sense_int(fdc, &st0, &cyl) != 0)
2292                 {
2293                         printf("[controller is dead now]\n");
2294                         return (0); /* will return later */
2295                 }
2296                 printf("ST0 = %x, PCN = %x\n", st0, cyl);
2297                 return (0);     /* will return later */
2298         }
2299         /* noone should ever get here */
2300 }
2301
2302 static int
2303 retrier(struct fdc_data *fdc)
2304 {
2305         struct bio *bp;
2306         struct fd_data *fd;
2307         int fdu;
2308
2309         bp = fdc->bp;
2310
2311         /* XXX shouldn't this be cached somewhere?  */
2312         fd = bp->bio_dev->si_drv1;
2313         fdu = fd->fdu;
2314         if (fd->options & FDOPT_NORETRY)
2315                 goto fail;
2316
2317         switch (fdc->retry) {
2318         case 0: case 1: case 2:
2319                 fdc->state = SEEKCOMPLETE;
2320                 break;
2321         case 3: case 4: case 5:
2322                 fdc->state = STARTRECAL;
2323                 break;
2324         case 6:
2325                 fdc->state = RESETCTLR;
2326                 break;
2327         case 7:
2328                 break;
2329         default:
2330         fail:
2331                 if ((fd->options & FDOPT_NOERRLOG) == 0) {
2332                         disk_err(bp, "hard error",
2333                             fdc->fd->skip / DEV_BSIZE, 0);
2334                         if (fdc->flags & FDC_STAT_VALID) {
2335                                 printf(
2336                                 " (ST0 %b ST1 %b ST2 %b cyl %u hd %u sec %u)\n",
2337                                        fdc->status[0], NE7_ST0BITS,
2338                                        fdc->status[1], NE7_ST1BITS,
2339                                        fdc->status[2], NE7_ST2BITS,
2340                                        fdc->status[3], fdc->status[4],
2341                                        fdc->status[5]);
2342                         }
2343                         else
2344                                 printf(" (No status)\n");
2345                 }
2346                 if ((fd->options & FDOPT_NOERROR) == 0) {
2347                         bp->bio_flags |= BIO_ERROR;
2348                         bp->bio_error = EIO;
2349                         bp->bio_resid = bp->bio_bcount - fdc->fd->skip;
2350                 } else
2351                         bp->bio_resid = 0;
2352                 fdc->bp = NULL;
2353                 fdc->fd->skip = 0;
2354                 device_unbusy(fd->dev);
2355                 biofinish(bp, fdc->fd->device_stats, 0);
2356                 fdc->state = FINDWORK;
2357                 fdc->flags |= FDC_NEEDS_RESET;
2358                 fdc->fd = (fd_p) 0;
2359                 fdc->fdu = -1;
2360                 return (1);
2361         }
2362         fdc->retry++;
2363         return (1);
2364 }
2365
2366 static void
2367 fdbiodone(struct bio *bp)
2368 {
2369         wakeup(bp);
2370 }
2371
2372 static int
2373 fdmisccmd(struct cdev *dev, u_int cmd, void *data)
2374 {
2375         fdu_t fdu;
2376         fd_p fd;
2377         struct bio *bp;
2378         struct fd_formb *finfo;
2379         struct fdc_readid *idfield;
2380         size_t fdblk;
2381         int error;
2382
2383         fd = dev->si_drv1;
2384         fdu = fd->fdu;
2385         fdblk = 128 << fd->ft->secsize;
2386         finfo = (struct fd_formb *)data;
2387         idfield = (struct fdc_readid *)data;
2388
2389         bp = malloc(sizeof(struct bio), M_TEMP, M_WAITOK | M_ZERO);
2390
2391         /*
2392          * Set up a bio request for fdstrategy().  bio_offset is faked
2393          * so that fdstrategy() will seek to the the requested
2394          * cylinder, and use the desired head.
2395          */
2396         bp->bio_cmd = cmd;
2397         if (cmd == FDBIO_FORMAT) {
2398                 bp->bio_offset =
2399                     (finfo->cyl * (fd->ft->sectrac * fd->ft->heads) +
2400                      finfo->head * fd->ft->sectrac) * fdblk;
2401                 bp->bio_bcount = sizeof(struct fd_idfield_data) *
2402                     finfo->fd_formb_nsecs;
2403         } else if (cmd == FDBIO_RDSECTID) {
2404                 bp->bio_offset =
2405                     (idfield->cyl * (fd->ft->sectrac * fd->ft->heads) +
2406                      idfield->head * fd->ft->sectrac) * fdblk;
2407                 bp->bio_bcount = sizeof(struct fdc_readid);
2408         } else
2409                 panic("wrong cmd in fdmisccmd()");
2410         bp->bio_data = data;
2411         bp->bio_dev = dev;
2412         bp->bio_done = fdbiodone;
2413         bp->bio_flags = 0;
2414
2415         /* Now run the command. */
2416         fdstrategy(bp);
2417         error = biowait(bp, "fdcmd");
2418
2419         free(bp, M_TEMP);
2420         return (error);
2421 }
2422
2423 static int
2424 fdioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
2425 {
2426         fdu_t fdu;
2427         fd_p fd;
2428         struct fdc_status *fsp;
2429         struct fdc_readid *rid;
2430         int error;
2431
2432         fd = dev->si_drv1;
2433         fdu = fd->fdu;
2434
2435 #ifdef PC98
2436         pc98_fd_check_ready(fdu);
2437 #endif  
2438
2439         /*
2440          * First, handle everything that could be done with
2441          * FD_NONBLOCK still being set.
2442          */
2443         switch (cmd) {
2444
2445         case DIOCGMEDIASIZE:
2446                 if (fd->ft == 0)
2447                         return ((fd->flags & FD_NONBLOCK) ? EAGAIN : ENXIO);
2448                 *(off_t *)addr = (128 << (fd->ft->secsize)) * fd->ft->size;
2449                 return (0);
2450
2451         case DIOCGSECTORSIZE:
2452                 if (fd->ft == 0)
2453                         return ((fd->flags & FD_NONBLOCK) ? EAGAIN : ENXIO);
2454                 *(u_int *)addr = 128 << (fd->ft->secsize);
2455                 return (0);
2456
2457         case FIONBIO:
2458                 if (*(int *)addr != 0)
2459                         fd->flags |= FD_NONBLOCK;
2460                 else {
2461                         if (fd->ft == 0) {
2462                                 /*
2463                                  * No drive type has been selected yet,
2464                                  * cannot turn FNONBLOCK off.
2465                                  */
2466                                 return (EINVAL);
2467                         }
2468                         fd->flags &= ~FD_NONBLOCK;
2469                 }
2470                 return (0);
2471
2472         case FIOASYNC:
2473                 /* keep the generic fcntl() code happy */
2474                 return (0);
2475
2476         case FD_GTYPE:                  /* get drive type */
2477                 if (fd->ft == 0)
2478                         /* no type known yet, return the native type */
2479                         *(struct fd_type *)addr = fd_native_types[fd->type];
2480                 else
2481                         *(struct fd_type *)addr = *fd->ft;
2482                 return (0);
2483
2484         case FD_STYPE:                  /* set drive type */
2485                 /*
2486                  * Allow setting drive type temporarily iff
2487                  * currently unset.  Used for fdformat so any
2488                  * user can set it, and then start formatting.
2489                  */
2490                 if (fd->ft)
2491                         return (EINVAL); /* already set */
2492                 fd->fts[0] = *(struct fd_type *)addr;
2493                 fd->ft = &fd->fts[0];
2494                 fd->flags |= FD_UA;
2495                 return (0);
2496
2497         case FD_GOPTS:                  /* get drive options */
2498                 *(int *)addr = fd->options + FDOPT_AUTOSEL;
2499                 return (0);
2500
2501         case FD_SOPTS:                  /* set drive options */
2502                 fd->options = *(int *)addr & ~FDOPT_AUTOSEL;
2503                 return (0);
2504
2505 #ifdef FDC_DEBUG
2506         case FD_DEBUG:
2507                 if ((fd_debug != 0) != (*(int *)addr != 0)) {
2508                         fd_debug = (*(int *)addr != 0);
2509                         printf("fd%d: debugging turned %s\n",
2510                             fd->fdu, fd_debug ? "on" : "off");
2511                 }
2512                 return (0);
2513 #endif
2514
2515         case FD_CLRERR:
2516                 if (priv_check(td, PRIV_DRIVER) != 0)
2517                         return (EPERM);
2518                 fd->fdc->fdc_errs = 0;
2519                 return (0);
2520
2521         case FD_GSTAT:
2522                 fsp = (struct fdc_status *)addr;
2523                 if ((fd->fdc->flags & FDC_STAT_VALID) == 0)
2524                         return (EINVAL);
2525                 memcpy(fsp->status, fd->fdc->status, 7 * sizeof(u_int));
2526                 return (0);
2527
2528         case FD_GDTYPE:
2529                 *(enum fd_drivetype *)addr = fd->type;
2530                 return (0);
2531         }
2532
2533         /*
2534          * Now handle everything else.  Make sure we have a valid
2535          * drive type.
2536          */
2537         if (fd->flags & FD_NONBLOCK)
2538                 return (EAGAIN);
2539         if (fd->ft == 0)
2540                 return (ENXIO);
2541         error = 0;
2542
2543         switch (cmd) {
2544
2545         case FD_FORM:
2546                 if ((flag & FWRITE) == 0)
2547                         return (EBADF); /* must be opened for writing */
2548                 if (((struct fd_formb *)addr)->format_version !=
2549                     FD_FORMAT_VERSION)
2550                         return (EINVAL); /* wrong version of formatting prog */
2551                 error = fdmisccmd(dev, FDBIO_FORMAT, addr);
2552                 break;
2553
2554         case FD_GTYPE:                  /* get drive type */
2555                 *(struct fd_type *)addr = *fd->ft;
2556                 break;
2557
2558         case FD_STYPE:                  /* set drive type */
2559                 /* this is considered harmful; only allow for superuser */
2560                 if (priv_check(td, PRIV_DRIVER) != 0)
2561                         return (EPERM);
2562                 *fd->ft = *(struct fd_type *)addr;
2563                 break;
2564
2565         case FD_GOPTS:                  /* get drive options */
2566                 *(int *)addr = fd->options;
2567                 break;
2568
2569         case FD_SOPTS:                  /* set drive options */
2570                 fd->options = *(int *)addr;
2571                 break;
2572
2573 #ifdef FDC_DEBUG
2574         case FD_DEBUG:
2575                 if ((fd_debug != 0) != (*(int *)addr != 0)) {
2576                         fd_debug = (*(int *)addr != 0);
2577                         printf("fd%d: debugging turned %s\n",
2578                             fd->fdu, fd_debug ? "on" : "off");
2579                 }
2580                 break;
2581 #endif
2582
2583         case FD_CLRERR:
2584                 if (priv_check(td, PRIV_DRIVER) != 0)
2585                         return (EPERM);
2586                 fd->fdc->fdc_errs = 0;
2587                 break;
2588
2589         case FD_GSTAT:
2590                 fsp = (struct fdc_status *)addr;
2591                 if ((fd->fdc->flags & FDC_STAT_VALID) == 0)
2592                         return (EINVAL);
2593                 memcpy(fsp->status, fd->fdc->status, 7 * sizeof(u_int));
2594                 break;
2595
2596         case FD_READID:
2597                 rid = (struct fdc_readid *)addr;
2598                 if (rid->cyl > MAX_CYLINDER || rid->head > MAX_HEAD)
2599                         return (EINVAL);
2600                 error = fdmisccmd(dev, FDBIO_RDSECTID, addr);
2601                 break;
2602
2603         default:
2604                 error = ENOTTY;
2605                 break;
2606         }
2607         return (error);
2608 }