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