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