]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/pc98/cbus/fdc.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.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_release_resource(dev, SYS_RES_IRQ, fdc->rid_irq,
661                                      fdc->res_irq);
662                 fdc->res_irq = NULL;
663         }
664 #ifndef PC98
665         if (fdc->res_ctl != 0) {
666                 bus_release_resource(dev, SYS_RES_IOPORT, fdc->rid_ctl,
667                                      fdc->res_ctl);
668                 fdc->res_ctl = NULL;
669         }
670 #endif
671 #ifdef PC98
672         if (fdc->res_fdsio != 0) {
673                 bus_release_resource(dev, SYS_RES_IOPORT, 3, fdc->res_fdsio);
674                 fdc->res_fdsio = NULL;
675         }
676         if (fdc->res_fdemsio != 0) {
677                 bus_release_resource(dev, SYS_RES_IOPORT, 4, fdc->res_fdemsio);
678                 fdc->res_fdemsio = NULL;
679         }
680 #endif
681         if (fdc->res_ioport != 0) {
682                 bus_release_resource(dev, SYS_RES_IOPORT, fdc->rid_ioport,
683                                      fdc->res_ioport);
684                 fdc->res_ioport = NULL;
685         }
686         if (fdc->res_drq != 0) {
687                 bus_release_resource(dev, SYS_RES_DRQ, fdc->rid_drq,
688                                      fdc->res_drq);
689                 fdc->res_drq = NULL;
690         }
691 }
692
693 /*
694  * Configuration/initialization stuff, per controller.
695  */
696
697 int
698 fdc_read_ivar(device_t dev, device_t child, int which, uintptr_t *result)
699 {
700         struct fdc_ivars *ivars = device_get_ivars(child);
701
702         switch (which) {
703         case FDC_IVAR_FDUNIT:
704                 *result = ivars->fdunit;
705                 break;
706         case FDC_IVAR_FDTYPE:
707                 *result = ivars->fdtype;
708                 break;
709         default:
710                 return (ENOENT);
711         }
712         return (0);
713 }
714
715 int
716 fdc_write_ivar(device_t dev, device_t child, int which, uintptr_t value)
717 {
718         struct fdc_ivars *ivars = device_get_ivars(child);
719
720         switch (which) {
721         case FDC_IVAR_FDUNIT:
722                 ivars->fdunit = value;
723                 break;
724         case FDC_IVAR_FDTYPE:
725                 ivars->fdtype = value;
726                 break;
727         default:
728                 return (ENOENT);
729         }
730         return (0);
731 }
732
733 int
734 fdc_initial_reset(struct fdc_data *fdc)
735 {
736 #ifdef PC98
737         /* see if it can handle a command */
738         if (fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(4, 240), 
739                    NE7_SPEC_2(2, 0), 0))
740                 return (ENXIO);
741 #else
742         /* First, reset the floppy controller. */
743         fdout_wr(fdc, 0);
744         DELAY(100);
745         fdout_wr(fdc, FDO_FRST);
746
747         /* Then, see if it can handle a command. */
748         if (fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(3, 240), 
749             NE7_SPEC_2(2, 0), 0))
750                 return (ENXIO);
751 #endif
752         return (0);
753 }
754
755 int
756 fdc_detach(device_t dev)
757 {
758         struct  fdc_data *fdc;
759         int     error;
760
761         fdc = device_get_softc(dev);
762
763         /* have our children detached first */
764         if ((error = bus_generic_detach(dev)))
765                 return (error);
766
767 #ifdef PC98
768         /* reset controller, turn motor off */
769         fdc_reset(fdc);
770 #else
771         /* reset controller, turn motor off */
772         fdout_wr(fdc, 0);
773 #endif
774
775         fdc_release_resources(fdc);
776         return (0);
777 }
778
779 /*
780  * Add a child device to the fdc controller.  It will then be probed etc.
781  */
782 device_t
783 fdc_add_child(device_t dev, const char *name, int unit)
784 {
785         struct fdc_ivars *ivar;
786         device_t child;
787
788         ivar = malloc(sizeof *ivar, M_DEVBUF /* XXX */, M_NOWAIT | M_ZERO);
789         if (ivar == NULL)
790                 return (NULL);
791         child = device_add_child(dev, name, unit);
792         if (child == NULL) {
793                 free(ivar, M_DEVBUF);
794                 return (NULL);
795         }
796         device_set_ivars(child, ivar);
797         ivar->fdunit = unit;
798         ivar->fdtype = FDT_NONE;
799         if (resource_disabled(name, unit))
800                 device_disable(child);
801         return (child);
802 }
803
804 int
805 fdc_attach(device_t dev)
806 {
807         struct  fdc_data *fdc;
808         int     error;
809
810         fdc = device_get_softc(dev);
811         fdc->fdc_dev = dev;
812         error = bus_setup_intr(dev, fdc->res_irq,
813                                INTR_TYPE_BIO | INTR_ENTROPY, NULL, fdc_intr, fdc,
814                                &fdc->fdc_intr);
815         if (error) {
816                 device_printf(dev, "cannot setup interrupt\n");
817                 return error;
818         }
819         fdc->fdcu = device_get_unit(dev);
820         fdc->flags |= FDC_NEEDS_RESET;
821
822         fdc->state = DEVIDLE;
823
824 #ifdef PC98
825         /* reset controller, turn motor off, clear fdout mirror reg */
826         fdc_reset(fdc);
827 #else
828         /* reset controller, turn motor off, clear fdout mirror reg */
829         fdout_wr(fdc, fdc->fdout = 0);
830 #endif
831         bioq_init(&fdc->head);
832
833         return (0);
834 }
835
836 int
837 fdc_hints_probe(device_t dev)
838 {
839         const char *name, *dname;
840         int i, error, dunit;
841
842         /*
843          * Probe and attach any children.  We should probably detect
844          * devices from the BIOS unless overridden.
845          */
846         name = device_get_nameunit(dev);
847         i = 0;
848         while ((resource_find_match(&i, &dname, &dunit, "at", name)) == 0) {
849                 resource_int_value(dname, dunit, "drive", &dunit);
850                 fdc_add_child(dev, dname, dunit);
851         }
852
853         if ((error = bus_generic_attach(dev)) != 0)
854                 return (error);
855         return (0);
856 }
857
858 int
859 fdc_print_child(device_t me, device_t child)
860 {
861         int retval = 0, flags;
862
863         retval += bus_print_child_header(me, child);
864         retval += printf(" on %s drive %d", device_get_nameunit(me),
865                fdc_get_fdunit(child));
866         if ((flags = device_get_flags(me)) != 0)
867                 retval += printf(" flags %#x", flags);
868         retval += printf("\n");
869         
870         return (retval);
871 }
872
873 /*
874  * Configuration/initialization, per drive.
875  */
876 static int
877 fd_probe(device_t dev)
878 {
879         int     i;
880 #ifndef PC98
881         u_int   st0, st3;
882 #endif
883         struct  fd_data *fd;
884         struct  fdc_data *fdc;
885         fdsu_t  fdsu;
886         int     flags, type;
887
888         fdsu = fdc_get_fdunit(dev);
889         fd = device_get_softc(dev);
890         fdc = device_get_softc(device_get_parent(dev));
891         flags = device_get_flags(dev);
892
893         fd->dev = dev;
894         fd->fdc = fdc;
895         fd->fdsu = fdsu;
896         fd->fdu = device_get_unit(dev);
897
898         /* Auto-probe if fdinfo is present, but always allow override. */
899         type = FD_DTYPE(flags);
900         if (type == FDT_NONE && (type = fdc_get_fdtype(dev)) != FDT_NONE) {
901                 fd->type = type;
902                 goto done;
903         } else {
904                 /* make sure fdautoselect() will be called */
905                 fd->flags = FD_UA;
906                 fd->type = type;
907         }
908
909 #ifdef PC98
910         pc98_fd_check_type(fd);
911 #else
912 /*
913  * XXX I think using __i386__ is wrong here since we actually want to probe
914  * for the machine type, not the CPU type (so non-PC arch's like the PC98 will
915  * fail the probe).
916  */
917 #ifdef __i386__
918         if (fd->type == FDT_NONE && (fd->fdu == 0 || fd->fdu == 1)) {
919                 /* Look up what the BIOS thinks we have. */
920                 if (fd->fdu == 0) {
921                         if ((fdc->flags & FDC_ISPCMCIA))
922                                 /*
923                                  * Somewhat special.  No need to force the
924                                  * user to set device flags, since the Y-E
925                                  * Data PCMCIA floppy is always a 1.44 MB
926                                  * device.
927                                  */
928                                 fd->type = FDT_144M;
929                         else
930                                 fd->type = (rtcin(RTC_FDISKETTE) & 0xf0) >> 4;
931                 } else {
932                         fd->type = rtcin(RTC_FDISKETTE) & 0x0f;
933                 }
934                 if (fd->type == FDT_288M_1)
935                         fd->type = FDT_288M;
936         }
937 #endif /* __i386__ */
938 #endif /* PC98 */
939
940         /* is there a unit? */
941         if (fd->type == FDT_NONE)
942                 return (ENXIO);
943
944 #ifndef PC98
945         /* select it */
946         set_motor(fdc, fdsu, TURNON);
947         fdc_reset(fdc);         /* XXX reset, then unreset, etc. */
948         DELAY(1000000); /* 1 sec */
949
950         if ((flags & FD_NO_PROBE) == 0) {
951                 /* If we're at track 0 first seek inwards. */
952                 if ((fd_sense_drive_status(fdc, &st3) == 0) &&
953                     (st3 & NE7_ST3_T0)) {
954                         /* Seek some steps... */
955                         if (fd_cmd(fdc, 3, NE7CMD_SEEK, fdsu, 10, 0) == 0) {
956                                 /* ...wait a moment... */
957                                 DELAY(300000);
958                                 /* make ctrlr happy: */
959                                 fd_sense_int(fdc, 0, 0);
960                         }
961                 }
962
963                 for (i = 0; i < 2; i++) {
964                         /*
965                          * we must recalibrate twice, just in case the
966                          * heads have been beyond cylinder 76, since
967                          * most FDCs still barf when attempting to
968                          * recalibrate more than 77 steps
969                          */
970                         /* go back to 0: */
971                         if (fd_cmd(fdc, 2, NE7CMD_RECAL, fdsu, 0) == 0) {
972                                 /* a second being enough for full stroke seek*/
973                                 DELAY(i == 0 ? 1000000 : 300000);
974
975                                 /* anything responding? */
976                                 if (fd_sense_int(fdc, &st0, 0) == 0 &&
977                                     (st0 & NE7_ST0_EC) == 0)
978                                         break; /* already probed succesfully */
979                         }
980                 }
981         }
982
983         set_motor(fdc, fdsu, TURNOFF);
984
985         if ((flags & FD_NO_PROBE) == 0 &&
986             (st0 & NE7_ST0_EC) != 0) /* no track 0 -> no drive present */
987                 return (ENXIO);
988 #endif /* PC98 */
989
990 done:
991 #ifndef PC98
992         /* This doesn't work before the first reset. */
993         if ((fdc->flags & FDC_HAS_FIFO) == 0 &&
994             fdc->fdct == FDC_ENHANCED &&
995             (device_get_flags(fdc->fdc_dev) & FDC_NO_FIFO) == 0 &&
996             enable_fifo(fdc) == 0) {
997                 device_printf(device_get_parent(dev),
998                     "FIFO enabled, %d bytes threshold\n", fifo_threshold);
999         }
1000 #endif /* PC98 */
1001
1002 #ifdef PC98
1003         switch (fd->type) {
1004         case FDT_144M:
1005                 device_set_desc(dev, "1.44M FDD");
1006                 break;
1007         case FDT_12M:
1008                 device_set_desc(dev, "1M/640K FDD");
1009                 break;
1010         default:
1011                 return (ENXIO);
1012         }
1013 #else
1014         switch (fd->type) {
1015         case FDT_12M:
1016                 device_set_desc(dev, "1200-KB 5.25\" drive");
1017                 break;
1018         case FDT_144M:
1019                 device_set_desc(dev, "1440-KB 3.5\" drive");
1020                 break;
1021         case FDT_288M:
1022                 device_set_desc(dev, "2880-KB 3.5\" drive (in 1440-KB mode)");
1023                 break;
1024         case FDT_360K:
1025                 device_set_desc(dev, "360-KB 5.25\" drive");
1026                 break;
1027         case FDT_720K:
1028                 device_set_desc(dev, "720-KB 3.5\" drive");
1029                 break;
1030         default:
1031                 return (ENXIO);
1032         }
1033 #endif
1034         fd->track = FD_NO_TRACK;
1035         fd->fdc = fdc;
1036         fd->fdsu = fdsu;
1037         fd->options = 0;
1038 #ifdef PC98
1039         fd->pc98_trans = 0;
1040 #endif
1041         callout_handle_init(&fd->toffhandle);
1042         callout_handle_init(&fd->tohandle);
1043
1044         /* initialize densities for subdevices */
1045 #ifdef PC98
1046         for (i = 0; i < NUMDENS; i++)
1047                 memcpy(fd->fts + i, fd_searchlist_144m + i,
1048                        sizeof(struct fd_type));
1049 #else
1050         for (i = 0; i < NUMDENS; i++)
1051                 memcpy(fd->fts + i, fd_native_types + fd->type,
1052                        sizeof(struct fd_type));
1053 #endif
1054         return (0);
1055 }
1056
1057 static int
1058 fd_attach(device_t dev)
1059 {
1060         struct  fd_data *fd;
1061
1062         fd = device_get_softc(dev);
1063         fd->masterdev = make_dev(&fd_cdevsw, fd->fdu,
1064                                  UID_ROOT, GID_OPERATOR, 0640, "fd%d", fd->fdu);
1065         fd->masterdev->si_drv1 = fd;
1066         fd->device_stats = devstat_new_entry(device_get_name(dev), 
1067                           device_get_unit(dev), 0, DEVSTAT_NO_ORDERED_TAGS,
1068                           DEVSTAT_TYPE_FLOPPY | DEVSTAT_TYPE_IF_OTHER,
1069                           DEVSTAT_PRIORITY_FD);
1070         return (0);
1071 }
1072
1073 static int
1074 fd_detach(device_t dev)
1075 {
1076         struct  fd_data *fd;
1077
1078         fd = device_get_softc(dev);
1079         untimeout(fd_turnoff, fd, fd->toffhandle);
1080         devstat_remove_entry(fd->device_stats);
1081         destroy_dev(fd->masterdev);
1082
1083         return (0);
1084 }
1085
1086 static device_method_t fd_methods[] = {
1087         /* Device interface */
1088         DEVMETHOD(device_probe,         fd_probe),
1089         DEVMETHOD(device_attach,        fd_attach),
1090         DEVMETHOD(device_detach,        fd_detach),
1091         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
1092         DEVMETHOD(device_suspend,       bus_generic_suspend), /* XXX */
1093         DEVMETHOD(device_resume,        bus_generic_resume), /* XXX */
1094
1095         { 0, 0 }
1096 };
1097
1098 static driver_t fd_driver = {
1099         "fd",
1100         fd_methods,
1101         sizeof(struct fd_data)
1102 };
1103
1104 DRIVER_MODULE(fd, fdc, fd_driver, fd_devclass, 0, 0);
1105
1106 /*
1107  * More auxiliary functions.
1108  */
1109 /*
1110  * Motor control stuff.
1111  * Remember to not deselect the drive we're working on.
1112  */
1113 static void
1114 set_motor(struct fdc_data *fdc, int fdsu, int turnon)
1115 {
1116 #ifdef PC98
1117         bus_space_write_1(fdc->sc_fdsiot, fdc->sc_fdsioh, 0,
1118                           (pc98_trans != 1 ? FDP_FDDEXC : 0) | FDP_PORTEXC);
1119         DELAY(10);
1120         fdctl_wr(fdc, FDC_DMAE | FDC_MTON);
1121 #else
1122         int fdout;
1123
1124         fdout = fdc->fdout;
1125         if (turnon) {
1126                 fdout &= ~FDO_FDSEL;
1127                 fdout |= (FDO_MOEN0 << fdsu) | FDO_FDMAEN | FDO_FRST | fdsu;
1128         } else
1129                 fdout &= ~(FDO_MOEN0 << fdsu);
1130         fdc->fdout = fdout;
1131         fdout_wr(fdc, fdout);
1132         TRACE1("[0x%x->FDOUT]", fdout);
1133 #endif
1134 }
1135
1136 static void
1137 fd_turnoff(void *xfd)
1138 {
1139         int     s;
1140         fd_p fd = xfd;
1141
1142         TRACE1("[fd%d: turnoff]", fd->fdu);
1143
1144         s = splbio();
1145         /*
1146          * Don't turn off the motor yet if the drive is active.
1147          *
1148          * If we got here, this could only mean we missed an interrupt.
1149          * This can e. g. happen on the Y-E Date PCMCIA floppy controller
1150          * after a controller reset.  Just schedule a pseudo-interrupt
1151          * so the state machine gets re-entered.
1152          */
1153         if (fd->fdc->state != DEVIDLE && fd->fdc->fdu == fd->fdu) {
1154                 fdc_intr(fd->fdc);
1155                 splx(s);
1156                 return;
1157         }
1158
1159         fd->flags &= ~FD_MOTOR;
1160         set_motor(fd->fdc, fd->fdsu, TURNOFF);
1161         splx(s);
1162 }
1163
1164 static void
1165 fd_motor_on(void *xfd)
1166 {
1167         int     s;
1168         fd_p fd = xfd;
1169
1170         s = splbio();
1171         fd->flags &= ~FD_MOTOR_WAIT;
1172         if((fd->fdc->fd == fd) && (fd->fdc->state == MOTORWAIT))
1173         {
1174                 fdc_intr(fd->fdc);
1175         }
1176         splx(s);
1177 }
1178
1179 static void
1180 fd_turnon(fd_p fd)
1181 {
1182         if(!(fd->flags & FD_MOTOR))
1183         {
1184                 fd->flags |= (FD_MOTOR + FD_MOTOR_WAIT);
1185                 set_motor(fd->fdc, fd->fdsu, TURNON);
1186                 timeout(fd_motor_on, fd, hz); /* in 1 sec its ok */
1187         }
1188 }
1189
1190 static void
1191 fdc_reset(fdc_p fdc)
1192 {
1193         /* Try a reset, keep motor on */
1194 #ifdef PC98
1195         set_density(fdc);
1196         if (pc98_machine_type & M_EPSON_PC98)
1197                 fdctl_wr(fdc, FDC_RST | FDC_RDY | FDC_DD | FDC_MTON);
1198         else
1199                 fdctl_wr(fdc, FDC_RST | FDC_RDY | FDC_DMAE | FDC_MTON);
1200         DELAY(200);
1201         fdctl_wr(fdc, FDC_DMAE | FDC_MTON);
1202         DELAY(10);
1203 #else
1204         fdout_wr(fdc, fdc->fdout & ~(FDO_FRST|FDO_FDMAEN));
1205         TRACE1("[0x%x->FDOUT]", fdc->fdout & ~(FDO_FRST|FDO_FDMAEN));
1206         DELAY(100);
1207         /* enable FDC, but defer interrupts a moment */
1208         fdout_wr(fdc, fdc->fdout & ~FDO_FDMAEN);
1209         TRACE1("[0x%x->FDOUT]", fdc->fdout & ~FDO_FDMAEN);
1210         DELAY(100);
1211         fdout_wr(fdc, fdc->fdout);
1212         TRACE1("[0x%x->FDOUT]", fdc->fdout);
1213 #endif
1214
1215         /* XXX after a reset, silently believe the FDC will accept commands */
1216 #ifdef PC98
1217         (void)fd_cmd(fdc, 3, NE7CMD_SPECIFY,
1218                      NE7_SPEC_1(4, 240), NE7_SPEC_2(2, 0),
1219                      0);
1220 #else
1221         (void)fd_cmd(fdc, 3, NE7CMD_SPECIFY,
1222                      NE7_SPEC_1(3, 240), NE7_SPEC_2(2, 0),
1223                      0);
1224 #endif
1225         if (fdc->flags & FDC_HAS_FIFO)
1226                 (void) enable_fifo(fdc);
1227 }
1228
1229 /*
1230  * FDC IO functions, take care of the main status register, timeout
1231  * in case the desired status bits are never set.
1232  *
1233  * These PIO loops initially start out with short delays between
1234  * each iteration in the expectation that the required condition
1235  * is usually met quickly, so it can be handled immediately.  After
1236  * about 1 ms, stepping is increased to achieve a better timing
1237  * accuracy in the calls to DELAY().
1238  */
1239 static int
1240 fd_in(struct fdc_data *fdc, int *ptr)
1241 {
1242         int i, j, step;
1243
1244         for (j = 0, step = 1;
1245             (i = fdsts_rd(fdc) & (NE7_DIO|NE7_RQM)) != (NE7_DIO|NE7_RQM) &&
1246             j < FDSTS_TIMEOUT;
1247             j += step) {
1248                 if (i == NE7_RQM)
1249                         return (fdc_err(fdc, "ready for output in input\n"));
1250                 if (j == 1000)
1251                         step = 1000;
1252                 DELAY(step);
1253         }
1254         if (j >= FDSTS_TIMEOUT)
1255                 return (fdc_err(fdc, bootverbose? "input ready timeout\n": 0));
1256 #ifdef  FDC_DEBUG
1257         i = fddata_rd(fdc);
1258         TRACE1("[FDDATA->0x%x]", (unsigned char)i);
1259         *ptr = i;
1260         return (0);
1261 #else   /* !FDC_DEBUG */
1262         i = fddata_rd(fdc);
1263         if (ptr)
1264                 *ptr = i;
1265         return (0);
1266 #endif  /* FDC_DEBUG */
1267 }
1268
1269 static int
1270 out_fdc(struct fdc_data *fdc, int x)
1271 {
1272         int i, j, step;
1273
1274         for (j = 0, step = 1;
1275             (i = fdsts_rd(fdc) & (NE7_DIO|NE7_RQM)) != NE7_RQM &&
1276             j < FDSTS_TIMEOUT;
1277             j += step) {
1278                 if (i == (NE7_DIO|NE7_RQM))
1279                         return (fdc_err(fdc, "ready for input in output\n"));
1280                 if (j == 1000)
1281                         step = 1000;
1282                 DELAY(step);
1283         }
1284         if (j >= FDSTS_TIMEOUT)
1285                 return (fdc_err(fdc, bootverbose? "output ready timeout\n": 0));
1286
1287         /* Send the command and return */
1288         fddata_wr(fdc, x);
1289         TRACE1("[0x%x->FDDATA]", x);
1290         return (0);
1291 }
1292
1293 /*
1294  * Block device driver interface functions (interspersed with even more
1295  * auxiliary functions).
1296  */
1297 static int
1298 fdopen(struct cdev *dev, int flags, int mode, struct thread *td)
1299 {
1300         fd_p    fd;
1301         fdc_p   fdc;
1302 #ifdef PC98
1303         fdu_t   fdu;
1304 #endif
1305         int rv, unitattn, dflags;
1306
1307         fd = dev->si_drv1;
1308         if (fd == NULL)
1309                 return (ENXIO);
1310         fdc = fd->fdc;
1311         if ((fdc == NULL) || (fd->type == FDT_NONE))
1312                 return (ENXIO);
1313 #ifdef PC98
1314         fdu = fd->fdu;
1315 #endif
1316         dflags = device_get_flags(fd->dev);
1317         /*
1318          * This is a bit bogus.  It's still possible that e. g. a
1319          * descriptor gets inherited to a child, but then it's at
1320          * least for the same subdevice.  By checking FD_OPEN here, we
1321          * can ensure that a device isn't attempted to be opened with
1322          * different densities at the same time where the second open
1323          * could clobber the settings from the first one.
1324          */
1325         if (fd->flags & FD_OPEN)
1326                 return (EBUSY);
1327
1328 #ifdef PC98
1329         if (pc98_fd_check_ready(fdu) == -1)
1330                 return(EIO);
1331 #endif
1332
1333         if (flags & FNONBLOCK) {
1334                 /*
1335                  * Unfortunately, physio(9) discards its ioflag
1336                  * argument, thus preventing us from seeing the
1337                  * O_NONBLOCK bit.  So we need to keep track
1338                  * ourselves.
1339                  */
1340                 fd->flags |= FD_NONBLOCK;
1341                 fd->ft = 0;
1342         } else {
1343                 /*
1344                  * Figure out a unit attention condition.
1345                  *
1346                  * If UA has been forced, proceed.
1347                  *
1348                  * If the drive has no changeline support,
1349                  * or if the drive parameters have been lost
1350                  * due to previous non-blocking access,
1351                  * assume a forced UA condition.
1352                  *
1353                  * If motor is off, turn it on for a moment
1354                  * and select our drive, in order to read the
1355                  * UA hardware signal.
1356                  *
1357                  * If motor is on, and our drive is currently
1358                  * selected, just read the hardware bit.
1359                  *
1360                  * If motor is on, but active for another
1361                  * drive on that controller, we are lost.  We
1362                  * cannot risk to deselect the other drive, so
1363                  * we just assume a forced UA condition to be
1364                  * on the safe side.
1365                  */
1366                 unitattn = 0;
1367                 if ((dflags & FD_NO_CHLINE) != 0 ||
1368                     (fd->flags & FD_UA) != 0 ||
1369                     fd->ft == 0) {
1370                         unitattn = 1;
1371                         fd->flags &= ~FD_UA;
1372 #ifndef PC98
1373                 } else if (fdc->fdout & (FDO_MOEN0 | FDO_MOEN1 |
1374                                          FDO_MOEN2 | FDO_MOEN3)) {
1375                         if ((fdc->fdout & FDO_FDSEL) == fd->fdsu)
1376                                 unitattn = fdin_rd(fdc) & FDI_DCHG;
1377                         else
1378                                 unitattn = 1;
1379                 } else {
1380                         set_motor(fdc, fd->fdsu, TURNON);
1381                         unitattn = fdin_rd(fdc) & FDI_DCHG;
1382                         set_motor(fdc, fd->fdsu, TURNOFF);
1383 #endif /* PC98 */
1384                 }
1385                 if (unitattn && (rv = fdautoselect(dev)) != 0)
1386                         return (rv);
1387         }
1388         fd->flags |= FD_OPEN;
1389
1390         if ((fdc->flags & FDC_NODMA) == 0) {
1391                 if (fdc->dmacnt++ == 0) {
1392                         isa_dma_acquire(fdc->dmachan);
1393                         isa_dmainit(fdc->dmachan, MAX_SEC_SIZE);
1394                 }
1395         }
1396
1397         /*
1398          * Clearing the DMA overrun counter at open time is a bit messy.
1399          * Since we're only managing one counter per controller, opening
1400          * the second drive could mess it up.  Anyway, if the DMA overrun
1401          * condition is really persistent, it will eventually time out
1402          * still.  OTOH, clearing it here will ensure we'll at least start
1403          * trying again after a previous (maybe even long ago) failure.
1404          * Also, this is merely a stop-gap measure only that should not
1405          * happen during normal operation, so we can tolerate it to be a
1406          * bit sloppy about this.
1407          */
1408         fdc->dma_overruns = 0;
1409
1410         return 0;
1411 }
1412
1413 static int
1414 fdclose(struct cdev *dev, int flags, int mode, struct thread *td)
1415 {
1416         struct fd_data *fd;
1417         fdc_p   fdc;
1418
1419         fd = dev->si_drv1;
1420         fdc = fd->fdc;
1421         fd->flags &= ~(FD_OPEN | FD_NONBLOCK);
1422         fd->options &= ~(FDOPT_NORETRY | FDOPT_NOERRLOG | FDOPT_NOERROR);
1423
1424         if ((fdc->flags & FDC_NODMA) == 0)
1425                 if (--fdc->dmacnt == 0)
1426                         isa_dma_release(fdc->dmachan);
1427
1428         return (0);
1429 }
1430
1431 static void
1432 fdstrategy(struct bio *bp)
1433 {
1434         long blknum, nblocks;
1435         int     s;
1436         fdu_t   fdu;
1437         fdc_p   fdc;
1438         fd_p    fd;
1439         size_t  fdblk;
1440
1441         fd = bp->bio_dev->si_drv1;
1442         fdu = fd->fdu;
1443         fdc = fd->fdc;
1444         bp->bio_resid = bp->bio_bcount;
1445         if (fd->type == FDT_NONE || fd->ft == 0) {
1446                 if (fd->type != FDT_NONE && (fd->flags & FD_NONBLOCK))
1447                         bp->bio_error = EAGAIN;
1448                 else
1449                         bp->bio_error = ENXIO;
1450                 bp->bio_flags |= BIO_ERROR;
1451                 goto bad;
1452         }
1453         fdblk = 128 << (fd->ft->secsize);
1454         if (bp->bio_cmd != FDBIO_FORMAT && bp->bio_cmd != FDBIO_RDSECTID) {
1455                 if (fd->flags & FD_NONBLOCK) {
1456                         bp->bio_error = EAGAIN;
1457                         bp->bio_flags |= BIO_ERROR;
1458                         goto bad;
1459                 }
1460                 if (bp->bio_offset < 0) {
1461                         printf(
1462                 "fd%d: fdstrat: bad request offset = %ju, bcount = %ld\n",
1463                                fdu, (intmax_t)bp->bio_offset, bp->bio_bcount);
1464                         bp->bio_error = EINVAL;
1465                         bp->bio_flags |= BIO_ERROR;
1466                         goto bad;
1467                 }
1468                 if ((bp->bio_bcount % fdblk) != 0) {
1469                         bp->bio_error = EINVAL;
1470                         bp->bio_flags |= BIO_ERROR;
1471                         goto bad;
1472                 }
1473         }
1474
1475         /*
1476          * Set up block calculations.
1477          */
1478 #ifndef PC98
1479         if (bp->bio_offset >= ((off_t)128 << fd->ft->secsize) * fd->ft->size) {
1480                 bp->bio_error = EINVAL;
1481                 bp->bio_flags |= BIO_ERROR;
1482                 goto bad;
1483         }
1484 #endif
1485         blknum = bp->bio_offset / fdblk;
1486         nblocks = fd->ft->size;
1487         if (blknum + bp->bio_bcount / fdblk > nblocks) {
1488                 if (blknum >= nblocks) {
1489                         if (bp->bio_cmd != BIO_READ) {
1490                                 bp->bio_error = ENOSPC;
1491                                 bp->bio_flags |= BIO_ERROR;
1492                         }
1493                         goto bad;       /* not always bad, but EOF */
1494                 }
1495                 bp->bio_bcount = (nblocks - blknum) * fdblk;
1496         }
1497         bp->bio_pblkno = blknum;
1498         s = splbio();
1499         bioq_disksort(&fdc->head, bp);
1500         untimeout(fd_turnoff, fd, fd->toffhandle); /* a good idea */
1501         devstat_start_transaction_bio(fd->device_stats, bp);
1502         device_busy(fd->dev);
1503         fdstart(fdc);
1504         splx(s);
1505         return;
1506
1507 bad:
1508         biodone(bp);
1509 }
1510
1511 /*
1512  * fdstart
1513  *
1514  * We have just queued something.  If the controller is not busy
1515  * then simulate the case where it has just finished a command
1516  * So that it (the interrupt routine) looks on the queue for more
1517  * work to do and picks up what we just added.
1518  *
1519  * If the controller is already busy, we need do nothing, as it
1520  * will pick up our work when the present work completes.
1521  */
1522 static void
1523 fdstart(struct fdc_data *fdc)
1524 {
1525         int s;
1526
1527         s = splbio();
1528         if(fdc->state == DEVIDLE)
1529         {
1530                 fdc_intr(fdc);
1531         }
1532         splx(s);
1533 }
1534
1535 static void
1536 fd_iotimeout(void *xfdc)
1537 {
1538         fdc_p fdc;
1539         int s;
1540
1541         fdc = xfdc;
1542         TRACE1("fd%d[fd_iotimeout()]", fdc->fdu);
1543
1544         /*
1545          * Due to IBM's brain-dead design, the FDC has a faked ready
1546          * signal, hardwired to ready == true. Thus, any command
1547          * issued if there's no diskette in the drive will _never_
1548          * complete, and must be aborted by resetting the FDC.
1549          * Many thanks, Big Blue!
1550          * The FDC must not be reset directly, since that would
1551          * interfere with the state machine.  Instead, pretend that
1552          * the command completed but was invalid.  The state machine
1553          * will reset the FDC and retry once.
1554          */
1555         s = splbio();
1556         fdc->status[0] = NE7_ST0_IC_IV;
1557         fdc->flags &= ~FDC_STAT_VALID;
1558         fdc->state = IOTIMEDOUT;
1559         fdc_intr(fdc);
1560         splx(s);
1561 }
1562
1563 /* Just ensure it has the right spl. */
1564 static void
1565 fd_pseudointr(void *xfdc)
1566 {
1567         int     s;
1568
1569         s = splbio();
1570         fdc_intr(xfdc);
1571         splx(s);
1572 }
1573
1574 /*
1575  * fdc_intr
1576  *
1577  * Keep calling the state machine until it returns a 0.
1578  * Always called at splbio.
1579  */
1580 static void
1581 fdc_intr(void *xfdc)
1582 {
1583         fdc_p fdc = xfdc;
1584         while(fdstate(fdc))
1585                 ;
1586 }
1587
1588 /*
1589  * Magic pseudo-DMA initialization for YE FDC. Sets count and
1590  * direction.
1591  */
1592 #define SET_BCDR(fdc,wr,cnt,port) \
1593         bus_space_write_1(fdc->portt, fdc->porth, fdc->port_off + port,  \
1594             ((cnt)-1) & 0xff);                                           \
1595         bus_space_write_1(fdc->portt, fdc->porth, fdc->port_off + port + 1, \
1596             ((wr ? 0x80 : 0) | ((((cnt)-1) >> 8) & 0x7f)));
1597
1598 /*
1599  * fdcpio(): perform programmed IO read/write for YE PCMCIA floppy.
1600  */
1601 static int
1602 fdcpio(fdc_p fdc, long flags, caddr_t addr, u_int count)
1603 {
1604         u_char *cptr = (u_char *)addr;
1605
1606         if (flags == BIO_READ) {
1607                 if (fdc->state != PIOREAD) {
1608                         fdc->state = PIOREAD;
1609                         return(0);
1610                 }
1611                 SET_BCDR(fdc, 0, count, 0);
1612                 bus_space_read_multi_1(fdc->portt, fdc->porth, fdc->port_off +
1613                     FDC_YE_DATAPORT, cptr, count);
1614         } else {
1615                 bus_space_write_multi_1(fdc->portt, fdc->porth, fdc->port_off +
1616                     FDC_YE_DATAPORT, cptr, count);
1617                 SET_BCDR(fdc, 0, count, 0);
1618         }
1619         return(1);
1620 }
1621
1622 /*
1623  * Try figuring out the density of the media present in our device.
1624  */
1625 static int
1626 fdautoselect(struct cdev *dev)
1627 {
1628         fd_p fd;
1629         struct fd_type *fdtp;
1630         struct fdc_readid id;
1631         int i, n, oopts, rv;
1632
1633         fd = dev->si_drv1;
1634
1635         switch (fd->type) {
1636         default:
1637                 return (ENXIO);
1638
1639 #ifndef PC98
1640         case FDT_360K:
1641         case FDT_720K:
1642                 /* no autoselection on those drives */
1643                 fd->ft = fd_native_types + fd->type;
1644                 return (0);
1645 #endif
1646
1647         case FDT_12M:
1648                 fdtp = fd_searchlist_12m;
1649                 n = sizeof fd_searchlist_12m / sizeof(struct fd_type);
1650                 break;
1651
1652         case FDT_144M:
1653                 fdtp = fd_searchlist_144m;
1654                 n = sizeof fd_searchlist_144m / sizeof(struct fd_type);
1655                 break;
1656
1657 #ifndef PC98
1658         case FDT_288M:
1659                 fdtp = fd_searchlist_288m;
1660                 n = sizeof fd_searchlist_288m / sizeof(struct fd_type);
1661                 break;
1662 #endif
1663         }
1664
1665         /*
1666          * Try reading sector ID fields, first at cylinder 0, head 0,
1667          * then at cylinder 2, head N.  We don't probe cylinder 1,
1668          * since for 5.25in DD media in a HD drive, there are no data
1669          * to read (2 step pulses per media cylinder required).  For
1670          * two-sided media, the second probe always goes to head 1, so
1671          * we can tell them apart from single-sided media.  As a
1672          * side-effect this means that single-sided media should be
1673          * mentioned in the search list after two-sided media of an
1674          * otherwise identical density.  Media with a different number
1675          * of sectors per track but otherwise identical parameters
1676          * cannot be distinguished at all.
1677          *
1678          * If we successfully read an ID field on both cylinders where
1679          * the recorded values match our expectation, we are done.
1680          * Otherwise, we try the next density entry from the table.
1681          *
1682          * Stepping to cylinder 2 has the side-effect of clearing the
1683          * unit attention bit.
1684          */
1685         oopts = fd->options;
1686         fd->options |= FDOPT_NOERRLOG | FDOPT_NORETRY;
1687         for (i = 0; i < n; i++, fdtp++) {
1688                 fd->ft = fdtp;
1689
1690                 id.cyl = id.head = 0;
1691                 rv = fdmisccmd(dev, FDBIO_RDSECTID, &id);
1692                 if (rv != 0)
1693                         continue;
1694                 if (id.cyl != 0 || id.head != 0 ||
1695                     id.secshift != fdtp->secsize)
1696                         continue;
1697                 id.cyl = 2;
1698                 id.head = fd->ft->heads - 1;
1699                 rv = fdmisccmd(dev, FDBIO_RDSECTID, &id);
1700                 if (id.cyl != 2 || id.head != fdtp->heads - 1 ||
1701                     id.secshift != fdtp->secsize)
1702                         continue;
1703                 if (rv == 0)
1704                         break;
1705         }
1706
1707         fd->options = oopts;
1708         if (i == n) {
1709                 if (bootverbose)
1710                         device_printf(fd->dev, "autoselection failed\n");
1711                 fd->ft = 0;
1712                 return (EIO);
1713         } else {
1714                 if (bootverbose)
1715                         device_printf(fd->dev, "autoselected %d KB medium\n",
1716 #ifdef PC98
1717                                       (128 << (fd->ft->secsize)) *
1718                                       fd->ft->size / 1024);
1719 #else
1720                                       fd->ft->size / 2);
1721 #endif
1722                 return (0);
1723         }
1724 }
1725
1726
1727 /*
1728  * The controller state machine.
1729  *
1730  * If it returns a non zero value, it should be called again immediately.
1731  */
1732 static int
1733 fdstate(fdc_p fdc)
1734 {
1735         struct fdc_readid *idp;
1736         int read, format, rdsectid, cylinder, head, i, sec = 0, sectrac;
1737         int st0, cyl, st3, idf, ne7cmd, mfm, steptrac;
1738         unsigned long blknum;
1739         fdu_t fdu = fdc->fdu;
1740         fd_p fd;
1741         register struct bio *bp;
1742         struct fd_formb *finfo = NULL;
1743         size_t fdblk;
1744
1745         bp = fdc->bp;
1746         if (bp == NULL) {
1747                 bp = bioq_takefirst(&fdc->head);
1748                 if (bp != NULL)
1749                         fdc->bp = bp;
1750         }
1751         if (bp == NULL) {
1752                 /*
1753                  * Nothing left for this controller to do,
1754                  * force into the IDLE state.
1755                  */
1756                 fdc->state = DEVIDLE;
1757                 if (fdc->fd) {
1758                         device_printf(fdc->fdc_dev,
1759                             "unexpected valid fd pointer\n");
1760                         fdc->fd = (fd_p) 0;
1761                         fdc->fdu = -1;
1762                 }
1763                 TRACE1("[fdc%d IDLE]", fdc->fdcu);
1764                 return (0);
1765         }
1766         fd = bp->bio_dev->si_drv1;
1767         fdu = fd->fdu;
1768         fdblk = 128 << fd->ft->secsize;
1769         if (fdc->fd && (fd != fdc->fd))
1770                 device_printf(fd->dev, "confused fd pointers\n");
1771         read = bp->bio_cmd == BIO_READ;
1772         mfm = (fd->ft->flags & FL_MFM)? NE7CMD_MFM: 0;
1773         steptrac = (fd->ft->flags & FL_2STEP)? 2: 1;
1774         if (read)
1775                 idf = ISADMA_READ;
1776         else
1777                 idf = ISADMA_WRITE;
1778         format = bp->bio_cmd == FDBIO_FORMAT;
1779         rdsectid = bp->bio_cmd == FDBIO_RDSECTID;
1780         if (format)
1781                 finfo = (struct fd_formb *)bp->bio_data;
1782         TRACE1("fd%d", fdu);
1783         TRACE1("[%s]", fdstates[fdc->state]);
1784         TRACE1("(0x%x)", fd->flags);
1785         untimeout(fd_turnoff, fd, fd->toffhandle);
1786         fd->toffhandle = timeout(fd_turnoff, fd, 4 * hz);
1787         switch (fdc->state)
1788         {
1789         case DEVIDLE:
1790         case FINDWORK:  /* we have found new work */
1791                 fdc->retry = 0;
1792                 fd->skip = 0;
1793                 fdc->fd = fd;
1794                 fdc->fdu = fdu;
1795 #ifdef PC98
1796                 pc98_trans = fd->ft->trans;
1797                 if (pc98_trans_prev != pc98_trans) {
1798                         int i;
1799                         set_density(fdc);
1800                         for (i = 0; i < 10; i++) {
1801                                 outb(0x5f, 0);
1802                                 outb(0x5f, 0);
1803                         }
1804                         pc98_trans_prev = pc98_trans;
1805                 }
1806                 if (pc98_trans != fd->pc98_trans) {
1807                         if (fd->type == FDT_144M) {
1808                                 bus_space_write_1(fdc->sc_fdemsiot,
1809                                                   fdc->sc_fdemsioh,
1810                                                   0,
1811                                                   (fdu << 5) | 0x10 |
1812                                                   (pc98_trans >> 1));
1813                                 outb(0x5f, 0);
1814                                 outb(0x5f, 0);
1815                         }
1816                         fd->pc98_trans = pc98_trans;
1817                 }
1818 #else
1819                 fdc->fdctl_wr(fdc, fd->ft->trans);
1820 #endif
1821                 TRACE1("[0x%x->FDCTL]", fd->ft->trans);
1822                 /*
1823                  * If the next drive has a motor startup pending, then
1824                  * it will start up in its own good time.
1825                  */
1826                 if(fd->flags & FD_MOTOR_WAIT) {
1827                         fdc->state = MOTORWAIT;
1828                         return (0); /* will return later */
1829                 }
1830                 /*
1831                  * Maybe if it's not starting, it SHOULD be starting.
1832                  */
1833                 if (!(fd->flags & FD_MOTOR))
1834                 {
1835                         fdc->state = MOTORWAIT;
1836                         fd_turnon(fd);
1837                         return (0); /* will return later */
1838                 }
1839                 else    /* at least make sure we are selected */
1840                 {
1841                         set_motor(fdc, fd->fdsu, TURNON);
1842                 }
1843                 if (fdc->flags & FDC_NEEDS_RESET) {
1844                         fdc->state = RESETCTLR;
1845                         fdc->flags &= ~FDC_NEEDS_RESET;
1846                 } else
1847                         fdc->state = DOSEEK;
1848                 return (1);     /* will return immediately */
1849
1850         case DOSEEK:
1851                 blknum = bp->bio_pblkno + fd->skip / fdblk;
1852                 cylinder = blknum / (fd->ft->sectrac * fd->ft->heads);
1853                 if (cylinder == fd->track)
1854                 {
1855                         fdc->state = SEEKCOMPLETE;
1856                         return (1); /* will return immediately */
1857                 }
1858 #ifdef PC98
1859                 pc98_fd_check_ready(fdu);
1860 #endif
1861                 if (fd_cmd(fdc, 3, NE7CMD_SEEK,
1862                            fd->fdsu, cylinder * steptrac, 0))
1863                 {
1864                         /*
1865                          * Seek command not accepted, looks like
1866                          * the FDC went off to the Saints...
1867                          */
1868                         fdc->retry = 6; /* try a reset */
1869                         return(retrier(fdc));
1870                 }
1871                 fd->track = FD_NO_TRACK;
1872                 fdc->state = SEEKWAIT;
1873                 return(0);      /* will return later */
1874
1875         case SEEKWAIT:
1876                 /* allow heads to settle */
1877                 timeout(fd_pseudointr, fdc, hz / 16);
1878                 fdc->state = SEEKCOMPLETE;
1879                 return(0);      /* will return later */
1880
1881         case SEEKCOMPLETE : /* seek done, start DMA */
1882                 blknum = bp->bio_pblkno + fd->skip / fdblk;
1883                 cylinder = blknum / (fd->ft->sectrac * fd->ft->heads);
1884
1885                 /* Make sure seek really happened. */
1886                 if(fd->track == FD_NO_TRACK) {
1887                         int descyl = cylinder * steptrac;
1888                         do {
1889                                 /*
1890                                  * This might be a "ready changed" interrupt,
1891                                  * which cannot really happen since the
1892                                  * RDY pin is hardwired to + 5 volts.  This
1893                                  * generally indicates a "bouncing" intr
1894                                  * line, so do one of the following:
1895                                  *
1896                                  * When running on an enhanced FDC that is
1897                                  * known to not go stuck after responding
1898                                  * with INVALID, fetch all interrupt states
1899                                  * until seeing either an INVALID or a
1900                                  * real interrupt condition.
1901                                  *
1902                                  * When running on a dumb old NE765, give
1903                                  * up immediately.  The controller will
1904                                  * provide up to four dummy RC interrupt
1905                                  * conditions right after reset (for the
1906                                  * corresponding four drives), so this is
1907                                  * our only chance to get notice that it
1908                                  * was not the FDC that caused the interrupt.
1909                                  */
1910                                 if (fd_sense_int(fdc, &st0, &cyl)
1911                                     == FD_NOT_VALID)
1912                                         return (0); /* will return later */
1913                                 if(fdc->fdct == FDC_NE765
1914                                    && (st0 & NE7_ST0_IC) == NE7_ST0_IC_RC)
1915                                         return (0); /* hope for a real intr */
1916                         } while ((st0 & NE7_ST0_IC) == NE7_ST0_IC_RC);
1917
1918                         if (0 == descyl) {
1919                                 int failed = 0;
1920                                 /*
1921                                  * seek to cyl 0 requested; make sure we are
1922                                  * really there
1923                                  */
1924                                 if (fd_sense_drive_status(fdc, &st3))
1925                                         failed = 1;
1926                                 if ((st3 & NE7_ST3_T0) == 0) {
1927                                         printf(
1928                 "fd%d: Seek to cyl 0, but not really there (ST3 = %b)\n",
1929                                                fdu, st3, NE7_ST3BITS);
1930                                         failed = 1;
1931                                 }
1932
1933                                 if (failed) {
1934                                         if(fdc->retry < 3)
1935                                                 fdc->retry = 3;
1936                                         return (retrier(fdc));
1937                                 }
1938                         }
1939
1940                         if (cyl != descyl) {
1941                                 printf(
1942                 "fd%d: Seek to cyl %d failed; am at cyl %d (ST0 = 0x%x)\n",
1943                                        fdu, descyl, cyl, st0);
1944                                 if (fdc->retry < 3)
1945                                         fdc->retry = 3;
1946                                 return (retrier(fdc));
1947                         }
1948                 }
1949
1950                 fd->track = cylinder;
1951                 if (format)
1952                         fd->skip = (char *)&(finfo->fd_formb_cylno(0))
1953                             - (char *)finfo;
1954                 if (!rdsectid && !(fdc->flags & FDC_NODMA))
1955                         isa_dmastart(idf, bp->bio_data+fd->skip,
1956                                 format ? bp->bio_bcount : fdblk, fdc->dmachan);
1957                 blknum = bp->bio_pblkno + fd->skip / fdblk;
1958                 sectrac = fd->ft->sectrac;
1959                 sec = blknum %  (sectrac * fd->ft->heads);
1960                 head = sec / sectrac;
1961                 sec = sec % sectrac + 1;
1962                 if (head != 0 && fd->ft->offset_side2 != 0)
1963                         sec += fd->ft->offset_side2;
1964                 fd->hddrv = ((head&1)<<2)+fdu;
1965
1966                 if(format || !(read || rdsectid))
1967                 {
1968                         /* make sure the drive is writable */
1969                         if(fd_sense_drive_status(fdc, &st3) != 0)
1970                         {
1971                                 /* stuck controller? */
1972                                 if (!(fdc->flags & FDC_NODMA))
1973                                         isa_dmadone(idf,
1974                                                     bp->bio_data + fd->skip,
1975                                                     format ? bp->bio_bcount : fdblk,
1976                                                     fdc->dmachan);
1977                                 fdc->retry = 6; /* reset the beast */
1978                                 return (retrier(fdc));
1979                         }
1980                         if(st3 & NE7_ST3_WP)
1981                         {
1982                                 /*
1983                                  * XXX YES! this is ugly.
1984                                  * in order to force the current operation
1985                                  * to fail, we will have to fake an FDC
1986                                  * error - all error handling is done
1987                                  * by the retrier()
1988                                  */
1989                                 fdc->status[0] = NE7_ST0_IC_AT;
1990                                 fdc->status[1] = NE7_ST1_NW;
1991                                 fdc->status[2] = 0;
1992                                 fdc->status[3] = fd->track;
1993                                 fdc->status[4] = head;
1994                                 fdc->status[5] = sec;
1995                                 fdc->retry = 8; /* break out immediately */
1996                                 fdc->state = IOTIMEDOUT; /* not really... */
1997                                 return (1); /* will return immediately */
1998                         }
1999                 }
2000
2001                 if (format) {
2002                         ne7cmd = NE7CMD_FORMAT | mfm;
2003                         if (fdc->flags & FDC_NODMA) {
2004                                 /*
2005                                  * This seems to be necessary for
2006                                  * whatever obscure reason; if we omit
2007                                  * it, we end up filling the sector ID
2008                                  * fields of the newly formatted track
2009                                  * entirely with garbage, causing
2010                                  * `wrong cylinder' errors all over
2011                                  * the place when trying to read them
2012                                  * back.
2013                                  *
2014                                  * Umpf.
2015                                  */
2016                                 SET_BCDR(fdc, 1, bp->bio_bcount, 0);
2017
2018                                 (void)fdcpio(fdc,bp->bio_cmd,
2019                                         bp->bio_data+fd->skip,
2020                                         bp->bio_bcount);
2021
2022                         }
2023                         /* formatting */
2024                         if(fd_cmd(fdc, 6,  ne7cmd, head << 2 | fdu,
2025                                   finfo->fd_formb_secshift,
2026                                   finfo->fd_formb_nsecs,
2027                                   finfo->fd_formb_gaplen,
2028                                   finfo->fd_formb_fillbyte, 0)) {
2029                                 /* controller fell over */
2030                                 if (!(fdc->flags & FDC_NODMA))
2031                                         isa_dmadone(idf,
2032                                                     bp->bio_data + fd->skip,
2033                                                     format ? bp->bio_bcount : fdblk,
2034                                                     fdc->dmachan);
2035                                 fdc->retry = 6;
2036                                 return (retrier(fdc));
2037                         }
2038                 } else if (rdsectid) {
2039                         ne7cmd = NE7CMD_READID | mfm;
2040                         if (fd_cmd(fdc, 2, ne7cmd, head << 2 | fdu, 0)) {
2041                                 /* controller jamming */
2042                                 fdc->retry = 6;
2043                                 return (retrier(fdc));
2044                         }
2045                 } else {
2046                         /* read or write operation */
2047                         ne7cmd = (read ? NE7CMD_READ | NE7CMD_SK : NE7CMD_WRITE) | mfm;
2048                         if (fdc->flags & FDC_NODMA) {
2049                                 /*
2050                                  * This seems to be necessary even when
2051                                  * reading data.
2052                                  */
2053                                 SET_BCDR(fdc, 1, fdblk, 0);
2054
2055                                 /*
2056                                  * Perform the write pseudo-DMA before
2057                                  * the WRITE command is sent.
2058                                  */
2059                                 if (!read)
2060                                         (void)fdcpio(fdc,bp->bio_cmd,
2061                                             bp->bio_data+fd->skip,
2062                                             fdblk);
2063                         }
2064                         if (fd_cmd(fdc, 9,
2065                                    ne7cmd,
2066                                    head << 2 | fdu,  /* head & unit */
2067                                    fd->track,        /* track */
2068                                    head,
2069                                    sec,              /* sector + 1 */
2070                                    fd->ft->secsize,  /* sector size */
2071                                    sectrac,          /* sectors/track */
2072                                    fd->ft->gap,      /* gap size */
2073                                    fd->ft->datalen,  /* data length */
2074                                    0)) {
2075                                 /* the beast is sleeping again */
2076                                 if (!(fdc->flags & FDC_NODMA))
2077                                         isa_dmadone(idf,
2078                                                     bp->bio_data + fd->skip,
2079                                                     format ? bp->bio_bcount : fdblk,
2080                                                     fdc->dmachan);
2081                                 fdc->retry = 6;
2082                                 return (retrier(fdc));
2083                         }
2084                 }
2085                 if (!rdsectid && (fdc->flags & FDC_NODMA))
2086                         /*
2087                          * If this is a read, then simply await interrupt
2088                          * before performing PIO.
2089                          */
2090                         if (read && !fdcpio(fdc,bp->bio_cmd,
2091                             bp->bio_data+fd->skip,fdblk)) {
2092                                 fd->tohandle = timeout(fd_iotimeout, fdc, hz);
2093                                 return(0);      /* will return later */
2094                         }
2095
2096                 /*
2097                  * Write (or format) operation will fall through and
2098                  * await completion interrupt.
2099                  */
2100                 fdc->state = IOCOMPLETE;
2101                 fd->tohandle = timeout(fd_iotimeout, fdc, hz);
2102                 return (0);     /* will return later */
2103
2104         case PIOREAD:
2105                 /* 
2106                  * Actually perform the PIO read.  The IOCOMPLETE case
2107                  * removes the timeout for us.
2108                  */
2109                 (void)fdcpio(fdc,bp->bio_cmd,bp->bio_data+fd->skip,fdblk);
2110                 fdc->state = IOCOMPLETE;
2111                 /* FALLTHROUGH */
2112         case IOCOMPLETE: /* IO done, post-analyze */
2113                 untimeout(fd_iotimeout, fdc, fd->tohandle);
2114
2115                 if (fd_read_status(fdc)) {
2116                         if (!rdsectid && !(fdc->flags & FDC_NODMA))
2117                                 isa_dmadone(idf, bp->bio_data + fd->skip,
2118                                             format ? bp->bio_bcount : fdblk,
2119                                             fdc->dmachan);
2120                         if (fdc->retry < 6)
2121                                 fdc->retry = 6; /* force a reset */
2122                         return (retrier(fdc));
2123                 }
2124
2125                 fdc->state = IOTIMEDOUT;
2126
2127                 /* FALLTHROUGH */
2128         case IOTIMEDOUT:
2129                 if (!rdsectid && !(fdc->flags & FDC_NODMA))
2130                         isa_dmadone(idf, bp->bio_data + fd->skip,
2131                                 format ? bp->bio_bcount : fdblk, fdc->dmachan);
2132                 if (fdc->status[0] & NE7_ST0_IC) {
2133                         if ((fdc->status[0] & NE7_ST0_IC) == NE7_ST0_IC_AT
2134                             && fdc->status[1] & NE7_ST1_OR) {
2135                                 /*
2136                                  * DMA overrun. Someone hogged the bus and
2137                                  * didn't release it in time for the next
2138                                  * FDC transfer.
2139                                  *
2140                                  * We normally restart this without bumping
2141                                  * the retry counter.  However, in case
2142                                  * something is seriously messed up (like
2143                                  * broken hardware), we rather limit the
2144                                  * number of retries so the IO operation
2145                                  * doesn't block indefinately.
2146                                  */
2147                                 if (fdc->dma_overruns++ < FDC_DMAOV_MAX) {
2148                                         fdc->state = SEEKCOMPLETE;
2149                                         return (1);/* will return immediately */
2150                                 } /* else fall through */
2151                         }
2152                         if((fdc->status[0] & NE7_ST0_IC) == NE7_ST0_IC_IV
2153                                 && fdc->retry < 6)
2154                                 fdc->retry = 6; /* force a reset */
2155                         else if((fdc->status[0] & NE7_ST0_IC) == NE7_ST0_IC_AT
2156                                 && fdc->status[2] & NE7_ST2_WC
2157                                 && fdc->retry < 3)
2158                                 fdc->retry = 3; /* force recalibrate */
2159                         return (retrier(fdc));
2160                 }
2161                 /* All OK */
2162                 if (rdsectid) {
2163                         /* copy out ID field contents */
2164                         idp = (struct fdc_readid *)bp->bio_data;
2165                         idp->cyl = fdc->status[3];
2166                         idp->head = fdc->status[4];
2167                         idp->sec = fdc->status[5];
2168                         idp->secshift = fdc->status[6];
2169                 }
2170                 /* Operation successful, retry DMA overruns again next time. */
2171                 fdc->dma_overruns = 0;
2172                 fd->skip += fdblk;
2173                 if (!rdsectid && !format && fd->skip < bp->bio_bcount) {
2174                         /* set up next transfer */
2175                         fdc->state = DOSEEK;
2176                 } else {
2177                         /* ALL DONE */
2178                         fd->skip = 0;
2179                         bp->bio_resid = 0;
2180                         fdc->bp = NULL;
2181                         device_unbusy(fd->dev);
2182                         biofinish(bp, fd->device_stats, 0);
2183                         fdc->fd = (fd_p) 0;
2184                         fdc->fdu = -1;
2185                         fdc->state = FINDWORK;
2186                 }
2187                 return (1);     /* will return immediately */
2188
2189         case RESETCTLR:
2190                 fdc_reset(fdc);
2191                 fdc->retry++;
2192                 fdc->state = RESETCOMPLETE;
2193                 return (0);     /* will return later */
2194
2195         case RESETCOMPLETE:
2196                 /*
2197                  * Discard all the results from the reset so that they
2198                  * can't cause an unexpected interrupt later.
2199                  */
2200                 for (i = 0; i < 4; i++)
2201                         (void)fd_sense_int(fdc, &st0, &cyl);
2202                 fdc->state = STARTRECAL;
2203                 /* FALLTHROUGH */
2204         case STARTRECAL:
2205 #ifdef PC98
2206                 pc98_fd_check_ready(fdu);
2207 #endif
2208                 if(fd_cmd(fdc, 2, NE7CMD_RECAL, fdu, 0)) {
2209                         /* arrgl */
2210                         fdc->retry = 6;
2211                         return (retrier(fdc));
2212                 }
2213                 fdc->state = RECALWAIT;
2214                 return (0);     /* will return later */
2215
2216         case RECALWAIT:
2217                 /* allow heads to settle */
2218                 timeout(fd_pseudointr, fdc, hz / 8);
2219                 fdc->state = RECALCOMPLETE;
2220                 return (0);     /* will return later */
2221
2222         case RECALCOMPLETE:
2223                 do {
2224                         /*
2225                          * See SEEKCOMPLETE for a comment on this:
2226                          */
2227                         if (fd_sense_int(fdc, &st0, &cyl) == FD_NOT_VALID)
2228                                 return (0); /* will return later */
2229                         if(fdc->fdct == FDC_NE765
2230                            && (st0 & NE7_ST0_IC) == NE7_ST0_IC_RC)
2231                                 return (0); /* hope for a real intr */
2232                 } while ((st0 & NE7_ST0_IC) == NE7_ST0_IC_RC);
2233                 if ((st0 & NE7_ST0_IC) != NE7_ST0_IC_NT || cyl != 0)
2234                 {
2235                         if(fdc->retry > 3)
2236                                 /*
2237                                  * A recalibrate from beyond cylinder 77
2238                                  * will "fail" due to the FDC limitations;
2239                                  * since people used to complain much about
2240                                  * the failure message, try not logging
2241                                  * this one if it seems to be the first
2242                                  * time in a line.
2243                                  */
2244                                 printf("fd%d: recal failed ST0 %b cyl %d\n",
2245                                        fdu, st0, NE7_ST0BITS, cyl);
2246                         if(fdc->retry < 3) fdc->retry = 3;
2247                         return (retrier(fdc));
2248                 }
2249                 fd->track = 0;
2250                 /* Seek (probably) necessary */
2251                 fdc->state = DOSEEK;
2252                 return (1);     /* will return immediately */
2253
2254         case MOTORWAIT:
2255                 if(fd->flags & FD_MOTOR_WAIT)
2256                 {
2257                         return (0); /* time's not up yet */
2258                 }
2259                 if (fdc->flags & FDC_NEEDS_RESET) {
2260                         fdc->state = RESETCTLR;
2261                         fdc->flags &= ~FDC_NEEDS_RESET;
2262                 } else
2263                         fdc->state = DOSEEK;
2264                 return (1);     /* will return immediately */
2265
2266         default:
2267                 device_printf(fdc->fdc_dev, "unexpected FD int->");
2268                 if (fd_read_status(fdc) == 0)
2269                         printf("FDC status :%x %x %x %x %x %x %x   ",
2270                                fdc->status[0],
2271                                fdc->status[1],
2272                                fdc->status[2],
2273                                fdc->status[3],
2274                                fdc->status[4],
2275                                fdc->status[5],
2276                                fdc->status[6] );
2277                 else
2278                         printf("No status available   ");
2279                 if (fd_sense_int(fdc, &st0, &cyl) != 0)
2280                 {
2281                         printf("[controller is dead now]\n");
2282                         return (0); /* will return later */
2283                 }
2284                 printf("ST0 = %x, PCN = %x\n", st0, cyl);
2285                 return (0);     /* will return later */
2286         }
2287         /* noone should ever get here */
2288 }
2289
2290 static int
2291 retrier(struct fdc_data *fdc)
2292 {
2293         struct bio *bp;
2294         struct fd_data *fd;
2295         int fdu;
2296
2297         bp = fdc->bp;
2298
2299         /* XXX shouldn't this be cached somewhere?  */
2300         fd = bp->bio_dev->si_drv1;
2301         fdu = fd->fdu;
2302         if (fd->options & FDOPT_NORETRY)
2303                 goto fail;
2304
2305         switch (fdc->retry) {
2306         case 0: case 1: case 2:
2307                 fdc->state = SEEKCOMPLETE;
2308                 break;
2309         case 3: case 4: case 5:
2310                 fdc->state = STARTRECAL;
2311                 break;
2312         case 6:
2313                 fdc->state = RESETCTLR;
2314                 break;
2315         case 7:
2316                 break;
2317         default:
2318         fail:
2319                 if ((fd->options & FDOPT_NOERRLOG) == 0) {
2320                         disk_err(bp, "hard error",
2321                             fdc->fd->skip / DEV_BSIZE, 0);
2322                         if (fdc->flags & FDC_STAT_VALID) {
2323                                 printf(
2324                                 " (ST0 %b ST1 %b ST2 %b cyl %u hd %u sec %u)\n",
2325                                        fdc->status[0], NE7_ST0BITS,
2326                                        fdc->status[1], NE7_ST1BITS,
2327                                        fdc->status[2], NE7_ST2BITS,
2328                                        fdc->status[3], fdc->status[4],
2329                                        fdc->status[5]);
2330                         }
2331                         else
2332                                 printf(" (No status)\n");
2333                 }
2334                 if ((fd->options & FDOPT_NOERROR) == 0) {
2335                         bp->bio_flags |= BIO_ERROR;
2336                         bp->bio_error = EIO;
2337                         bp->bio_resid = bp->bio_bcount - fdc->fd->skip;
2338                 } else
2339                         bp->bio_resid = 0;
2340                 fdc->bp = NULL;
2341                 fdc->fd->skip = 0;
2342                 device_unbusy(fd->dev);
2343                 biofinish(bp, fdc->fd->device_stats, 0);
2344                 fdc->state = FINDWORK;
2345                 fdc->flags |= FDC_NEEDS_RESET;
2346                 fdc->fd = (fd_p) 0;
2347                 fdc->fdu = -1;
2348                 return (1);
2349         }
2350         fdc->retry++;
2351         return (1);
2352 }
2353
2354 static void
2355 fdbiodone(struct bio *bp)
2356 {
2357         wakeup(bp);
2358 }
2359
2360 static int
2361 fdmisccmd(struct cdev *dev, u_int cmd, void *data)
2362 {
2363         fdu_t fdu;
2364         fd_p fd;
2365         struct bio *bp;
2366         struct fd_formb *finfo;
2367         struct fdc_readid *idfield;
2368         size_t fdblk;
2369         int error;
2370
2371         fd = dev->si_drv1;
2372         fdu = fd->fdu;
2373         fdblk = 128 << fd->ft->secsize;
2374         finfo = (struct fd_formb *)data;
2375         idfield = (struct fdc_readid *)data;
2376
2377         bp = malloc(sizeof(struct bio), M_TEMP, M_WAITOK | M_ZERO);
2378
2379         /*
2380          * Set up a bio request for fdstrategy().  bio_offset is faked
2381          * so that fdstrategy() will seek to the requested
2382          * cylinder, and use the desired head.
2383          */
2384         bp->bio_cmd = cmd;
2385         if (cmd == FDBIO_FORMAT) {
2386                 bp->bio_offset =
2387                     (finfo->cyl * (fd->ft->sectrac * fd->ft->heads) +
2388                      finfo->head * fd->ft->sectrac) * fdblk;
2389                 bp->bio_bcount = sizeof(struct fd_idfield_data) *
2390                     finfo->fd_formb_nsecs;
2391         } else if (cmd == FDBIO_RDSECTID) {
2392                 bp->bio_offset =
2393                     (idfield->cyl * (fd->ft->sectrac * fd->ft->heads) +
2394                      idfield->head * fd->ft->sectrac) * fdblk;
2395                 bp->bio_bcount = sizeof(struct fdc_readid);
2396         } else
2397                 panic("wrong cmd in fdmisccmd()");
2398         bp->bio_data = data;
2399         bp->bio_dev = dev;
2400         bp->bio_done = fdbiodone;
2401         bp->bio_flags = 0;
2402
2403         /* Now run the command. */
2404         fdstrategy(bp);
2405         error = biowait(bp, "fdcmd");
2406
2407         free(bp, M_TEMP);
2408         return (error);
2409 }
2410
2411 static int
2412 fdioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td)
2413 {
2414         fdu_t fdu;
2415         fd_p fd;
2416         struct fdc_status *fsp;
2417         struct fdc_readid *rid;
2418         int error;
2419
2420         fd = dev->si_drv1;
2421         fdu = fd->fdu;
2422
2423 #ifdef PC98
2424         pc98_fd_check_ready(fdu);
2425 #endif  
2426
2427         /*
2428          * First, handle everything that could be done with
2429          * FD_NONBLOCK still being set.
2430          */
2431         switch (cmd) {
2432
2433         case DIOCGMEDIASIZE:
2434                 if (fd->ft == 0)
2435                         return ((fd->flags & FD_NONBLOCK) ? EAGAIN : ENXIO);
2436                 *(off_t *)addr = (128 << (fd->ft->secsize)) * fd->ft->size;
2437                 return (0);
2438
2439         case DIOCGSECTORSIZE:
2440                 if (fd->ft == 0)
2441                         return ((fd->flags & FD_NONBLOCK) ? EAGAIN : ENXIO);
2442                 *(u_int *)addr = 128 << (fd->ft->secsize);
2443                 return (0);
2444
2445         case FIONBIO:
2446                 if (*(int *)addr != 0)
2447                         fd->flags |= FD_NONBLOCK;
2448                 else {
2449                         if (fd->ft == 0) {
2450                                 /*
2451                                  * No drive type has been selected yet,
2452                                  * cannot turn FNONBLOCK off.
2453                                  */
2454                                 return (EINVAL);
2455                         }
2456                         fd->flags &= ~FD_NONBLOCK;
2457                 }
2458                 return (0);
2459
2460         case FIOASYNC:
2461                 /* keep the generic fcntl() code happy */
2462                 return (0);
2463
2464         case FD_GTYPE:                  /* get drive type */
2465                 if (fd->ft == 0)
2466                         /* no type known yet, return the native type */
2467                         *(struct fd_type *)addr = fd_native_types[fd->type];
2468                 else
2469                         *(struct fd_type *)addr = *fd->ft;
2470                 return (0);
2471
2472         case FD_STYPE:                  /* set drive type */
2473                 /*
2474                  * Allow setting drive type temporarily iff
2475                  * currently unset.  Used for fdformat so any
2476                  * user can set it, and then start formatting.
2477                  */
2478                 if (fd->ft)
2479                         return (EINVAL); /* already set */
2480                 fd->fts[0] = *(struct fd_type *)addr;
2481                 fd->ft = &fd->fts[0];
2482                 fd->flags |= FD_UA;
2483                 return (0);
2484
2485         case FD_GOPTS:                  /* get drive options */
2486                 *(int *)addr = fd->options + FDOPT_AUTOSEL;
2487                 return (0);
2488
2489         case FD_SOPTS:                  /* set drive options */
2490                 fd->options = *(int *)addr & ~FDOPT_AUTOSEL;
2491                 return (0);
2492
2493 #ifdef FDC_DEBUG
2494         case FD_DEBUG:
2495                 if ((fd_debug != 0) != (*(int *)addr != 0)) {
2496                         fd_debug = (*(int *)addr != 0);
2497                         printf("fd%d: debugging turned %s\n",
2498                             fd->fdu, fd_debug ? "on" : "off");
2499                 }
2500                 return (0);
2501 #endif
2502
2503         case FD_CLRERR:
2504                 if (priv_check(td, PRIV_DRIVER) != 0)
2505                         return (EPERM);
2506                 fd->fdc->fdc_errs = 0;
2507                 return (0);
2508
2509         case FD_GSTAT:
2510                 fsp = (struct fdc_status *)addr;
2511                 if ((fd->fdc->flags & FDC_STAT_VALID) == 0)
2512                         return (EINVAL);
2513                 memcpy(fsp->status, fd->fdc->status, 7 * sizeof(u_int));
2514                 return (0);
2515
2516         case FD_GDTYPE:
2517                 *(enum fd_drivetype *)addr = fd->type;
2518                 return (0);
2519         }
2520
2521         /*
2522          * Now handle everything else.  Make sure we have a valid
2523          * drive type.
2524          */
2525         if (fd->flags & FD_NONBLOCK)
2526                 return (EAGAIN);
2527         if (fd->ft == 0)
2528                 return (ENXIO);
2529         error = 0;
2530
2531         switch (cmd) {
2532
2533         case FD_FORM:
2534                 if ((flag & FWRITE) == 0)
2535                         return (EBADF); /* must be opened for writing */
2536                 if (((struct fd_formb *)addr)->format_version !=
2537                     FD_FORMAT_VERSION)
2538                         return (EINVAL); /* wrong version of formatting prog */
2539                 error = fdmisccmd(dev, FDBIO_FORMAT, addr);
2540                 break;
2541
2542         case FD_GTYPE:                  /* get drive type */
2543                 *(struct fd_type *)addr = *fd->ft;
2544                 break;
2545
2546         case FD_STYPE:                  /* set drive type */
2547                 /* this is considered harmful; only allow for superuser */
2548                 if (priv_check(td, PRIV_DRIVER) != 0)
2549                         return (EPERM);
2550                 *fd->ft = *(struct fd_type *)addr;
2551                 break;
2552
2553         case FD_GOPTS:                  /* get drive options */
2554                 *(int *)addr = fd->options;
2555                 break;
2556
2557         case FD_SOPTS:                  /* set drive options */
2558                 fd->options = *(int *)addr;
2559                 break;
2560
2561 #ifdef FDC_DEBUG
2562         case FD_DEBUG:
2563                 if ((fd_debug != 0) != (*(int *)addr != 0)) {
2564                         fd_debug = (*(int *)addr != 0);
2565                         printf("fd%d: debugging turned %s\n",
2566                             fd->fdu, fd_debug ? "on" : "off");
2567                 }
2568                 break;
2569 #endif
2570
2571         case FD_CLRERR:
2572                 if (priv_check(td, PRIV_DRIVER) != 0)
2573                         return (EPERM);
2574                 fd->fdc->fdc_errs = 0;
2575                 break;
2576
2577         case FD_GSTAT:
2578                 fsp = (struct fdc_status *)addr;
2579                 if ((fd->fdc->flags & FDC_STAT_VALID) == 0)
2580                         return (EINVAL);
2581                 memcpy(fsp->status, fd->fdc->status, 7 * sizeof(u_int));
2582                 break;
2583
2584         case FD_READID:
2585                 rid = (struct fdc_readid *)addr;
2586                 if (rid->cyl > MAX_CYLINDER || rid->head > MAX_HEAD)
2587                         return (EINVAL);
2588                 error = fdmisccmd(dev, FDBIO_RDSECTID, addr);
2589                 break;
2590
2591         default:
2592                 error = ENOTTY;
2593                 break;
2594         }
2595         return (error);
2596 }