This source file includes following definitions.
- fdprobe
- fdattach
- fd_nvtotype
- fd_dev_to_type
- fdstrategy
- fdstart
- fdfinish
- fdread
- fdwrite
- fd_set_motor
- fd_motor_off
- fd_motor_on
- fdopen
- fdclose
- fdsize
- fddump
- fdintr
- fdtimeout
- fdretry
- fdioctl
- fdformat
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 #include <sys/param.h>
46 #include <sys/systm.h>
47 #include <sys/kernel.h>
48 #include <sys/file.h>
49 #include <sys/ioctl.h>
50 #include <sys/device.h>
51 #include <sys/disklabel.h>
52 #include <sys/dkstat.h>
53 #include <sys/disk.h>
54 #include <sys/buf.h>
55 #include <sys/malloc.h>
56 #include <sys/uio.h>
57 #include <sys/mtio.h>
58 #include <sys/proc.h>
59 #include <sys/syslog.h>
60 #include <sys/queue.h>
61 #include <sys/timeout.h>
62
63 #include <machine/cpu.h>
64 #include <machine/bus.h>
65 #include <machine/conf.h>
66 #include <machine/intr.h>
67 #include <machine/ioctl_fd.h>
68
69 #include <dev/isa/isavar.h>
70 #include <dev/isa/isadmavar.h>
71 #include <dev/isa/fdreg.h>
72
73 #if defined(__i386__) || defined(__amd64__)
74 #include <i386/isa/nvram.h>
75 #endif
76
77 #include <dev/isa/fdlink.h>
78
79
80 #define B_FORMAT B_XXX
81
82
83
84
85 struct fd_type fd_types[] = {
86 { 18,2,36,2,0xff,0xcf,0x1b,0x6c,80,2880,1,FDC_500KBPS,"1.44MB" },
87 { 15,2,30,2,0xff,0xdf,0x1b,0x54,80,2400,1,FDC_500KBPS, "1.2MB" },
88 { 9,2,18,2,0xff,0xdf,0x23,0x50,40, 720,2,FDC_300KBPS, "360KB/AT" },
89 { 9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,1,FDC_250KBPS, "360KB/PC" },
90 { 9,2,18,2,0xff,0xdf,0x2a,0x50,80,1440,1,FDC_250KBPS, "720KB" },
91 { 9,2,18,2,0xff,0xdf,0x23,0x50,80,1440,1,FDC_300KBPS, "720KB/x" },
92 { 9,2,18,2,0xff,0xdf,0x2a,0x50,40, 720,2,FDC_250KBPS, "360KB/x" },
93 { 36,2,72,2,0xff,0xaf,0x1b,0x54,80,5760,1,FDC_500KBPS,"2.88MB" },
94 { 8,2,16,3,0xff,0xdf,0x35,0x74,77,1232,1,FDC_500KBPS,"1.2MB/[1024bytes/sector]" }
95 };
96
97
98 struct fd_softc {
99 struct device sc_dev;
100 struct disk sc_dk;
101
102 struct fd_type *sc_deftype;
103 struct fd_type *sc_type;
104
105 daddr64_t sc_blkno;
106 int sc_bcount;
107 int sc_opts;
108 int sc_skip;
109 int sc_nblks;
110 int sc_nbytes;
111
112 int sc_drive;
113 int sc_flags;
114 #define FD_OPEN 0x01
115 #define FD_MOTOR 0x02
116 #define FD_MOTOR_WAIT 0x04
117 int sc_cylin;
118
119 void *sc_sdhook;
120
121 TAILQ_ENTRY(fd_softc) sc_drivechain;
122 int sc_ops;
123 struct buf sc_q;
124 struct timeout fd_motor_on_to;
125 struct timeout fd_motor_off_to;
126 struct timeout fdtimeout_to;
127 };
128
129
130 int fdprobe(struct device *, void *, void *);
131 void fdattach(struct device *, struct device *, void *);
132
133 struct cfattach fd_ca = {
134 sizeof(struct fd_softc), fdprobe, fdattach
135 };
136
137 struct cfdriver fd_cd = {
138 NULL, "fd", DV_DISK
139 };
140
141 void fdgetdisklabel(struct fd_softc *);
142 int fd_get_parms(struct fd_softc *);
143 void fdstrategy(struct buf *);
144 void fdstart(struct fd_softc *);
145 int fdintr(struct fdc_softc *);
146
147 struct dkdriver fddkdriver = { fdstrategy };
148
149 void fd_set_motor(struct fdc_softc *fdc, int reset);
150 void fd_motor_off(void *arg);
151 void fd_motor_on(void *arg);
152 void fdfinish(struct fd_softc *fd, struct buf *bp);
153 int fdformat(dev_t, struct fd_formb *, struct proc *);
154 static __inline struct fd_type *fd_dev_to_type(struct fd_softc *, dev_t);
155 void fdretry(struct fd_softc *);
156 void fdtimeout(void *);
157
158 int
159 fdprobe(parent, match, aux)
160 struct device *parent;
161 void *match, *aux;
162 {
163 struct fdc_softc *fdc = (void *)parent;
164 struct cfdata *cf = match;
165 struct fdc_attach_args *fa = aux;
166 int drive = fa->fa_drive;
167 bus_space_tag_t iot = fdc->sc_iot;
168 bus_space_handle_t ioh = fdc->sc_ioh;
169 int n;
170
171 if (cf->cf_loc[0] != -1 && cf->cf_loc[0] != drive)
172 return 0;
173
174
175
176
177
178 if (cf->cf_loc[0] == -1 && drive >= 2)
179 return 0;
180
181
182
183
184 fa->fa_flags = cf->cf_flags;
185
186
187 bus_space_write_1(iot, ioh, fdout, drive | FDO_FRST | FDO_MOEN(drive));
188
189 delay(250000);
190 out_fdc(iot, ioh, NE7CMD_RECAL);
191 out_fdc(iot, ioh, drive);
192
193 delay(2000000);
194 out_fdc(iot, ioh, NE7CMD_SENSEI);
195 n = fdcresult(fdc);
196 #ifdef FD_DEBUG
197 {
198 int i;
199 printf("fdprobe: status");
200 for (i = 0; i < n; i++)
201 printf(" %x", fdc->sc_status[i]);
202 printf("\n");
203 }
204 #endif
205
206
207 delay(250000);
208 bus_space_write_1(iot, ioh, fdout, FDO_FRST);
209
210
211 if (!(fa->fa_flags & 0x20) && (n != 2 || (fdc->sc_status[0] & 0xf8) != 0x20))
212 return 0;
213
214 return 1;
215 }
216
217
218
219
220 void
221 fdattach(parent, self, aux)
222 struct device *parent, *self;
223 void *aux;
224 {
225 struct fdc_softc *fdc = (void *)parent;
226 struct fd_softc *fd = (void *)self;
227 struct fdc_attach_args *fa = aux;
228 struct fd_type *type = fa->fa_deftype;
229 int drive = fa->fa_drive;
230
231 if (!type || (fa->fa_flags & 0x10)) {
232
233 switch (fa->fa_flags & 0x07) {
234 case 1:
235 type = &fd_types[7];
236 break;
237 case 2:
238 type = &fd_types[0];
239 break;
240 case 3:
241 type = &fd_types[1];
242 break;
243 case 4:
244 type = &fd_types[4];
245 break;
246 case 5:
247 type = &fd_types[3];
248 break;
249 case 6:
250 type = &fd_types[8];
251 break;
252 #ifdef __alpha__
253 default:
254
255
256
257 type = &fd_types[0];
258 #endif
259 }
260 }
261
262 if (type)
263 printf(": %s %d cyl, %d head, %d sec\n", type->name,
264 type->tracks, type->heads, type->sectrac);
265 else
266 printf(": density unknown\n");
267
268 fd->sc_cylin = -1;
269 fd->sc_drive = drive;
270 fd->sc_deftype = type;
271 fdc->sc_type[drive] = FDC_TYPE_DISK;
272 fdc->sc_link.fdlink.sc_fd[drive] = fd;
273
274
275
276
277 fd->sc_dk.dk_name = fd->sc_dev.dv_xname;
278 fd->sc_dk.dk_driver = &fddkdriver;
279 disk_attach(&fd->sc_dk);
280
281
282 fd->sc_sdhook = shutdownhook_establish(fd_motor_off, fd);
283
284
285 timeout_set(&fd->fd_motor_on_to, fd_motor_on, fd);
286 timeout_set(&fd->fd_motor_off_to, fd_motor_off, fd);
287 timeout_set(&fd->fdtimeout_to, fdtimeout, fd);
288 }
289
290
291
292
293
294 struct fd_type *
295 fd_nvtotype(fdc, nvraminfo, drive)
296 char *fdc;
297 int nvraminfo, drive;
298 {
299 #ifdef __alpha__
300
301
302
303 return &fd_types[0];
304 #else
305 int type;
306
307 type = (drive == 0 ? nvraminfo : nvraminfo << 4) & 0xf0;
308 switch (type) {
309 case NVRAM_DISKETTE_NONE:
310 return NULL;
311 case NVRAM_DISKETTE_12M:
312 return &fd_types[1];
313 case NVRAM_DISKETTE_TYPE5:
314 case NVRAM_DISKETTE_TYPE6:
315 return &fd_types[7];
316 case NVRAM_DISKETTE_144M:
317 return &fd_types[0];
318 case NVRAM_DISKETTE_360K:
319 return &fd_types[3];
320 case NVRAM_DISKETTE_720K:
321 return &fd_types[4];
322 default:
323 printf("%s: drive %d: unknown device type 0x%x\n",
324 fdc, drive, type);
325 return NULL;
326 }
327 #endif
328 }
329
330 static __inline struct fd_type *
331 fd_dev_to_type(fd, dev)
332 struct fd_softc *fd;
333 dev_t dev;
334 {
335 int type = FDTYPE(dev);
336
337 if (type > (sizeof(fd_types) / sizeof(fd_types[0])))
338 return NULL;
339 return type ? &fd_types[type - 1] : fd->sc_deftype;
340 }
341
342 void
343 fdstrategy(bp)
344 register struct buf *bp;
345 {
346 struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(bp->b_dev)];
347 int sz;
348 int s;
349 int fd_bsize = FD_BSIZE(fd);
350 int bf = fd_bsize / DEV_BSIZE;
351
352
353 if (bp->b_blkno < 0 ||
354 (((bp->b_blkno % bf) != 0 ||
355 (bp->b_bcount % fd_bsize) != 0) &&
356 (bp->b_flags & B_FORMAT) == 0)) {
357 bp->b_error = EINVAL;
358 goto bad;
359 }
360
361
362 if (bp->b_bcount == 0)
363 goto done;
364
365 sz = howmany(bp->b_bcount, DEV_BSIZE);
366
367 if (bp->b_blkno + sz > fd->sc_type->size * bf) {
368 sz = fd->sc_type->size * bf - bp->b_blkno;
369 if (sz == 0)
370
371 goto done;
372 if (sz < 0) {
373
374 bp->b_error = EINVAL;
375 goto bad;
376 }
377
378 bp->b_bcount = sz << DEV_BSHIFT;
379 }
380
381 bp->b_cylinder = bp->b_blkno / (fd_bsize / DEV_BSIZE) / fd->sc_type->seccyl;
382
383 #ifdef FD_DEBUG
384 printf("fdstrategy: b_blkno %d b_bcount %d blkno %d cylin %d sz %d\n",
385 bp->b_blkno, bp->b_bcount, fd->sc_blkno, bp->b_cylinder, sz);
386 #endif
387
388
389 s = splbio();
390 disksort(&fd->sc_q, bp);
391 timeout_del(&fd->fd_motor_off_to);
392 if (!fd->sc_q.b_active)
393 fdstart(fd);
394 #ifdef DIAGNOSTIC
395 else {
396 struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
397 if (fdc->sc_state == DEVIDLE) {
398 printf("fdstrategy: controller inactive\n");
399 fdcstart(fdc);
400 }
401 }
402 #endif
403 splx(s);
404 return;
405
406 bad:
407 bp->b_flags |= B_ERROR;
408 done:
409
410 bp->b_resid = bp->b_bcount;
411 s = splbio();
412 biodone(bp);
413 splx(s);
414 }
415
416 void
417 fdstart(fd)
418 struct fd_softc *fd;
419 {
420 struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
421 int active = !TAILQ_EMPTY(&fdc->sc_link.fdlink.sc_drives);
422
423
424 fd->sc_q.b_active = 1;
425 TAILQ_INSERT_TAIL(&fdc->sc_link.fdlink.sc_drives, fd, sc_drivechain);
426
427
428 if (!active)
429 fdcstart(fdc);
430 }
431
432 void
433 fdfinish(fd, bp)
434 struct fd_softc *fd;
435 struct buf *bp;
436 {
437 struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
438
439 splassert(IPL_BIO);
440
441
442
443
444
445
446
447 if (TAILQ_NEXT(fd, sc_drivechain) != NULL && ++fd->sc_ops >= 8) {
448 fd->sc_ops = 0;
449 TAILQ_REMOVE(&fdc->sc_link.fdlink.sc_drives, fd, sc_drivechain);
450 if (bp->b_actf) {
451 TAILQ_INSERT_TAIL(&fdc->sc_link.fdlink.sc_drives, fd,
452 sc_drivechain);
453 } else
454 fd->sc_q.b_active = 0;
455 }
456 bp->b_resid = fd->sc_bcount;
457 fd->sc_skip = 0;
458 fd->sc_q.b_actf = bp->b_actf;
459
460 biodone(bp);
461
462 timeout_add(&fd->fd_motor_off_to, 5 * hz);
463 fdc->sc_state = DEVIDLE;
464 }
465
466 int
467 fdread(dev, uio, flags)
468 dev_t dev;
469 struct uio *uio;
470 int flags;
471 {
472
473 return (physio(fdstrategy, NULL, dev, B_READ, minphys, uio));
474 }
475
476 int
477 fdwrite(dev, uio, flags)
478 dev_t dev;
479 struct uio *uio;
480 int flags;
481 {
482
483 return (physio(fdstrategy, NULL, dev, B_WRITE, minphys, uio));
484 }
485
486 void
487 fd_set_motor(fdc, reset)
488 struct fdc_softc *fdc;
489 int reset;
490 {
491 struct fd_softc *fd;
492 u_char status;
493 int n;
494
495 if ((fd = TAILQ_FIRST(&fdc->sc_link.fdlink.sc_drives)) != NULL)
496 status = fd->sc_drive;
497 else
498 status = 0;
499 if (!reset)
500 status |= FDO_FRST | FDO_FDMAEN;
501 for (n = 0; n < 4; n++)
502 if ((fd = fdc->sc_link.fdlink.sc_fd[n])
503 && (fd->sc_flags & FD_MOTOR))
504 status |= FDO_MOEN(n);
505 bus_space_write_1(fdc->sc_iot, fdc->sc_ioh, fdout, status);
506 }
507
508 void
509 fd_motor_off(arg)
510 void *arg;
511 {
512 struct fd_softc *fd = arg;
513 int s;
514
515 s = splbio();
516 fd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT);
517 fd_set_motor((struct fdc_softc *)fd->sc_dev.dv_parent, 0);
518 splx(s);
519 }
520
521 void
522 fd_motor_on(arg)
523 void *arg;
524 {
525 struct fd_softc *fd = arg;
526 struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
527 int s;
528
529 s = splbio();
530 fd->sc_flags &= ~FD_MOTOR_WAIT;
531 if ((TAILQ_FIRST(&fdc->sc_link.fdlink.sc_drives) == fd)
532 && (fdc->sc_state == MOTORWAIT))
533 (void) fdintr(fdc);
534 splx(s);
535 }
536
537 int
538 fdopen(dev, flags, mode, p)
539 dev_t dev;
540 int flags;
541 int mode;
542 struct proc *p;
543 {
544 int unit;
545 struct fd_softc *fd;
546 struct fd_type *type;
547
548 unit = FDUNIT(dev);
549 if (unit >= fd_cd.cd_ndevs)
550 return ENXIO;
551 fd = fd_cd.cd_devs[unit];
552 if (fd == 0)
553 return ENXIO;
554 type = fd_dev_to_type(fd, dev);
555 if (type == NULL)
556 return ENXIO;
557
558 if ((fd->sc_flags & FD_OPEN) != 0 &&
559 fd->sc_type != type)
560 return EBUSY;
561
562 fd->sc_type = type;
563 fd->sc_cylin = -1;
564 fd->sc_flags |= FD_OPEN;
565
566 return 0;
567 }
568
569 int
570 fdclose(dev, flags, mode, p)
571 dev_t dev;
572 int flags;
573 int mode;
574 struct proc *p;
575 {
576 struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
577
578 fd->sc_flags &= ~FD_OPEN;
579 fd->sc_opts &= ~FDOPT_NORETRY;
580 return 0;
581 }
582
583 daddr64_t
584 fdsize(dev)
585 dev_t dev;
586 {
587
588
589 return -1;
590 }
591
592 int
593 fddump(dev, blkno, va, size)
594 dev_t dev;
595 daddr64_t blkno;
596 caddr_t va;
597 size_t size;
598 {
599
600
601 return ENXIO;
602 }
603
604
605
606
607 int
608 fdintr(fdc)
609 struct fdc_softc *fdc;
610 {
611 #define st0 fdc->sc_status[0]
612 #define cyl fdc->sc_status[1]
613 struct fd_softc *fd;
614 struct buf *bp;
615 bus_space_tag_t iot = fdc->sc_iot;
616 bus_space_handle_t ioh = fdc->sc_ioh;
617 bus_space_handle_t ioh_ctl = fdc->sc_ioh_ctl;
618 int read, head, sec, i, nblks;
619 struct fd_type *type;
620 struct fd_formb *finfo = NULL;
621 int fd_bsize;
622
623 loop:
624
625 fd = TAILQ_FIRST(&fdc->sc_link.fdlink.sc_drives);
626 if (fd == NULL) {
627 fdc->sc_state = DEVIDLE;
628 return 1;
629 }
630 fd_bsize = FD_BSIZE(fd);
631
632 bp = fd->sc_q.b_actf;
633 if (bp == NULL) {
634 fd->sc_ops = 0;
635 TAILQ_REMOVE(&fdc->sc_link.fdlink.sc_drives, fd, sc_drivechain);
636 fd->sc_q.b_active = 0;
637 goto loop;
638 }
639
640 if (bp->b_flags & B_FORMAT)
641 finfo = (struct fd_formb *)bp->b_data;
642
643 switch (fdc->sc_state) {
644 case DEVIDLE:
645 fdc->sc_errors = 0;
646 fd->sc_skip = 0;
647 fd->sc_bcount = bp->b_bcount;
648 fd->sc_blkno = bp->b_blkno / (fd_bsize / DEV_BSIZE);
649 timeout_del(&fd->fd_motor_off_to);
650 if ((fd->sc_flags & FD_MOTOR_WAIT) != 0) {
651 fdc->sc_state = MOTORWAIT;
652 return 1;
653 }
654 if ((fd->sc_flags & FD_MOTOR) == 0) {
655
656 struct fd_softc *ofd =
657 fdc->sc_link.fdlink.sc_fd[fd->sc_drive ^ 1];
658 if (ofd && ofd->sc_flags & FD_MOTOR) {
659 timeout_del(&ofd->fd_motor_off_to);
660 ofd->sc_flags &= ~(FD_MOTOR | FD_MOTOR_WAIT);
661 }
662 fd->sc_flags |= FD_MOTOR | FD_MOTOR_WAIT;
663 fd_set_motor(fdc, 0);
664 fdc->sc_state = MOTORWAIT;
665
666 timeout_add(&fd->fd_motor_on_to, hz / 4);
667 return 1;
668 }
669
670 fd_set_motor(fdc, 0);
671
672
673 case DOSEEK:
674 doseek:
675 if (fd->sc_cylin == bp->b_cylinder)
676 goto doio;
677
678 out_fdc(iot, ioh, NE7CMD_SPECIFY);
679 out_fdc(iot, ioh, fd->sc_type->steprate);
680 out_fdc(iot, ioh, 6);
681
682 out_fdc(iot, ioh, NE7CMD_SEEK);
683 out_fdc(iot, ioh, fd->sc_drive);
684 out_fdc(iot, ioh, bp->b_cylinder * fd->sc_type->step);
685
686 fd->sc_cylin = -1;
687 fdc->sc_state = SEEKWAIT;
688
689 fd->sc_dk.dk_seek++;
690 disk_busy(&fd->sc_dk);
691
692 timeout_add(&fd->fdtimeout_to, 4 * hz);
693 return 1;
694
695 case DOIO:
696 doio:
697 type = fd->sc_type;
698 if (finfo)
699 fd->sc_skip = (char *)&(finfo->fd_formb_cylno(0)) -
700 (char *)finfo;
701 sec = fd->sc_blkno % type->seccyl;
702 nblks = type->seccyl - sec;
703 nblks = min(nblks, fd->sc_bcount / fd_bsize);
704 nblks = min(nblks, FDC_MAXIOSIZE / fd_bsize);
705 fd->sc_nblks = nblks;
706 fd->sc_nbytes = finfo ? bp->b_bcount : nblks * fd_bsize;
707 head = sec / type->sectrac;
708 sec -= head * type->sectrac;
709 #ifdef DIAGNOSTIC
710 {int block;
711 block = (fd->sc_cylin * type->heads + head) * type->sectrac + sec;
712 if (block != fd->sc_blkno) {
713 printf("fdintr: block %d != blkno %d\n", block, fd->sc_blkno);
714 #ifdef DDB
715 Debugger();
716 #endif
717 }}
718 #endif
719 read = bp->b_flags & B_READ ? DMAMODE_READ : DMAMODE_WRITE;
720 isadma_start(bp->b_data + fd->sc_skip, fd->sc_nbytes,
721 fdc->sc_drq, read);
722 bus_space_write_1(iot, ioh_ctl, fdctl, type->rate);
723 #ifdef FD_DEBUG
724 printf("fdintr: %s drive %d track %d head %d sec %d nblks %d\n",
725 read ? "read" : "write", fd->sc_drive, fd->sc_cylin, head,
726 sec, nblks);
727 #endif
728 if (finfo) {
729
730 if (out_fdc(iot, ioh, NE7CMD_FORMAT) < 0) {
731 fdc->sc_errors = 4;
732 fdretry(fd);
733 goto loop;
734 }
735 out_fdc(iot, ioh, (head << 2) | fd->sc_drive);
736 out_fdc(iot, ioh, finfo->fd_formb_secshift);
737 out_fdc(iot, ioh, finfo->fd_formb_nsecs);
738 out_fdc(iot, ioh, finfo->fd_formb_gaplen);
739 out_fdc(iot, ioh, finfo->fd_formb_fillbyte);
740 } else {
741 if (read)
742 out_fdc(iot, ioh, NE7CMD_READ);
743 else
744 out_fdc(iot, ioh, NE7CMD_WRITE);
745 out_fdc(iot, ioh, (head << 2) | fd->sc_drive);
746 out_fdc(iot, ioh, fd->sc_cylin);
747 out_fdc(iot, ioh, head);
748 out_fdc(iot, ioh, sec + 1);
749 out_fdc(iot, ioh, type->secsize);
750 out_fdc(iot, ioh, type->sectrac);
751 out_fdc(iot, ioh, type->gap1);
752 out_fdc(iot, ioh, type->datalen);
753 }
754 fdc->sc_state = IOCOMPLETE;
755
756 disk_busy(&fd->sc_dk);
757
758
759 timeout_add(&fd->fdtimeout_to, 2 * hz);
760 return 1;
761
762 case SEEKWAIT:
763 timeout_del(&fd->fdtimeout_to);
764 fdc->sc_state = SEEKCOMPLETE;
765
766 timeout_add(&fdc->fdcpseudointr_to, hz / 50);
767 return 1;
768
769 case SEEKCOMPLETE:
770 disk_unbusy(&fd->sc_dk, 0, 0);
771
772
773 out_fdc(iot, ioh, NE7CMD_SENSEI);
774 if (fdcresult(fdc) != 2 || (st0 & 0xf8) != 0x20 ||
775 cyl != bp->b_cylinder * fd->sc_type->step) {
776 #ifdef FD_DEBUG
777 fdcstatus(&fd->sc_dev, 2, "seek failed");
778 #endif
779 fdretry(fd);
780 goto loop;
781 }
782 fd->sc_cylin = bp->b_cylinder;
783 goto doio;
784
785 case IOTIMEDOUT:
786 isadma_abort(fdc->sc_drq);
787 case SEEKTIMEDOUT:
788 case RECALTIMEDOUT:
789 case RESETTIMEDOUT:
790 fdretry(fd);
791 goto loop;
792
793 case IOCOMPLETE:
794 timeout_del(&fd->fdtimeout_to);
795
796 disk_unbusy(&fd->sc_dk, (bp->b_bcount - bp->b_resid),
797 (bp->b_flags & B_READ));
798
799 if (fdcresult(fdc) != 7 || (st0 & 0xf8) != 0) {
800 isadma_abort(fdc->sc_drq);
801 #ifdef FD_DEBUG
802 fdcstatus(&fd->sc_dev, 7, bp->b_flags & B_READ ?
803 "read failed" : "write failed");
804 printf("blkno %d nblks %d\n",
805 fd->sc_blkno, fd->sc_nblks);
806 #endif
807 fdretry(fd);
808 goto loop;
809 }
810 read = bp->b_flags & B_READ ? DMAMODE_READ : DMAMODE_WRITE;
811 isadma_done(fdc->sc_drq);
812 if (fdc->sc_errors) {
813 diskerr(bp, "fd", "soft error", LOG_PRINTF,
814 fd->sc_skip / fd_bsize, (struct disklabel *)NULL);
815 printf("\n");
816 fdc->sc_errors = 0;
817 }
818 fd->sc_blkno += fd->sc_nblks;
819 fd->sc_skip += fd->sc_nbytes;
820 fd->sc_bcount -= fd->sc_nbytes;
821 if (!finfo && fd->sc_bcount > 0) {
822 bp->b_cylinder = fd->sc_blkno / fd->sc_type->seccyl;
823 goto doseek;
824 }
825 fdfinish(fd, bp);
826 goto loop;
827
828 case DORESET:
829
830 fd_set_motor(fdc, 1);
831 delay(100);
832 fd_set_motor(fdc, 0);
833 fdc->sc_state = RESETCOMPLETE;
834 timeout_add(&fd->fdtimeout_to, hz / 2);
835 return 1;
836
837 case RESETCOMPLETE:
838 timeout_del(&fd->fdtimeout_to);
839
840 for (i = 0; i < 4; i++) {
841 out_fdc(iot, ioh, NE7CMD_SENSEI);
842 (void) fdcresult(fdc);
843 }
844
845
846 case DORECAL:
847 out_fdc(iot, ioh, NE7CMD_RECAL);
848 out_fdc(iot, ioh, fd->sc_drive);
849 fdc->sc_state = RECALWAIT;
850 timeout_add(&fd->fdtimeout_to, 5 * hz);
851 return 1;
852
853 case RECALWAIT:
854 timeout_del(&fd->fdtimeout_to);
855 fdc->sc_state = RECALCOMPLETE;
856
857 timeout_add(&fdc->fdcpseudointr_to, hz / 30);
858 return 1;
859
860 case RECALCOMPLETE:
861 out_fdc(iot, ioh, NE7CMD_SENSEI);
862 if (fdcresult(fdc) != 2 || (st0 & 0xf8) != 0x20 || cyl != 0) {
863 #ifdef FD_DEBUG
864 fdcstatus(&fd->sc_dev, 2, "recalibrate failed");
865 #endif
866 fdretry(fd);
867 goto loop;
868 }
869 fd->sc_cylin = 0;
870 goto doseek;
871
872 case MOTORWAIT:
873 if (fd->sc_flags & FD_MOTOR_WAIT)
874 return 1;
875 goto doseek;
876
877 default:
878 fdcstatus(&fd->sc_dev, 0, "stray interrupt");
879 return 1;
880 }
881 #ifdef DIAGNOSTIC
882 panic("fdintr: impossible");
883 #endif
884 #undef st0
885 #undef cyl
886 }
887
888 void
889 fdtimeout(arg)
890 void *arg;
891 {
892 struct fd_softc *fd = arg;
893 struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
894 int s;
895
896 s = splbio();
897 #ifdef DEBUG
898 log(LOG_ERR,"fdtimeout: state %d\n", fdc->sc_state);
899 #endif
900 fdcstatus(&fd->sc_dev, 0, "timeout");
901
902 if (fd->sc_q.b_actf)
903 fdc->sc_state++;
904 else
905 fdc->sc_state = DEVIDLE;
906
907 (void) fdintr(fdc);
908 splx(s);
909 }
910
911 void
912 fdretry(fd)
913 struct fd_softc *fd;
914 {
915 struct fdc_softc *fdc = (void *)fd->sc_dev.dv_parent;
916 struct buf *bp = fd->sc_q.b_actf;
917
918 if (fd->sc_opts & FDOPT_NORETRY)
919 goto fail;
920 switch (fdc->sc_errors) {
921 case 0:
922
923 fdc->sc_state = DOSEEK;
924 break;
925
926 case 1: case 2: case 3:
927
928 fdc->sc_state = DORECAL;
929 break;
930
931 case 4:
932
933 fdc->sc_state = DORESET;
934 break;
935
936 default:
937 fail:
938 diskerr(bp, "fd", "hard error", LOG_PRINTF,
939 fd->sc_skip / FD_BSIZE(fd), (struct disklabel *)NULL);
940 printf(" (st0 %b st1 %b st2 %b cyl %d head %d sec %d)\n",
941 fdc->sc_status[0], NE7_ST0BITS,
942 fdc->sc_status[1], NE7_ST1BITS,
943 fdc->sc_status[2], NE7_ST2BITS,
944 fdc->sc_status[3], fdc->sc_status[4], fdc->sc_status[5]);
945
946 bp->b_flags |= B_ERROR;
947 bp->b_error = EIO;
948 fdfinish(fd, bp);
949 }
950 fdc->sc_errors++;
951 }
952
953 int
954 fdioctl(dev, cmd, addr, flag, p)
955 dev_t dev;
956 u_long cmd;
957 caddr_t addr;
958 int flag;
959 struct proc *p;
960 {
961 struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
962 struct disklabel dl, *lp = &dl;
963 char *errstring;
964 int error;
965
966 switch (cmd) {
967 case MTIOCTOP:
968 if (((struct mtop *)addr)->mt_op != MTOFFL)
969 return EIO;
970 return (0);
971 case DIOCGDINFO:
972 bzero(lp, sizeof(*lp));
973
974 lp->d_secsize = FD_BSIZE(fd);
975 lp->d_secpercyl = fd->sc_type->seccyl;
976 lp->d_ntracks = fd->sc_type->heads;
977 lp->d_nsectors = fd->sc_type->sectrac;
978 lp->d_ncylinders = fd->sc_type->tracks;
979
980 strncpy(lp->d_typename, "floppy disk", sizeof lp->d_typename);
981 lp->d_type = DTYPE_FLOPPY;
982 strncpy(lp->d_packname, "fictitious", sizeof lp->d_packname);
983 DL_SETDSIZE(lp, fd->sc_type->size);
984 lp->d_rpm = 300;
985 lp->d_interleave = 1;
986 lp->d_version = 1;
987
988 lp->d_magic = DISKMAGIC;
989 lp->d_magic2 = DISKMAGIC;
990 lp->d_checksum = dkcksum(lp);
991
992 errstring = readdisklabel(DISKLABELDEV(dev), fdstrategy, lp, 0);
993 if (errstring) {
994
995 }
996
997 *(struct disklabel *)addr = *lp;
998 return 0;
999
1000 case DIOCWLABEL:
1001 if ((flag & FWRITE) == 0)
1002 return EBADF;
1003
1004 return 0;
1005
1006 case DIOCWDINFO:
1007 if ((flag & FWRITE) == 0)
1008 return EBADF;
1009
1010 error = setdisklabel(lp, (struct disklabel *)addr, 0);
1011 if (error)
1012 return error;
1013
1014 error = writedisklabel(DISKLABELDEV(dev), fdstrategy, lp);
1015 return error;
1016
1017 case FD_FORM:
1018 if((flag & FWRITE) == 0)
1019 return EBADF;
1020 else if(((struct fd_formb *)addr)->format_version !=
1021 FD_FORMAT_VERSION)
1022 return EINVAL;
1023 else
1024 return fdformat(dev, (struct fd_formb *)addr, p);
1025 break;
1026
1027 case FD_GTYPE:
1028 *(struct fd_type *)addr = *fd->sc_type;
1029 return 0;
1030
1031 case FD_GOPTS:
1032 *(int *)addr = fd->sc_opts;
1033 return 0;
1034
1035 case FD_SOPTS:
1036 fd->sc_opts = *(int *)addr;
1037 return 0;
1038
1039 default:
1040 return ENOTTY;
1041 }
1042
1043 #ifdef DIAGNOSTIC
1044 panic("fdioctl: impossible");
1045 #endif
1046 }
1047
1048 int
1049 fdformat(dev, finfo, p)
1050 dev_t dev;
1051 struct fd_formb *finfo;
1052 struct proc *p;
1053 {
1054 int rv = 0;
1055 struct fd_softc *fd = fd_cd.cd_devs[FDUNIT(dev)];
1056 struct fd_type *type = fd->sc_type;
1057 struct buf *bp;
1058 int fd_bsize = FD_BSIZE(fd);
1059
1060
1061 bp = (struct buf *)malloc(sizeof(struct buf), M_TEMP, M_NOWAIT);
1062 if (bp == NULL)
1063 return ENOBUFS;
1064
1065 bzero((void *)bp, sizeof(struct buf));
1066 bp->b_flags = B_BUSY | B_PHYS | B_FORMAT;
1067 bp->b_proc = p;
1068 bp->b_dev = dev;
1069
1070
1071
1072
1073
1074 bp->b_blkno = (finfo->cyl * (type->sectrac * type->heads)
1075 + finfo->head * type->sectrac) * fd_bsize / DEV_BSIZE;
1076
1077 bp->b_bcount = sizeof(struct fd_idfield_data) * finfo->fd_formb_nsecs;
1078 bp->b_data = (caddr_t)finfo;
1079
1080 #ifdef DEBUG
1081 printf("fdformat: blkno %x count %x\n", bp->b_blkno, bp->b_bcount);
1082 #endif
1083
1084
1085 fdstrategy(bp);
1086
1087
1088 rv = biowait(bp);
1089 free(bp, M_TEMP);
1090 return (rv);
1091 }