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