fd.c revision 1.51.2.2 1 /* $NetBSD: fd.c,v 1.51.2.2 2014/05/22 11:39:26 yamt Exp $ */
2
3 /*-
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Charles M. Hannum.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*-
33 * Copyright (c) 1990 The Regents of the University of California.
34 * All rights reserved.
35 *
36 * This code is derived from software contributed to Berkeley by
37 * Don Ahn.
38 *
39 * Redistribution and use in source and binary forms, with or without
40 * modification, are permitted provided that the following conditions
41 * are met:
42 * 1. Redistributions of source code must retain the above copyright
43 * notice, this list of conditions and the following disclaimer.
44 * 2. Redistributions in binary form must reproduce the above copyright
45 * notice, this list of conditions and the following disclaimer in the
46 * documentation and/or other materials provided with the distribution.
47 * 3. Neither the name of the University nor the names of its contributors
48 * may be used to endorse or promote products derived from this software
49 * without specific prior written permission.
50 *
51 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 * SUCH DAMAGE.
62 *
63 * @(#)fd.c 7.4 (Berkeley) 5/25/91
64 * from: fd.c,v 1.104 1997/01/09 04:30:08 mycroft Exp
65 */
66
67 /*
68 * Floppy formatting facilities merged from FreeBSD fd.c driver:
69 * Id: fd.c,v 1.53 1995/03/12 22:40:56 joerg Exp
70 * which carries the same copyright/redistribution notice as shown above with
71 * the addition of the following statement before the "Redistribution and
72 * use ..." clause:
73 *
74 * Copyright (c) 1993, 1994 by
75 * jc (at) irbs.UUCP (John Capo)
76 * vak (at) zebub.msk.su (Serge Vakulenko)
77 * ache (at) astral.msk.su (Andrew A. Chernov)
78 *
79 * Copyright (c) 1993, 1994, 1995 by
80 * joerg_wunsch (at) uriah.sax.de (Joerg Wunsch)
81 * dufault (at) hda.com (Peter Dufault)
82 */
83
84 #include <sys/cdefs.h>
85 __KERNEL_RCSID(0, "$NetBSD: fd.c,v 1.51.2.2 2014/05/22 11:39:26 yamt Exp $");
86
87 #include "opt_ddb.h"
88
89 #include <sys/param.h>
90 #include <sys/systm.h>
91 #include <sys/callout.h>
92 #include <sys/kernel.h>
93 #include <sys/file.h>
94 #include <sys/ioctl.h>
95 #include <sys/device.h>
96 #include <sys/disklabel.h>
97 #include <sys/disk.h>
98 #include <sys/buf.h>
99 #include <sys/bufq.h>
100 #include <sys/malloc.h>
101 #include <sys/uio.h>
102 #include <sys/syslog.h>
103 #include <sys/queue.h>
104 #include <sys/proc.h>
105 #include <sys/fdio.h>
106 #include <sys/conf.h>
107 #include <sys/bus.h>
108
109 #include <uvm/uvm_extern.h>
110
111 #include <arm/fiq.h>
112
113 #include <machine/cpu.h>
114 #include <machine/intr.h>
115 #include <machine/io.h>
116 #include <arm/arm32/katelib.h>
117
118 #include <arm/iomd/iomdreg.h>
119 #include <arm/iomd/iomdvar.h>
120
121 #include <acorn32/mainbus/piocvar.h>
122 #include <acorn32/mainbus/fdreg.h>
123
124 #include "locators.h"
125
126 #define NE7CMD_CONFIGURE 0x13
127
128 #define FDUNIT(dev) (minor(dev) / 8)
129 #define FDTYPE(dev) (minor(dev) % 8)
130
131 /* (mis)use device use flag to identify format operation */
132 #define B_FORMAT B_DEVPRIVATE
133
134 enum fdc_state {
135 DEVIDLE = 0,
136 MOTORWAIT,
137 DOSEEK,
138 SEEKWAIT,
139 SEEKTIMEDOUT,
140 SEEKCOMPLETE,
141 DOIO,
142 IOCOMPLETE,
143 IOTIMEDOUT,
144 DORESET,
145 RESETCOMPLETE,
146 RESETTIMEDOUT,
147 DORECAL,
148 RECALWAIT,
149 RECALTIMEDOUT,
150 RECALCOMPLETE,
151 };
152
153 /* software state, per controller */
154 struct fdc_softc {
155 device_t sc_dev; /* boilerplate */
156 void *sc_ih;
157
158 bus_space_tag_t sc_iot; /* ISA i/o space identifier */
159 bus_space_handle_t sc_ioh; /* ISA io handle */
160
161 struct callout sc_timo_ch; /* timeout callout */
162 struct callout sc_intr_ch; /* pseudo-intr callout */
163
164 /* ...for pseudo-DMA... */
165 struct fiqhandler sc_fh; /* FIQ handler descriptor */
166 struct fiqregs sc_fr; /* FIQ handler reg context */
167 int sc_drq;
168
169 struct fd_softc *sc_fd[4]; /* pointers to children */
170 TAILQ_HEAD(drivehead, fd_softc) sc_drives;
171 enum fdc_state sc_state;
172 int sc_errors; /* number of retries so far */
173 u_char sc_status[7]; /* copy of registers */
174 };
175
176 /* controller driver configuration */
177 int fdcprobe(device_t, cfdata_t, void *);
178 int fdprint(void *, const char *);
179 void fdcattach(device_t, device_t, void *);
180
181 CFATTACH_DECL_NEW(fdc, sizeof(struct fdc_softc),
182 fdcprobe, fdcattach, NULL, NULL);
183
184 /*
185 * Floppies come in various flavors, e.g., 1.2MB vs 1.44MB; here is how
186 * we tell them apart.
187 */
188 struct fd_type {
189 int sectrac; /* sectors per track */
190 int heads; /* number of heads */
191 int seccyl; /* sectors per cylinder */
192 int secsize; /* size code for sectors */
193 int datalen; /* data len when secsize = 0 */
194 int steprate; /* step rate and head unload time */
195 int gap1; /* gap len between sectors */
196 int gap2; /* formatting gap */
197 int cyls; /* total num of cylinders */
198 int size; /* size of disk in sectors */
199 int step; /* steps per cylinder */
200 int rate; /* transfer speed code */
201 u_char fillbyte; /* format fill byte */
202 u_char interleave; /* interleave factor (formatting) */
203 const char *name;
204 };
205
206 /* The order of entries in the following table is important -- BEWARE! */
207 struct fd_type fd_types[] = {
208 { 18,2,36,2,0xff,0xcf,0x1b,0x6c,80,2880,1,FDC_500KBPS,0xf6,1, "1.44MB" }, /* 1.44MB diskette */
209 { 15,2,30,2,0xff,0xdf,0x1b,0x54,80,2400,1,FDC_500KBPS,0xf6,1, "1.2MB" }, /* 1.2 MB AT-diskettes */
210 { 9,2,18,2,0xff,0xdf,0x23,0x50,40, 720,2,FDC_300KBPS,0xf6,1, "360KB/AT" }, /* 360kB in 1.2MB drive */
211 { 9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,1,FDC_250KBPS,0xf6,1, "360KB/PC" }, /* 360kB PC diskettes */
212 { 9,2,18,2,0xff,0xdf,0x2a,0x50,80,1440,1,FDC_250KBPS,0xf6,1, "720KB" }, /* 3.5" 720kB diskette */
213 { 9,2,18,2,0xff,0xdf,0x23,0x50,80,1440,1,FDC_300KBPS,0xf6,1, "720KB/x" }, /* 720kB in 1.2MB drive */
214 { 9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,2,FDC_250KBPS,0xf6,1, "360KB/x" }, /* 360kB in 720kB drive */
215 };
216
217 /* software state, per disk (with up to 4 disks per ctlr) */
218 struct fd_softc {
219 device_t sc_dev;
220 struct disk sc_dk;
221
222 struct fd_type *sc_deftype; /* default type descriptor */
223 struct fd_type *sc_type; /* current type descriptor */
224 struct fd_type sc_type_copy; /* copy for fiddling when formatting */
225
226 struct callout sc_motoron_ch;
227 struct callout sc_motoroff_ch;
228
229 daddr_t sc_blkno; /* starting block number */
230 int sc_bcount; /* byte count left */
231 int sc_opts; /* user-set options */
232 int sc_skip; /* bytes already transferred */
233 int sc_nblks; /* number of blocks currently transferring */
234 int sc_nbytes; /* number of bytes currently transferring */
235
236 int sc_drive; /* physical unit number */
237 int sc_flags;
238 #define FD_OPEN 0x01 /* it's open */
239 #define FD_MOTOR 0x02 /* motor should be on */
240 #define FD_MOTOR_WAIT 0x04 /* motor coming up */
241 int sc_cylin; /* where we think the head is */
242
243 void *sc_sdhook; /* saved shutdown hook for drive. */
244
245 TAILQ_ENTRY(fd_softc) sc_drivechain;
246 int sc_ops; /* I/O ops since last switch */
247 struct bufq_state *sc_q;/* pending I/O requests */
248 int sc_active; /* number of active I/O operations */
249 };
250
251 /* floppy driver configuration */
252 int fdprobe(device_t, cfdata_t, void *);
253 void fdattach(device_t, device_t, void *);
254
255 extern char floppy_read_fiq[], floppy_read_fiq_end[];
256 extern char floppy_write_fiq[], floppy_write_fiq_end[];
257
258 CFATTACH_DECL_NEW(fd, sizeof(struct fd_softc),
259 fdprobe, fdattach, NULL, NULL);
260
261 extern struct cfdriver fd_cd;
262
263 dev_type_open(fdopen);
264 dev_type_close(fdclose);
265 dev_type_read(fdread);
266 dev_type_write(fdwrite);
267 dev_type_ioctl(fdioctl);
268 dev_type_strategy(fdstrategy);
269
270 const struct bdevsw fd_bdevsw = {
271 .d_open = fdopen,
272 .d_close = fdclose,
273 .d_strategy = fdstrategy,
274 .d_ioctl = fdioctl,
275 .d_dump = nodump,
276 .d_psize = nosize,
277 .d_flag = D_DISK
278 };
279
280 const struct cdevsw fd_cdevsw = {
281 .d_open = fdopen,
282 .d_close = fdclose,
283 .d_read = fdread,
284 .d_write = fdwrite,
285 .d_ioctl = fdioctl,
286 .d_stop = nostop,
287 .d_tty = notty,
288 .d_poll = nopoll,
289 .d_mmap = nommap,
290 .d_kqfilter = nokqfilter,
291 .d_flag = D_DISK
292 };
293
294 void fdgetdisklabel(struct fd_softc *);
295 int fd_get_parms(struct fd_softc *);
296 void fdstart(struct fd_softc *);
297
298 struct dkdriver fddkdriver = { fdstrategy };
299
300 struct fd_type *fd_nvtotype(const char *, int, int);
301 void fd_set_motor(struct fdc_softc *fdc, int reset);
302 void fd_motor_off(void *arg);
303 void fd_motor_on(void *arg);
304 int fdcresult(struct fdc_softc *fdc);
305 int out_fdc(bus_space_tag_t iot, bus_space_handle_t ioh, u_char x);
306 void fdcstart(struct fdc_softc *fdc);
307 void fdcstatus(device_t dv, int n, const char *s);
308 void fdctimeout(void *arg);
309 void fdcpseudointr(void *arg);
310 int fdcintr(void *);
311 void fdcretry(struct fdc_softc *fdc);
312 void fdfinish(struct fd_softc *fd, struct buf *bp);
313 inline struct fd_type *fd_dev_to_type(struct fd_softc *, dev_t);
314 int fdformat(dev_t, struct ne7_fd_formb *, struct lwp *);
315
316 int
317 fdcprobe(device_t parent, cfdata_t cf, void *aux)
318 {
319 struct pioc_attach_args *pa = aux;
320 bus_space_tag_t iot;
321 bus_space_handle_t ioh;
322 int rv;
323
324 if (pa->pa_name && strcmp(pa->pa_name, "fdc") != 0)
325 return(0);
326
327 iot = pa->pa_iot;
328 rv = 0;
329
330 /* Map the i/o space. */
331 if (bus_space_map(iot, pa->pa_iobase + pa->pa_offset, FDC_NPORT, 0, &ioh))
332 return 0;
333
334 /* reset */
335 bus_space_write_2(iot, ioh, fdout, 0);
336 delay(100);
337 bus_space_write_2(iot, ioh, fdout, FDO_FRST);
338
339 /* see if it can handle a command */
340 if (out_fdc(iot, ioh, NE7CMD_SPECIFY) < 0)
341 goto out;
342 out_fdc(iot, ioh, 0xdf);
343 out_fdc(iot, ioh, 2);
344
345 rv = 1;
346 pa->pa_iosize = FDC_NPORT;
347
348 out:
349 bus_space_unmap(iot, ioh, FDC_NPORT);
350 return rv;
351 }
352
353 /*
354 * Arguments passed between fdcattach and fdprobe.
355 */
356 struct fdc_attach_args {
357 int fa_drive;
358 struct fd_type *fa_deftype;
359 };
360
361 /*
362 * Print the location of a disk drive (called just before attaching the
363 * the drive). If `fdc' is not NULL, the drive was found but was not
364 * in the system config file; print the drive name as well.
365 * Return QUIET (config_find ignores this if the device was configured) to
366 * avoid printing `fdN not configured' messages.
367 */
368 int
369 fdprint(void *aux, const char *fdc)
370 {
371 register struct fdc_attach_args *fa = aux;
372
373 if (!fdc)
374 aprint_normal(" drive %d", fa->fa_drive);
375 return QUIET;
376 }
377
378 void
379 fdcattach(device_t parent, device_t self, void *aux)
380 {
381 struct fdc_softc *fdc = device_private(self);
382 bus_space_tag_t iot;
383 bus_space_handle_t ioh;
384 struct pioc_attach_args *pa = aux;
385 struct fdc_attach_args fa;
386 int type;
387
388 iot = pa->pa_iot;
389
390 /* Re-map the I/O space. */
391 if (bus_space_map(iot, pa->pa_iobase + pa->pa_offset, FDC_NPORT, 0, &ioh))
392 panic("fdcattach: couldn't map I/O ports");
393
394 fdc->sc_dev = self;
395 fdc->sc_iot = iot;
396 fdc->sc_ioh = ioh;
397
398 fdc->sc_drq = pa->pa_iobase + pa->pa_offset + pa->pa_drq;
399 fdc->sc_state = DEVIDLE;
400 TAILQ_INIT(&fdc->sc_drives);
401
402 printf("\n");
403
404 callout_init(&fdc->sc_timo_ch, 0);
405 callout_init(&fdc->sc_intr_ch, 0);
406
407 fdc->sc_ih = intr_claim(pa->pa_irq, IPL_BIO, "fdc", fdcintr, fdc);
408 if (!fdc->sc_ih)
409 panic("%s: Cannot claim IRQ %d",
410 device_xname(self), pa->pa_irq);
411
412 #if 0
413 /*
414 * The NVRAM info only tells us about the first two disks on the
415 * `primary' floppy controller.
416 */
417 if (device_unit(fdc->sc_dev) == 0)
418 type = mc146818_read(NULL, NVRAM_DISKETTE); /* XXX softc */
419 else
420 type = -1;
421 #endif
422 type = 0x10; /* XXX - hardcoded for 1 floppy */
423
424 /* physical limit: four drives per controller. */
425 for (fa.fa_drive = 0; fa.fa_drive < 4; fa.fa_drive++) {
426 if (type >= 0 && fa.fa_drive < 2)
427 fa.fa_deftype = fd_nvtotype(device_xname(fdc->sc_dev),
428 type, fa.fa_drive);
429 else
430 fa.fa_deftype = NULL; /* unknown */
431 (void)config_found(self, (void *)&fa, fdprint);
432 }
433 }
434
435 int
436 fdprobe(device_t parent, cfdata_t cf, void *aux)
437 {
438 struct fdc_softc *fdc = device_private(parent);
439 struct fdc_attach_args *fa = aux;
440 int drive = fa->fa_drive;
441 bus_space_tag_t iot = fdc->sc_iot;
442 bus_space_handle_t ioh = fdc->sc_ioh;
443 int n;
444
445 if (cf->cf_loc[FDCCF_DRIVE] != FDCCF_DRIVE_DEFAULT
446 && cf->cf_loc[FDCCF_DRIVE] != drive)
447 return 0;
448 /*
449 * XXX
450 * This is to work around some odd interactions between this driver
451 * and SMC Ethernet cards.
452 */
453
454 /* Don't need this for arm32 port but leave for the time being (it won't hurt) */
455
456 if (cf->cf_loc[FDCCF_DRIVE] == FDCCF_DRIVE_DEFAULT && drive >= 2)
457 return 0;
458
459 /* select drive and turn on motor */
460 bus_space_write_2(iot, ioh, fdout, drive | FDO_FRST | FDO_MOEN(drive));
461 /* wait for motor to spin up */
462 delay(250000);
463 out_fdc(iot, ioh, NE7CMD_RECAL);
464 out_fdc(iot, ioh, drive);
465 /* wait for recalibrate */
466 delay(2000000);
467 out_fdc(iot, ioh, NE7CMD_SENSEI);
468 n = fdcresult(fdc);
469 #ifdef FD_DEBUG
470 {
471 int i;
472 printf("fdprobe: status");
473 for (i = 0; i < n; i++)
474 printf(" %x", fdc->sc_status[i]);
475 printf("\n");
476 }
477 #endif
478 /* turn off motor */
479 bus_space_write_1(iot, ioh, fdout, FDO_FRST);
480
481 if (n != 2 || (fdc->sc_status[0] & 0xf8) != 0x20)
482 return 0;
483
484 return 1;
485 }
486
487 /*
488 * Controller is working, and drive responded. Attach it.
489 */
490 void
491 fdattach(device_t parent, device_t self, void *aux)
492 {
493 struct fdc_softc *fdc = device_private(parent);
494 struct fd_softc *fd = device_private(self);
495 struct fdc_attach_args *fa = aux;
496 struct fd_type *type = fa->fa_deftype;
497 int drive = fa->fa_drive;
498
499 fd->sc_dev = self;
500
501 callout_init(&fd->sc_motoron_ch, 0);
502 callout_init(&fd->sc_motoroff_ch, 0);
503
504 /* XXX Allow `flags' to override device type? */
505
506 if (type)
507 printf(": %s %d cyl, %d head, %d sec\n", type->name,
508 type->cyls, type->heads, type->sectrac);
509 else
510 printf(": density unknown\n");
511
512 bufq_alloc(&fd->sc_q, "disksort", BUFQ_SORT_CYLINDER);
513 fd->sc_cylin = -1;
514 fd->sc_drive = drive;
515 fd->sc_deftype = type;
516 fdc->sc_fd[drive] = fd;
517
518 /*
519 * Initialize and attach the disk structure.
520 */
521 disk_init(&fd->sc_dk, device_xname(fd->sc_dev), &fddkdriver);
522 disk_attach(&fd->sc_dk);
523
524 /* Needed to power off if the motor is on when we halt. */
525
526 }
527
528 /*
529 * Translate nvram type into internal data structure. Return NULL for
530 * none/unknown/unusable.
531 */
532 struct fd_type *
533 fd_nvtotype(const char *fdc, int nvraminfo, int drive)
534 {
535 int type;
536
537 type = (drive == 0 ? nvraminfo : nvraminfo << 4) & 0xf0;
538 switch (type) {
539 #ifndef RC7500
540 case 0x00 :
541 return NULL;
542 #else
543 case 0x00 :
544 #endif /* !RC7500 */
545 case 0x10 :
546 return &fd_types[0];
547 default:
548 printf("%s: drive %d: unknown device type 0x%x\n",
549 fdc, drive, type);
550 return NULL;
551 }
552 }
553
554 inline struct fd_type *
555 fd_dev_to_type(struct fd_softc *fd, dev_t dev)
556 {
557 int type = FDTYPE(dev);
558
559 if (type > (sizeof(fd_types) / sizeof(fd_types[0])))
560 return NULL;
561 return type ? &fd_types[type - 1] : fd->sc_deftype;
562 }
563
564 void
565 fdstrategy(struct buf *bp)
566 {
567 struct fd_softc *fd = device_lookup_private(&fd_cd,FDUNIT(bp->b_dev));
568 int sz;
569 int s;
570
571 /* Valid unit, controller, and request? */
572 if (bp->b_blkno < 0 ||
573 ((bp->b_bcount % FDC_BSIZE) != 0 &&
574 (bp->b_flags & B_FORMAT) == 0)) {
575 bp->b_error = EINVAL;
576 goto done;
577 }
578
579 /* If it's a null transfer, return immediately. */
580 if (bp->b_bcount == 0)
581 goto done;
582
583 sz = howmany(bp->b_bcount, FDC_BSIZE);
584
585 if (bp->b_blkno + sz > fd->sc_type->size) {
586 sz = fd->sc_type->size - bp->b_blkno;
587 if (sz == 0) {
588 /* If exactly at end of disk, return EOF. */
589 goto done;
590 }
591 if (sz < 0) {
592 /* If past end of disk, return EINVAL. */
593 bp->b_error = EINVAL;
594 goto done;
595 }
596 /* Otherwise, truncate request. */
597 bp->b_bcount = sz << DEV_BSHIFT;
598 }
599
600 bp->b_rawblkno = bp->b_blkno;
601 bp->b_cylinder = bp->b_blkno / (FDC_BSIZE / DEV_BSIZE) / fd->sc_type->seccyl;
602
603 #ifdef FD_DEBUG
604 printf("fdstrategy: b_blkno %d b_bcount %d blkno %d cylin %d sz %d\n",
605 bp->b_blkno, bp->b_bcount, fd->sc_blkno, bp->b_cylinder, sz);
606 #endif
607
608 /* Queue transfer on drive, activate drive and controller if idle. */
609 s = splbio();
610 bufq_put(fd->sc_q, bp);
611 callout_stop(&fd->sc_motoroff_ch); /* a good idea */
612 if (fd->sc_active == 0)
613 fdstart(fd);
614 #ifdef DIAGNOSTIC
615 else {
616 struct fdc_softc *fdc =
617 device_private(device_parent(fd->sc_dev));
618 if (fdc->sc_state == DEVIDLE) {
619 printf("fdstrategy: controller inactive\n");
620 fdcstart(fdc);
621 }
622 }
623 #endif
624 splx(s);
625 return;
626
627 done:
628 /* Toss transfer; we're done early. */
629 bp->b_resid = bp->b_bcount;
630 biodone(bp);
631 }
632
633 void
634 fdstart(struct fd_softc *fd)
635 {
636 struct fdc_softc *fdc = device_private(device_parent(fd->sc_dev));
637 int active = fdc->sc_drives.tqh_first != 0;
638
639 /* Link into controller queue. */
640 fd->sc_active = 1;
641 TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain);
642
643 /* If controller not already active, start it. */
644 if (!active)
645 fdcstart(fdc);
646 }
647
648 void
649 fdfinish(struct fd_softc *fd, struct buf *bp)
650 {
651 struct fdc_softc *fdc = device_private(device_parent(fd->sc_dev));
652
653 /*
654 * Move this drive to the end of the queue to give others a `fair'
655 * chance. We only force a switch if N operations are completed while
656 * another drive is waiting to be serviced, since there is a long motor
657 * startup delay whenever we switch.
658 */
659 (void)bufq_get(fd->sc_q);
660 if (fd->sc_drivechain.tqe_next && ++fd->sc_ops >= 8) {
661 fd->sc_ops = 0;
662 TAILQ_REMOVE(&fdc->sc_drives, fd, sc_drivechain);
663 if (bufq_peek(fd->sc_q) != NULL)
664 TAILQ_INSERT_TAIL(&fdc->sc_drives, fd, sc_drivechain);
665 else
666 fd->sc_active = 0;
667 }
668 bp->b_resid = fd->sc_bcount;
669 fd->sc_skip = 0;
670
671 biodone(bp);
672 /* turn off motor 5s from now */
673 callout_reset(&fd->sc_motoroff_ch, 5 * hz, fd_motor_off, fd);
674 fdc->sc_state = DEVIDLE;
675 }
676
677 int
678 fdread(dev_t dev, struct uio *uio, int flags)
679 {
680
681 return (physio(fdstrategy, NULL, dev, B_READ, minphys, uio));
682 }
683
684 int
685 fdwrite(dev_t dev, struct uio *uio, int flags)
686 {
687
688 return (physio(fdstrategy, NULL, dev, B_WRITE, minphys, uio));
689 }
690
691 void
692 fd_set_motor(struct fdc_softc *fdc, int reset)
693 {
694 struct fd_softc *fd;
695 u_char status;
696 int n;
697
698 if ((fd = fdc->sc_drives.tqh_first) != NULL)
699 status = fd->sc_drive;
700 else
701 status = 0;
702 if (!reset)
703 status |= FDO_FRST | FDO_FDMAEN;
704 for (n = 0; n < 4; n++)
705 if ((fd = fdc->sc_fd[n]) && (fd->sc_flags & FD_MOTOR))
706 status |= FDO_MOEN(n);
707 bus_space_write_2(fdc->sc_iot, fdc->sc_ioh, fdout, status);
708 }
709
710 void
711 fd_motor_off(void *arg)
712 {
713 struct fd_softc *fd = arg;
714 int s;
715
716 s = splbio();
717 fd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT);
718 fd_set_motor(device_private(device_parent(fd->sc_dev)), 0);
719 splx(s);
720 }
721
722 void
723 fd_motor_on(void *arg)
724 {
725 struct fd_softc *fd = arg;
726 struct fdc_softc *fdc = device_private(device_parent(fd->sc_dev));
727 int s;
728
729 s = splbio();
730 fd->sc_flags &= ~FD_MOTOR_WAIT;
731 if ((fdc->sc_drives.tqh_first == fd) && (fdc->sc_state == MOTORWAIT))
732 (void) fdcintr(fdc);
733 splx(s);
734 }
735
736 int
737 fdcresult(struct fdc_softc *fdc)
738 {
739 bus_space_tag_t iot = fdc->sc_iot;
740 bus_space_handle_t ioh = fdc->sc_ioh;
741 u_char i;
742 int j = 100000,
743 n = 0;
744
745 for (; j; j--) {
746 i = bus_space_read_1(iot, ioh, fdsts) &
747 (NE7_DIO | NE7_RQM | NE7_CB);
748 if (i == NE7_RQM)
749 return n;
750 if (i == (NE7_DIO | NE7_RQM | NE7_CB)) {
751 if (n >= sizeof(fdc->sc_status)) {
752 log(LOG_ERR, "fdcresult: overrun\n");
753 return -1;
754 }
755 fdc->sc_status[n++] =
756 bus_space_read_1(iot, ioh, fddata);
757 }
758 delay(10);
759 }
760 log(LOG_ERR, "fdcresult: timeout\n");
761 return -1;
762 }
763
764 int
765 out_fdc(bus_space_tag_t iot, bus_space_handle_t ioh, u_char x)
766 {
767 int i = 100000;
768
769 while ((bus_space_read_1(iot, ioh, fdsts) & NE7_DIO) && i-- > 0);
770 if (i <= 0)
771 return -1;
772 while ((bus_space_read_1(iot, ioh, fdsts) & NE7_RQM) == 0 && i-- > 0);
773 if (i <= 0)
774 return -1;
775 bus_space_write_2(iot, ioh, fddata, x);
776 return 0;
777 }
778
779 int
780 fdopen(dev_t dev, int flags, int mode, struct lwp *l)
781 {
782 struct fd_softc *fd;
783 struct fd_type *type;
784
785 fd = device_lookup_private(&fd_cd, FDUNIT(dev));
786 if (fd == NULL)
787 return ENXIO;
788 type = fd_dev_to_type(fd, dev);
789 if (type == NULL)
790 return ENXIO;
791
792 if ((fd->sc_flags & FD_OPEN) != 0 &&
793 memcmp(fd->sc_type, type, sizeof(*type)))
794 return EBUSY;
795
796 fd->sc_type_copy = *type;
797 fd->sc_type = &fd->sc_type_copy;
798 fd->sc_cylin = -1;
799 fd->sc_flags |= FD_OPEN;
800
801 return 0;
802 }
803
804 int
805 fdclose(dev_t dev, int flags, int mode, struct lwp *l)
806 {
807 struct fd_softc *fd = device_lookup_private(&fd_cd, FDUNIT(dev));
808
809 fd->sc_flags &= ~FD_OPEN;
810 fd->sc_opts &= ~(FDOPT_NORETRY|FDOPT_SILENT);
811 return 0;
812 }
813
814 void
815 fdcstart(struct fdc_softc *fdc)
816 {
817
818 #ifdef DIAGNOSTIC
819 /* only got here if controller's drive queue was inactive; should
820 be in idle state */
821 if (fdc->sc_state != DEVIDLE) {
822 printf("fdcstart: not idle\n");
823 return;
824 }
825 #endif
826 (void) fdcintr(fdc);
827 }
828
829 static void
830 fdcpstatus(int n, struct fdc_softc *fdc)
831 {
832 char bits[64];
833
834 switch (n) {
835 case 0:
836 printf("\n");
837 break;
838 case 2:
839 snprintb(bits, sizeof(bits), NE7_ST0BITS, fdc->sc_status[0]);
840 printf(" (st0 %s cyl %d)\n", bits, fdc->sc_status[1]);
841 break;
842 case 7:
843 snprintb(bits, sizeof(bits), NE7_ST0BITS, fdc->sc_status[0]);
844 printf(" (st0 %s", bits);
845 snprintb(bits, sizeof(bits), NE7_ST1BITS, fdc->sc_status[1]);
846 printf(" st1 %s", bits);
847 snprintb(bits, sizeof(bits), NE7_ST2BITS, fdc->sc_status[2]);
848 printf(" st2 %s", bits);
849 printf(" cyl %d head %d sec %d)\n",
850 fdc->sc_status[3], fdc->sc_status[4], fdc->sc_status[5]);
851 break;
852 #ifdef DIAGNOSTIC
853 default:
854 printf("\nfdcstatus: weird size");
855 break;
856 #endif
857 }
858 }
859
860 void
861 fdcstatus(device_t dv, int n, const char *s)
862 {
863 struct fdc_softc *fdc = device_private(device_parent(dv));
864
865 if (n == 0) {
866 out_fdc(fdc->sc_iot, fdc->sc_ioh, NE7CMD_SENSEI);
867 (void) fdcresult(fdc);
868 n = 2;
869 }
870
871 printf("%s: %s", device_xname(dv), s);
872 fdcpstatus(n, fdc);
873 }
874
875 void
876 fdctimeout(void *arg)
877 {
878 struct fdc_softc *fdc = arg;
879 struct fd_softc *fd = fdc->sc_drives.tqh_first;
880 int s;
881
882 s = splbio();
883 #ifdef DEBUG
884 log(LOG_ERR,"fdctimeout: state %d\n", fdc->sc_state);
885 #endif
886 fdcstatus(fd->sc_dev, 0, "timeout");
887
888 if (bufq_peek(fd->sc_q) != NULL)
889 fdc->sc_state++;
890 else
891 fdc->sc_state = DEVIDLE;
892
893 (void) fdcintr(fdc);
894 splx(s);
895 }
896
897 void
898 fdcpseudointr(void *arg)
899 {
900 int s;
901
902 /* Just ensure it has the right spl. */
903 s = splbio();
904 (void) fdcintr(arg);
905 splx(s);
906 }
907
908 int
909 fdcintr(void *arg)
910 {
911 struct fdc_softc *fdc = arg;
912 #define st0 fdc->sc_status[0]
913 #define cyl fdc->sc_status[1]
914 struct fd_softc *fd;
915 struct buf *bp;
916 bus_space_tag_t iot = fdc->sc_iot;
917 bus_space_handle_t ioh = fdc->sc_ioh;
918 int read, head, sec, i, nblks;
919 struct fd_type *type;
920 struct ne7_fd_formb *finfo = NULL;
921
922 loop:
923 /* Is there a drive for the controller to do a transfer with? */
924 fd = fdc->sc_drives.tqh_first;
925 if (fd == NULL) {
926 fdc->sc_state = DEVIDLE;
927 return 1;
928 }
929
930 /* Is there a transfer to this drive? If not, deactivate drive. */
931 bp = bufq_peek(fd->sc_q);
932 if (bp == NULL) {
933 fd->sc_ops = 0;
934 TAILQ_REMOVE(&fdc->sc_drives, fd, sc_drivechain);
935 fd->sc_active = 0;
936 goto loop;
937 }
938
939 if (bp->b_flags & B_FORMAT)
940 finfo = (struct ne7_fd_formb *)bp->b_data;
941
942 switch (fdc->sc_state) {
943 case DEVIDLE:
944 fdc->sc_errors = 0;
945 fd->sc_skip = 0;
946 fd->sc_bcount = bp->b_bcount;
947 fd->sc_blkno = bp->b_blkno / (FDC_BSIZE / DEV_BSIZE);
948 callout_stop(&fd->sc_motoroff_ch);
949 if ((fd->sc_flags & FD_MOTOR_WAIT) != 0) {
950 fdc->sc_state = MOTORWAIT;
951 return 1;
952 }
953 if ((fd->sc_flags & FD_MOTOR) == 0) {
954 /* Turn on the motor, being careful about pairing. */
955 struct fd_softc *ofd = fdc->sc_fd[fd->sc_drive ^ 1];
956 if (ofd && ofd->sc_flags & FD_MOTOR) {
957 callout_stop(&ofd->sc_motoroff_ch);
958 ofd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT);
959 }
960 fd->sc_flags |= FD_MOTOR | FD_MOTOR_WAIT;
961 fd_set_motor(fdc, 0);
962 fdc->sc_state = MOTORWAIT;
963 /* Allow .25s for motor to stabilize. */
964 callout_reset(&fd->sc_motoron_ch, hz / 4,
965 fd_motor_on, fd);
966 return 1;
967 }
968 /* Make sure the right drive is selected. */
969 fd_set_motor(fdc, 0);
970
971 /* fall through */
972 case DOSEEK:
973 doseek:
974 if (fd->sc_cylin == bp->b_cylinder)
975 goto doio;
976
977 #if 1
978 out_fdc(iot, ioh, NE7CMD_CONFIGURE);/* configure command */
979 out_fdc(iot, ioh, 0);
980 out_fdc(iot, ioh, 0x18);
981 out_fdc(iot, ioh, 0);
982 #endif
983 out_fdc(iot, ioh, NE7CMD_SPECIFY);/* specify command */
984 out_fdc(iot, ioh, fd->sc_type->steprate);
985 out_fdc(iot, ioh, 6); /* XXX head load time == 6ms */
986
987 out_fdc(iot, ioh, NE7CMD_SEEK); /* seek function */
988 out_fdc(iot, ioh, fd->sc_drive); /* drive number */
989 out_fdc(iot, ioh, bp->b_cylinder * fd->sc_type->step);
990
991 fd->sc_cylin = -1;
992 fdc->sc_state = SEEKWAIT;
993
994 iostat_seek(fd->sc_dk.dk_stats);
995 disk_busy(&fd->sc_dk);
996
997 callout_reset(&fdc->sc_timo_ch, 4 * hz, fdctimeout, fdc);
998 return 1;
999
1000 case DOIO:
1001 doio:
1002 type = fd->sc_type;
1003 if (finfo)
1004 fd->sc_skip = (char *)&(finfo->fd_formb_cylno(0)) -
1005 (char *)finfo;
1006 sec = fd->sc_blkno % type->seccyl;
1007 nblks = type->seccyl - sec;
1008 nblks = min(nblks, fd->sc_bcount / FDC_BSIZE);
1009 nblks = min(nblks, FDC_MAXIOSIZE / FDC_BSIZE);
1010 fd->sc_nblks = nblks;
1011 fd->sc_nbytes = finfo ? bp->b_bcount : nblks * FDC_BSIZE;
1012 head = sec / type->sectrac;
1013 sec -= head * type->sectrac;
1014 #ifdef DIAGNOSTIC
1015 {daddr_t block;
1016 block = (fd->sc_cylin * type->heads + head) * type->sectrac + sec;
1017 if (block != fd->sc_blkno) {
1018 printf("fdcintr: block %" PRId64
1019 " != blkno %" PRId64 "\n",
1020 block, fd->sc_blkno);
1021 #ifdef DDB
1022 Debugger();
1023 #endif
1024 }}
1025 #endif
1026 read = bp->b_flags & B_READ;
1027 if (read) {
1028 fdc->sc_fh.fh_func = floppy_read_fiq;
1029 fdc->sc_fh.fh_size = floppy_read_fiq_end -
1030 floppy_read_fiq;
1031 } else {
1032 fdc->sc_fh.fh_func = floppy_write_fiq;
1033 fdc->sc_fh.fh_size = floppy_read_fiq_end -
1034 floppy_read_fiq;
1035 }
1036 fdc->sc_fh.fh_flags = 0;
1037 fdc->sc_fh.fh_regs = &fdc->sc_fr;
1038 fdc->sc_fr.fr_r9 = IOMD_BASE + (IOMD_FIQRQ << 2);
1039 fdc->sc_fr.fr_r10 = fd->sc_nbytes;
1040 fdc->sc_fr.fr_r11 =
1041 (u_int)((uintptr_t)bp->b_data + fd->sc_skip);
1042 fdc->sc_fr.fr_r12 = fdc->sc_drq;
1043 #ifdef FD_DEBUG
1044 printf("fdc-doio:r9=%x r10=%x r11=%x r12=%x data=%x skip=%x\n",
1045 fdc->sc_fr.fr_r9, fdc->sc_fr.fh_r10, fdc->sc_fr.fh_r11,
1046 fdc->sc_fr.fh_r12, (u_int)bp->b_data, fd->sc_skip);
1047 #endif
1048 if (fiq_claim(&fdc->sc_fh) == -1)
1049 panic("%s: Cannot claim FIQ vector",
1050 device_xname(fdc->sc_dev));
1051 IOMD_WRITE_BYTE(IOMD_FIQMSK, 0x01);
1052 bus_space_write_2(iot, ioh, fdctl, type->rate);
1053 #ifdef FD_DEBUG
1054 printf("fdcintr: %s drive %d track %d head %d sec %d nblks %d\n",
1055 read ? "read" : "write", fd->sc_drive, fd->sc_cylin,
1056 head, sec, nblks);
1057 #endif
1058 if (finfo) {
1059 /* formatting */
1060 if (out_fdc(iot, ioh, NE7CMD_FORMAT) < 0) {
1061 fdc->sc_errors = 4;
1062 fdcretry(fdc);
1063 goto loop;
1064 }
1065 out_fdc(iot, ioh, (head << 2) | fd->sc_drive);
1066 out_fdc(iot, ioh, finfo->fd_formb_secshift);
1067 out_fdc(iot, ioh, finfo->fd_formb_nsecs);
1068 out_fdc(iot, ioh, finfo->fd_formb_gaplen);
1069 out_fdc(iot, ioh, finfo->fd_formb_fillbyte);
1070 } else {
1071 if (read)
1072 out_fdc(iot, ioh, NE7CMD_READ); /* READ */
1073 else
1074 out_fdc(iot, ioh, NE7CMD_WRITE); /* WRITE */
1075 out_fdc(iot, ioh, (head << 2) | fd->sc_drive);
1076 out_fdc(iot, ioh, fd->sc_cylin); /* track */
1077 out_fdc(iot, ioh, head);
1078 out_fdc(iot, ioh, sec + 1); /* sector +1 */
1079 out_fdc(iot, ioh, type->secsize);/* sector size */
1080 out_fdc(iot, ioh, type->sectrac);/* sectors/track */
1081 out_fdc(iot, ioh, type->gap1); /* gap1 size */
1082 out_fdc(iot, ioh, type->datalen);/* data length */
1083 }
1084 fdc->sc_state = IOCOMPLETE;
1085
1086 disk_busy(&fd->sc_dk);
1087
1088 /* allow 2 seconds for operation */
1089 callout_reset(&fdc->sc_timo_ch, 2 * hz, fdctimeout, fdc);
1090 return 1; /* will return later */
1091
1092 case SEEKWAIT:
1093 callout_stop(&fdc->sc_timo_ch);
1094 fdc->sc_state = SEEKCOMPLETE;
1095 /* allow 1/50 second for heads to settle */
1096 #if 0
1097 callout_reset(&fdc->sc_intr_ch, hz / 50, fdcpseudointr, fdc);
1098 #endif
1099 return 1;
1100
1101 case SEEKCOMPLETE:
1102 /* no data on seek */
1103 disk_unbusy(&fd->sc_dk, 0, 0);
1104
1105 /* Make sure seek really happened. */
1106 out_fdc(iot, ioh, NE7CMD_SENSEI);
1107 if (fdcresult(fdc) != 2 || (st0 & 0xf8) != 0x20 ||
1108 cyl != bp->b_cylinder * fd->sc_type->step) {
1109 #ifdef FD_DEBUG
1110 fdcstatus(fd->sc_dev, 2, "seek failed");
1111 #endif
1112 fdcretry(fdc);
1113 goto loop;
1114 }
1115 fd->sc_cylin = bp->b_cylinder;
1116 goto doio;
1117
1118 case IOTIMEDOUT:
1119 fiq_release(&fdc->sc_fh);
1120 IOMD_WRITE_BYTE(IOMD_FIQMSK, 0x00);
1121 case SEEKTIMEDOUT:
1122 case RECALTIMEDOUT:
1123 case RESETTIMEDOUT:
1124 fdcretry(fdc);
1125 goto loop;
1126
1127 case IOCOMPLETE: /* IO DONE, post-analyze */
1128 callout_stop(&fdc->sc_timo_ch);
1129
1130 disk_unbusy(&fd->sc_dk, (bp->b_bcount - bp->b_resid),
1131 (bp->b_flags & B_READ));
1132
1133 if (fdcresult(fdc) != 7 || (st0 & 0xf8) != 0) {
1134 fiq_release(&fdc->sc_fh);
1135 IOMD_WRITE_BYTE(IOMD_FIQMSK, 0x00);
1136 #ifdef FD_DEBUG
1137 fdcstatus(fd->sc_dev, 7, bp->b_flags & B_READ ?
1138 "read failed" : "write failed");
1139 printf("blkno %d nblks %d\n",
1140 fd->sc_blkno, fd->sc_nblks);
1141 #endif
1142 fdcretry(fdc);
1143 goto loop;
1144 }
1145 fiq_release(&fdc->sc_fh);
1146 IOMD_WRITE_BYTE(IOMD_FIQMSK, 0x00);
1147 if (fdc->sc_errors) {
1148 #if 0
1149 diskerr(bp, "fd", "soft error (corrected)", LOG_PRINTF,
1150 fd->sc_skip / FDC_BSIZE, (struct disklabel *)NULL);
1151 printf("\n");
1152 #endif
1153 fdc->sc_errors = 0;
1154 }
1155 fd->sc_blkno += fd->sc_nblks;
1156 fd->sc_skip += fd->sc_nbytes;
1157 fd->sc_bcount -= fd->sc_nbytes;
1158 if (!finfo && fd->sc_bcount > 0) {
1159 bp->b_cylinder = fd->sc_blkno / fd->sc_type->seccyl;
1160 goto doseek;
1161 }
1162 fdfinish(fd, bp);
1163 goto loop;
1164
1165 case DORESET:
1166 /* try a reset, keep motor on */
1167 fd_set_motor(fdc, 1);
1168 delay(100);
1169 fd_set_motor(fdc, 0);
1170 fdc->sc_state = RESETCOMPLETE;
1171 callout_reset(&fdc->sc_timo_ch, hz / 2, fdctimeout, fdc);
1172 return 1; /* will return later */
1173
1174 case RESETCOMPLETE:
1175 callout_stop(&fdc->sc_timo_ch);
1176 /* clear the controller output buffer */
1177 for (i = 0; i < 4; i++) {
1178 out_fdc(iot, ioh, NE7CMD_SENSEI);
1179 (void) fdcresult(fdc);
1180 }
1181
1182 /* fall through */
1183 case DORECAL:
1184 out_fdc(iot, ioh, NE7CMD_RECAL); /* recalibrate function */
1185 out_fdc(iot, ioh, fd->sc_drive);
1186 fdc->sc_state = RECALWAIT;
1187 callout_reset(&fdc->sc_timo_ch, 5 * hz, fdctimeout, fdc);
1188 return 1; /* will return later */
1189
1190 case RECALWAIT:
1191 callout_stop(&fdc->sc_timo_ch);
1192 fdc->sc_state = RECALCOMPLETE;
1193 /* allow 1/30 second for heads to settle */
1194 #if 0
1195 callout_reset(&fdc->sc_intr_ch, hz / 30, fdcpseudointr, fdc);
1196 #endif
1197 return 1; /* will return later */
1198
1199 case RECALCOMPLETE:
1200 out_fdc(iot, ioh, NE7CMD_SENSEI);
1201 if (fdcresult(fdc) != 2 || (st0 & 0xf8) != 0x20 || cyl != 0) {
1202 #ifdef FD_DEBUG
1203 fdcstatus(fd->sc_dev, 2, "recalibrate failed");
1204 #endif
1205 fdcretry(fdc);
1206 goto loop;
1207 }
1208 fd->sc_cylin = 0;
1209 goto doseek;
1210
1211 case MOTORWAIT:
1212 if (fd->sc_flags & FD_MOTOR_WAIT)
1213 return 1; /* time's not up yet */
1214 goto doseek;
1215
1216 default:
1217 fdcstatus(fd->sc_dev, 0, "stray interrupt");
1218 return 1;
1219 }
1220 #ifdef DIAGNOSTIC
1221 panic("fdcintr: impossible");
1222 #endif
1223 #undef st0
1224 #undef cyl
1225 }
1226
1227 void
1228 fdcretry(struct fdc_softc *fdc)
1229 {
1230 struct fd_softc *fd;
1231 struct buf *bp;
1232
1233 fd = fdc->sc_drives.tqh_first;
1234 bp = bufq_peek(fd->sc_q);
1235
1236 if (fd->sc_opts & FDOPT_NORETRY)
1237 goto fail;
1238 switch (fdc->sc_errors) {
1239 case 0:
1240 /* try again */
1241 fdc->sc_state = DOSEEK;
1242 break;
1243
1244 case 1: case 2: case 3:
1245 /* didn't work; try recalibrating */
1246 fdc->sc_state = DORECAL;
1247 break;
1248
1249 case 4:
1250 /* still no go; reset the bastard */
1251 fdc->sc_state = DORESET;
1252 break;
1253
1254 default:
1255 fail:
1256 if ((fd->sc_opts & FDOPT_SILENT) == 0) {
1257 diskerr(bp, "fd", "hard error", LOG_PRINTF,
1258 fd->sc_skip / FDC_BSIZE,
1259 (struct disklabel *)NULL);
1260 fdcpstatus(7, fdc);
1261 }
1262
1263 bp->b_error = EIO;
1264 fdfinish(fd, bp);
1265 }
1266 fdc->sc_errors++;
1267 }
1268
1269 int
1270 fdioctl(dev_t dev, u_long cmd, void *addr, int flag, struct lwp *l)
1271 {
1272 struct fd_softc *fd = device_lookup_private(&fd_cd, FDUNIT(dev));
1273 struct fdformat_parms *form_parms;
1274 struct fdformat_cmd *form_cmd;
1275 struct ne7_fd_formb *fd_formb;
1276 struct disklabel buffer;
1277 int error;
1278 unsigned int scratch;
1279 int il[FD_MAX_NSEC + 1];
1280 register int i, j;
1281
1282 switch (cmd) {
1283 case DIOCGDINFO:
1284 memset(&buffer, 0, sizeof(buffer));
1285
1286 buffer.d_secpercyl = fd->sc_type->seccyl;
1287 buffer.d_type = DTYPE_FLOPPY;
1288 buffer.d_secsize = FDC_BSIZE;
1289
1290 if (readdisklabel(dev, fdstrategy, &buffer, NULL) != NULL)
1291 return EINVAL;
1292
1293 *(struct disklabel *)addr = buffer;
1294 return 0;
1295
1296 case DIOCWLABEL:
1297 if ((flag & FWRITE) == 0)
1298 return EBADF;
1299 /* XXX do something */
1300 return 0;
1301
1302 case DIOCWDINFO:
1303 if ((flag & FWRITE) == 0)
1304 return EBADF;
1305
1306 error = setdisklabel(&buffer, (struct disklabel *)addr, 0, NULL);
1307 if (error)
1308 return error;
1309
1310 error = writedisklabel(dev, fdstrategy, &buffer, NULL);
1311 return error;
1312
1313 case FDIOCGETFORMAT:
1314 form_parms = (struct fdformat_parms *)addr;
1315 form_parms->fdformat_version = FDFORMAT_VERSION;
1316 form_parms->nbps = 128 * (1 << fd->sc_type->secsize);
1317 form_parms->ncyl = fd->sc_type->cyls;
1318 form_parms->nspt = fd->sc_type->sectrac;
1319 form_parms->ntrk = fd->sc_type->heads;
1320 form_parms->stepspercyl = fd->sc_type->step;
1321 form_parms->gaplen = fd->sc_type->gap2;
1322 form_parms->fillbyte = fd->sc_type->fillbyte;
1323 form_parms->interleave = fd->sc_type->interleave;
1324 switch (fd->sc_type->rate) {
1325 case FDC_500KBPS:
1326 form_parms->xfer_rate = 500 * 1024;
1327 break;
1328 case FDC_300KBPS:
1329 form_parms->xfer_rate = 300 * 1024;
1330 break;
1331 case FDC_250KBPS:
1332 form_parms->xfer_rate = 250 * 1024;
1333 break;
1334 default:
1335 return EINVAL;
1336 }
1337 return 0;
1338
1339 case FDIOCSETFORMAT:
1340 if((flag & FWRITE) == 0)
1341 return EBADF; /* must be opened for writing */
1342 form_parms = (struct fdformat_parms *)addr;
1343 if (form_parms->fdformat_version != FDFORMAT_VERSION)
1344 return EINVAL; /* wrong version of formatting prog */
1345
1346 scratch = form_parms->nbps >> 7;
1347 if ((form_parms->nbps & 0x7f) || ffs(scratch) == 0 ||
1348 scratch & ~(1 << (ffs(scratch)-1)))
1349 /* not a power-of-two multiple of 128 */
1350 return EINVAL;
1351
1352 switch (form_parms->xfer_rate) {
1353 case 500 * 1024:
1354 fd->sc_type->rate = FDC_500KBPS;
1355 break;
1356 case 300 * 1024:
1357 fd->sc_type->rate = FDC_300KBPS;
1358 break;
1359 case 250 * 1024:
1360 fd->sc_type->rate = FDC_250KBPS;
1361 break;
1362 default:
1363 return EINVAL;
1364 }
1365
1366 if (form_parms->nspt > FD_MAX_NSEC ||
1367 form_parms->fillbyte > 0xff ||
1368 form_parms->interleave > 0xff)
1369 return EINVAL;
1370 fd->sc_type->sectrac = form_parms->nspt;
1371 if (form_parms->ntrk != 2 && form_parms->ntrk != 1)
1372 return EINVAL;
1373 fd->sc_type->heads = form_parms->ntrk;
1374 fd->sc_type->seccyl = form_parms->nspt * form_parms->ntrk;
1375 fd->sc_type->secsize = ffs(scratch)-1;
1376 fd->sc_type->gap2 = form_parms->gaplen;
1377 fd->sc_type->cyls = form_parms->ncyl;
1378 fd->sc_type->size = fd->sc_type->seccyl * form_parms->ncyl *
1379 form_parms->nbps / DEV_BSIZE;
1380 fd->sc_type->step = form_parms->stepspercyl;
1381 fd->sc_type->fillbyte = form_parms->fillbyte;
1382 fd->sc_type->interleave = form_parms->interleave;
1383 return 0;
1384
1385 case FDIOCFORMAT_TRACK:
1386 if((flag & FWRITE) == 0)
1387 return EBADF; /* must be opened for writing */
1388 form_cmd = (struct fdformat_cmd *)addr;
1389 if (form_cmd->formatcmd_version != FDFORMAT_VERSION)
1390 return EINVAL; /* wrong version of formatting prog */
1391
1392 if (form_cmd->head >= fd->sc_type->heads ||
1393 form_cmd->cylinder >= fd->sc_type->cyls) {
1394 return EINVAL;
1395 }
1396
1397 fd_formb = malloc(sizeof(struct ne7_fd_formb),
1398 M_TEMP, M_NOWAIT);
1399 if(fd_formb == 0)
1400 return ENOMEM;
1401
1402
1403 fd_formb->head = form_cmd->head;
1404 fd_formb->cyl = form_cmd->cylinder;
1405 fd_formb->transfer_rate = fd->sc_type->rate;
1406 fd_formb->fd_formb_secshift = fd->sc_type->secsize;
1407 fd_formb->fd_formb_nsecs = fd->sc_type->sectrac;
1408 fd_formb->fd_formb_gaplen = fd->sc_type->gap2;
1409 fd_formb->fd_formb_fillbyte = fd->sc_type->fillbyte;
1410
1411 memset(il, 0, sizeof il);
1412 for (j = 0, i = 1; i <= fd_formb->fd_formb_nsecs; i++) {
1413 while (il[(j%fd_formb->fd_formb_nsecs)+1])
1414 j++;
1415 il[(j%fd_formb->fd_formb_nsecs)+1] = i;
1416 j += fd->sc_type->interleave;
1417 }
1418 for (i = 0; i < fd_formb->fd_formb_nsecs; i++) {
1419 fd_formb->fd_formb_cylno(i) = form_cmd->cylinder;
1420 fd_formb->fd_formb_headno(i) = form_cmd->head;
1421 fd_formb->fd_formb_secno(i) = il[i+1];
1422 fd_formb->fd_formb_secsize(i) = fd->sc_type->secsize;
1423 }
1424
1425 error = fdformat(dev, fd_formb, l);
1426 free(fd_formb, M_TEMP);
1427 return error;
1428
1429 case FDIOCGETOPTS: /* get drive options */
1430 *(int *)addr = fd->sc_opts;
1431 return 0;
1432
1433 case FDIOCSETOPTS: /* set drive options */
1434 fd->sc_opts = *(int *)addr;
1435 return 0;
1436
1437 default:
1438 return ENOTTY;
1439 }
1440
1441 #ifdef DIAGNOSTIC
1442 panic("fdioctl: impossible");
1443 #endif
1444 }
1445
1446 int
1447 fdformat(dev_t dev, struct ne7_fd_formb *finfo, struct lwp *l)
1448 {
1449 int rv = 0;
1450 struct fd_softc *fd = device_lookup_private(&fd_cd,FDUNIT(dev));
1451 struct fd_type *type = fd->sc_type;
1452 struct buf *bp;
1453
1454 /* set up a buffer header for fdstrategy() */
1455 bp = getiobuf(NULL, false);
1456 if(bp == 0)
1457 return ENOBUFS;
1458 bp->b_flags = B_PHYS | B_FORMAT;
1459 bp->b_cflags |= BC_BUSY;
1460 bp->b_proc = l->l_proc;
1461 bp->b_dev = dev;
1462
1463 /*
1464 * calculate a fake blkno, so fdstrategy() would initiate a
1465 * seek to the requested cylinder
1466 */
1467 bp->b_blkno = (finfo->cyl * (type->sectrac * type->heads)
1468 + finfo->head * type->sectrac) * FDC_BSIZE / DEV_BSIZE;
1469
1470 bp->b_bcount = sizeof(struct fd_idfield_data) * finfo->fd_formb_nsecs;
1471 bp->b_data = (void *)finfo;
1472
1473 #ifdef DEBUG
1474 printf("fdformat: blkno %llx count %x\n",
1475 (unsigned long long)bp->b_blkno, bp->b_bcount);
1476 #endif
1477
1478 /* now do the format */
1479 fdstrategy(bp);
1480
1481 /* ...and wait for it to complete */
1482 /* XXX very dodgy */
1483 mutex_enter(bp->b_objlock);
1484 while (!(bp->b_oflags & BO_DONE)) {
1485 rv = cv_timedwait(&bp->b_done, bp->b_objlock, 20 * hz);
1486 if (rv == EWOULDBLOCK)
1487 break;
1488 }
1489 mutex_exit(bp->b_objlock);
1490
1491 if (rv == EWOULDBLOCK) {
1492 /* timed out */
1493 rv = EIO;
1494 biodone(bp);
1495 } else if (bp->b_error != 0)
1496 rv = bp->b_error;
1497 putiobuf(bp);
1498 return rv;
1499 }
1500
1501 #include <dev/md.h>
1502
1503 int load_memory_disc_from_floppy(struct md_conf *md, dev_t dev);
1504
1505 int
1506 load_memory_disc_from_floppy(struct md_conf *md, dev_t dev)
1507 {
1508 struct buf *bp;
1509 int loop;
1510 int s;
1511 int type;
1512 int floppysize;
1513
1514 if (bdevsw_lookup(dev) != &fd_bdevsw)
1515 return(EINVAL);
1516
1517 if (md->md_type == MD_UNCONFIGURED || md->md_addr == 0)
1518 return(EBUSY);
1519
1520 type = FDTYPE(dev) - 1;
1521 if (type < 0) type = 0;
1522 floppysize = fd_types[type].size << (fd_types[type].secsize + 7);
1523
1524 if (md->md_size < floppysize) {
1525 printf("Memory disc is not big enough for floppy image\n");
1526 return(EINVAL);
1527 }
1528
1529 /* We have the memory disk ! */
1530
1531 printf("Loading memory disc : %4dK ", 0);
1532
1533 /* obtain a buffer */
1534
1535 bp = geteblk(fd_types[type].sectrac * DEV_BSIZE);
1536
1537 /* request no partition relocation by driver on I/O operations */
1538
1539 bp->b_dev = dev;
1540
1541 s = splbio();
1542
1543 if (fdopen(bp->b_dev, 0, 0, curlwp) != 0) {
1544 brelse(bp, 0);
1545 printf("Cannot open floppy device\n");
1546 return(EINVAL);
1547 }
1548
1549 for (loop = 0;
1550 loop < (floppysize / DEV_BSIZE / fd_types[type].sectrac);
1551 ++loop) {
1552 printf("\x08\x08\x08\x08\x08\x08%4dK ",
1553 loop * fd_types[type].sectrac * DEV_BSIZE / 1024);
1554 bp->b_blkno = loop * fd_types[type].sectrac;
1555 bp->b_bcount = fd_types[type].sectrac * DEV_BSIZE;
1556 bp->b_flags |= B_READ;
1557 bp->b_error = 0;
1558 bp->b_resid = 0;
1559 fdstrategy(bp);
1560
1561 if (biowait(bp))
1562 panic("Cannot load floppy image");
1563
1564 memcpy((char *)md->md_addr + loop * fd_types[type].sectrac
1565 * DEV_BSIZE, (void *)bp->b_data,
1566 fd_types[type].sectrac * DEV_BSIZE);
1567 }
1568 printf("\x08\x08\x08\x08\x08\x08%4dK done\n",
1569 loop * fd_types[type].sectrac * DEV_BSIZE / 1024);
1570
1571 fdclose(bp->b_dev, 0, 0, curlwp);
1572
1573 brelse(bp, 0);
1574
1575 splx(s);
1576 return(0);
1577 }
1578