|
|
1.1 root 1: /*
2: * Copyright (c) 1994 Shantanu Goel
3: * All Rights Reserved.
4: *
5: * Permission to use, copy, modify and distribute this software and its
6: * documentation is hereby granted, provided that both the copyright
7: * notice and this permission notice appear in all copies of the
8: * software, derivative works or modified versions, and any portions
9: * thereof, and that both notices appear in supporting documentation.
10: *
11: * THE AUTHOR ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
12: * CONDITION. THE AUTHOR DISCLAIMS ANY LIABILITY OF ANY KIND FOR
13: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
14: */
15:
16: #include <fd.h>
17: #if NFD > 0
18: /*
19: * Floppy disk driver.
20: *
21: * Supports:
22: * 1 controller and 2 drives.
23: * Media change and automatic media detection.
24: * Arbitrarily sized read/write requests.
25: * Misaligned requests
26: * DMA above 16 Meg
27: *
28: * TODO:
29: * 1) Real probe routines for controller and drives.
30: * 2) Support for multiple controllers. The driver does
31: * not assume a single controller since all functions
32: * take the controller and/or device structure as an
33: * argument, however the probe routines limit the
34: * number of controllers and drives to 1 and 2 respectively.
35: * 3) V_VERIFY ioctl.
36: * 4) User defined diskette parameters.
37: * 5) Detect Intel 82077 or compatible and use its FIFO mode.
38: *
39: * Shantanu Goel ([email protected])
40: */
41: #include <sys/types.h>
42: #include <sys/ioctl.h>
43: #include "vm_param.h"
44: #include <kern/time_out.h>
45: #include <vm/pmap.h>
46: #include <device/param.h>
47: #include <device/buf.h>
48: #include <device/errno.h>
49: #include <chips/busses.h>
50: #include <i386/machspl.h>
51: #include <i386/pio.h>
52: #include <i386at/cram.h>
53: #include <i386at/disk.h>
54: #include <i386at/nfdreg.h>
55:
56: /*
57: * Number of drives supported by an FDC.
58: * The controller is actually capable of
59: * supporting 4 drives, however, most (all?)
60: * board implementations only support 2.
61: */
62: #define NDRIVES_PER_FDC 2
63: #define NFDC ((NFD + NDRIVES_PER_FDC - 1) / NDRIVES_PER_FDC)
64:
65: #define fdunit(dev) (((int)(dev) >> 6) & 3)
66: #define fdmedia(dev) ((int)(dev) & 3)
67:
68: #define b_cylin b_resid
69: #define B_FORMAT B_MD1
70:
71: #define SECSIZE 512
72:
73: #define DMABSIZE (18*1024) /* size of DMA bounce buffer */
74:
75: #define OP_TIMEOUT 5 /* time to wait (secs) for an
76: operation before giving up */
77: #define MOTOR_TIMEOUT 5 /* time to wait (secs) before turning
78: off an idle drive motor */
79: #define MAX_RETRIES 48 /* number of times to try
80: an I/O operation */
81:
82: #define SRTHUT 0xdf /* step rate/head unload time */
83: #define HLTND 0x02 /* head load time/dma mode */
84:
85: /*
86: * DMA controller.
87: *
88: * XXX: There should be a generic <i386/dma.h> file.
89: */
90:
91: /*
92: * Ports
93: */
94: #define DMA2_PAGE 0x81 /* channel 2, page register */
95: #define DMA2_ADDR 0x04 /* channel 2, addr register */
96: #define DMA2_COUNT 0x05 /* channel 2, count register */
97: #define DMA_STATUS 0x08 /* status register */
98: #define DMA_COMMAND 0x08 /* command register */
99: #define DMA_WREQ 0x09 /* request register */
100: #define DMA_SINGLEMSK 0x0a /* single mask register */
101: #define DMA_MODE 0x0b /* mode register */
102: #define DMA_FLIPFLOP 0x0c /* pointer flip/flop */
103: #define DMA_TEMP 0x0d /* temporary register */
104: #define DMA_MASTERCLR 0x0d /* master clear */
105: #define DMA_CLRMASK 0x0e /* clear mask register */
106: #define DMA_ALLMASK 0x0f /* all mask register */
107:
108: /*
109: * Commands
110: */
111: #define DMA_WRITE 0x46 /* write on channel 2 */
112: #define DMA_READ 0x4a /* read on channel 2 */
113:
114: /*
115: * Autoconfiguration stuff.
116: */
117: struct bus_ctlr *fdminfo[NFDC];
118: struct bus_device *fddinfo[NFD];
119: int fdstd[] = { 0 };
120: int fdprobe(), fdslave(), fdintr();
121: void fdattach();
122: struct bus_driver fddriver = {
123: fdprobe, fdslave, fdattach, 0, fdstd, "fd", fddinfo, "fdc", fdminfo
124: };
125:
126: /*
127: * Per-controller state.
128: */
129: struct fdcsoftc {
130: int sc_flags;
131: #define FDF_WANT 0x01 /* someone needs direct controller access */
132: #define FDF_RESET 0x02 /* controller needs reset */
133: #define FDF_LIMIT 0x04 /* limit transfer to a single sector */
134: #define FDF_BOUNCE 0x08 /* using bounce buffer */
135: int sc_state; /* transfer fsm */
136: caddr_t sc_addr; /* buffer address */
137: int sc_resid; /* amount left to transfer */
138: int sc_amt; /* amount currently being transferred */
139: int sc_op; /* operation being performed */
140: int sc_mode; /* DMA mode */
141: int sc_sn; /* sector number */
142: int sc_tn; /* track number */
143: int sc_cn; /* cylinder number */
144: int sc_recalerr; /* # recalibration errors */
145: int sc_seekerr; /* # seek errors */
146: int sc_ioerr; /* # i/o errors */
147: int sc_dor; /* copy of digital output register */
148: int sc_rate; /* copy of transfer rate register */
149: int sc_wticks; /* watchdog */
150: u_int sc_buf; /* buffer for transfers > 16 Meg */
151: u_char sc_cmd[9]; /* command buffer */
152: u_char sc_results[7]; /* operation results */
153: } fdcsoftc[NFDC];
154:
155: #define sc_st0 sc_results[0]
156: #define sc_st3 sc_results[0]
157: #define sc_st1 sc_results[1]
158: #define sc_pcn sc_results[1]
159: #define sc_st2 sc_results[2]
160: #define sc_c sc_results[3]
161: #define sc_h sc_results[4]
162: #define sc_r sc_results[5]
163: #define sc_n sc_results[6]
164:
165: /*
166: * Transfer states.
167: */
168: #define IDLE 0 /* controller is idle */
169: #define RESET 1 /* reset controller */
170: #define RESETDONE 2 /* reset completion interrupt */
171: #define RECAL 3 /* recalibrate drive */
172: #define RECALDONE 4 /* recalibration complete interrupt */
173: #define SEEK 5 /* perform seek on drive */
174: #define SEEKDONE 6 /* seek completion interrupt */
175: #define TRANSFER 7 /* perform transfer on drive */
176: #define TRANSFERDONE 8 /* transfer completion interrupt */
177:
178: /*
179: * Per-drive state.
180: */
181: struct fdsoftc {
182: int sc_flags;
183: #define FDF_RECAL 0x02 /* drive needs recalibration */
184: #define FDF_SEEK 0x04 /* force seek during auto-detection */
185: #define FDF_AUTO 0x08 /* performing auto-density */
186: #define FDF_AUTOFORCE 0x10 /* force auto-density */
187: #define FDF_INIT 0x20 /* drive is being initialized */
188: int sc_type; /* drive type */
189: struct fddk *sc_dk; /* diskette type */
190: int sc_cyl; /* current head position */
191: int sc_mticks; /* motor timeout */
192: } fdsoftc[NFD];
193:
194: struct buf fdtab[NFDC]; /* controller queues */
195: struct buf fdutab[NFD]; /* drive queues */
196:
197: /*
198: * Floppy drive type names.
199: */
200: char *fdnames[] = { "360K", "1.2 Meg", "720K", "1.44 Meg" };
201: #define NTYPES (sizeof(fdnames) / sizeof(fdnames[0]))
202:
203: /*
204: * Floppy diskette parameters.
205: */
206: struct fddk {
207: int dk_nspu; /* sectors/unit */
208: int dk_nspc; /* sectors/cylinder */
209: int dk_ncyl; /* cylinders/unit */
210: int dk_nspt; /* sectors/track */
211: int dk_step; /* !=0 means double track steps */
212: int dk_gap; /* read/write gap length */
213: int dk_fgap; /* format gap length */
214: int dk_rate; /* transfer rate */
215: int dk_drives; /* bit mask of drives that accept diskette */
216: char *dk_name; /* type name */
217: } fddk[] = {
218: /*
219: * NOTE: largest density for each drive type must be first so
220: * fdauto() tries it before any lower ones.
221: */
222: { 2880, 36, 80, 18, 0, 0x1b, 0x6c, 0x00, 0x08, "1.44 Meg" },
223: { 2400, 30, 80, 15, 0, 0x1b, 0x54, 0x00, 0x02, "1.2 Meg" },
224: { 1440, 18, 80, 9, 0, 0x2a, 0x50, 0x02, 0x0c, "720K" },
225: { 720, 18, 40, 9, 1, 0x23, 0x50, 0x01, 0x02, "360K" },
226: { 720, 18, 40, 9, 0, 0x2a, 0x50, 0x02, 0x01, "360K PC" }
227: };
228: #define NDKTYPES (sizeof(fddk) / sizeof(fddk[0]))
229:
230: /*
231: * For compatibility with old driver.
232: * This array is indexed by the old floppy type codes
233: * and points to the corresponding entry for that
234: * type in fddk[] above.
235: */
236: struct fddk *fdcompat[NDKTYPES];
237:
238: int fdwstart = 0;
239: int fdstrategy(), fdformat();
240: char *fderrmsg();
241: void fdwatch(), fdminphys(), fdspinup(), wakeup();
242:
243: #define FDDEBUG
244: #ifdef FDDEBUG
245: int fddebug = 0;
246: #define DEBUGF(n, stmt) { if (fddebug >= (n)) stmt; }
247: #else
248: #define DEBUGF(n, stmt)
249: #endif
250:
251: /*
252: * Probe for a controller.
253: */
254: int
255: fdprobe(xxx, um)
256: int xxx;
257: struct bus_ctlr *um;
258: {
259: struct fdcsoftc *fdc;
260:
261: if (um->unit >= NFDC) {
262: printf("fdc%d: not configured\n", um->unit);
263: return (0);
264: }
265: if (um->unit > 0) /* XXX: only 1 controller */
266: return (0);
267:
268: /*
269: * XXX: need real probe
270: */
271: take_ctlr_irq(um);
272: printf("%s%d: port 0x%x, spl %d, pic %d.\n",
273: um->name, um->unit, um->address, um->sysdep, um->sysdep1);
274:
275: /*
276: * Set up compatibility array.
277: */
278: fdcompat[0] = &fddk[2];
279: fdcompat[1] = &fddk[0];
280: fdcompat[2] = &fddk[3];
281: fdcompat[3] = &fddk[1];
282:
283: fdc = &fdcsoftc[um->unit];
284: fdc->sc_rate = -1;
285: if (!fdc->sc_buf) {
286: fdc->sc_buf = alloc_dma_mem(DMABSIZE, 64*1024);
287: if (fdc->sc_buf == 0)
288: panic("fd: alloc_dma_mem() failed");
289: }
290: fdc->sc_dor = DOR_RSTCLR | DOR_IENABLE;
291: outb(FD_DOR(um->address), fdc->sc_dor);
292: return (1);
293: }
294:
295: /*
296: * Probe for a drive.
297: */
298: int
299: fdslave(ui)
300: struct bus_device *ui;
301: {
302: struct fdsoftc *sc;
303:
304: if (ui->unit >= NFD) {
305: printf("fd%d: not configured\n", ui->unit);
306: return (0);
307: }
308: if (ui->unit > 1) /* XXX: only 2 drives */
309: return (0);
310:
311: /*
312: * Find out from CMOS if drive exists.
313: */
314: sc = &fdsoftc[ui->unit];
315: outb(CMOS_ADDR, 0x10);
316: sc->sc_type = inb(CMOS_DATA);
317: if (ui->unit == 0)
318: sc->sc_type >>= 4;
319: sc->sc_type &= 0x0f;
320: return (sc->sc_type);
321: }
322:
323: /*
324: * Attach a drive to the system.
325: */
326: void
327: fdattach(ui)
328: struct bus_device *ui;
329: {
330: struct fdsoftc *sc;
331:
332: sc = &fdsoftc[ui->unit];
333: if (--sc->sc_type >= NTYPES) {
334: printf(": unknown drive type %d", sc->sc_type);
335: ui->alive = 0;
336: return;
337: }
338: printf(": %s", fdnames[sc->sc_type]);
339: sc->sc_flags = FDF_RECAL | FDF_SEEK | FDF_AUTOFORCE;
340: }
341:
342: int
343: fdopen(dev, mode)
344: dev_t dev;
345: int mode;
346: {
347: int unit = fdunit(dev), error;
348: struct bus_device *ui;
349: struct fdsoftc *sc;
350:
351: if (unit >= NFD || (ui = fddinfo[unit]) == 0 || ui->alive == 0)
352: return (ENXIO);
353:
354: /*
355: * Start watchdog.
356: */
357: if (!fdwstart) {
358: fdwstart++;
359: timeout(fdwatch, 0, hz);
360: }
361: /*
362: * Do media detection if drive is being opened for the
363: * first time or diskette has been changed since the last open.
364: */
365: sc = &fdsoftc[unit];
366: if ((sc->sc_flags & FDF_AUTOFORCE) || fddskchg(ui)) {
367: if (error = fdauto(dev))
368: return (error);
369: sc->sc_flags &= ~FDF_AUTOFORCE;
370: }
371: return (0);
372: }
373:
374: int
375: fdclose(dev)
376: dev_t dev;
377: {
378: int s, unit = fdunit(dev);
379: struct fdsoftc *sc = &fdsoftc[unit];
380:
381: /*
382: * Wait for pending operations to complete.
383: */
384: s = splbio();
385: while (fdutab[unit].b_active) {
386: sc->sc_flags |= FDF_WANT;
387: assert_wait((event_t)sc, FALSE);
388: thread_block((void (*)())0);
389: }
390: splx(s);
391: return (0);
392: }
393:
394: int
395: fdread(dev, ior)
396: dev_t dev;
397: io_req_t ior;
398: {
399: return (block_io(fdstrategy, fdminphys, ior));
400: }
401:
402: int
403: fdwrite(dev, ior)
404: dev_t dev;
405: io_req_t ior;
406: {
407: return (block_io(fdstrategy, fdminphys, ior));
408: }
409:
410: int
411: fdgetstat(dev, flavor, status, status_count)
412: dev_t dev;
413: dev_flavor_t flavor;
414: dev_status_t status;
415: mach_msg_type_number_t *status_count;
416: {
417: switch (flavor) {
418:
419: case DEV_GET_SIZE:
420: {
421: int *info;
422: io_return_t error;
423: struct disk_parms dp;
424:
425: if (error = fdgetparms(dev, &dp))
426: return (error);
427: info = (int *)status;
428: info[DEV_GET_SIZE_DEVICE_SIZE] = dp.dp_pnumsec * SECSIZE;
429: info[DEV_GET_SIZE_RECORD_SIZE] = SECSIZE;
430: *status_count = DEV_GET_SIZE_COUNT;
431: return (D_SUCCESS);
432: }
433: case V_GETPARMS:
434: if (*status_count < (sizeof(struct disk_parms) / sizeof(int)))
435: return (D_INVALID_OPERATION);
436: *status_count = sizeof(struct disk_parms) / sizeof(int);
437: return (fdgetparms(dev, (struct disk_parms *)status));
438:
439: default:
440: return (D_INVALID_OPERATION);
441: }
442: }
443:
444: int
445: fdsetstat(dev, flavor, status, status_count)
446: dev_t dev;
447: dev_flavor_t flavor;
448: dev_status_t status;
449: mach_msg_type_number_t status_count;
450: {
451: switch (flavor) {
452:
453: case V_SETPARMS:
454: return (fdsetparms(dev, *(int *)status));
455:
456: case V_FORMAT:
457: return (fdformat(dev, (union io_arg *)status));
458:
459: case V_VERIFY:
460: /*
461: * XXX: needs to be implemented
462: */
463: return (D_SUCCESS);
464:
465: default:
466: return (D_INVALID_OPERATION);
467: }
468: }
469:
470: int
471: fddevinfo(dev, flavor, info)
472: dev_t dev;
473: int flavor;
474: char *info;
475: {
476: switch (flavor) {
477:
478: case D_INFO_BLOCK_SIZE:
479: *(int *)info = SECSIZE;
480: return (D_SUCCESS);
481:
482: default:
483: return (D_INVALID_OPERATION);
484: }
485: }
486:
487: /*
488: * Allow arbitrary transfers. Standard minphys restricts
489: * transfers to a maximum of 256K preventing us from reading
490: * an entire diskette in a single system call.
491: */
492: void
493: fdminphys(ior)
494: io_req_t ior;
495: {
496: }
497:
498: /*
499: * Return current media parameters.
500: */
501: int
502: fdgetparms(dev, dp)
503: dev_t dev;
504: struct disk_parms *dp;
505: {
506: struct fddk *dk = fdsoftc[fdunit(dev)].sc_dk;
507:
508: dp->dp_type = DPT_FLOPPY;
509: dp->dp_heads = 2;
510: dp->dp_sectors = dk->dk_nspt;
511: dp->dp_pstartsec = 0;
512: dp->dp_cyls = dk->dk_ncyl;
513: dp->dp_pnumsec = dk->dk_nspu;
514: return (0);
515: }
516:
517: /*
518: * Set media parameters.
519: */
520: int
521: fdsetparms(dev, type)
522: dev_t dev;
523: int type;
524: {
525: struct fdsoftc *sc;
526: struct fddk *dk;
527:
528: if (type < 0 || type >= NDKTYPES)
529: return (EINVAL);
530: dk = fdcompat[type];
531: sc = &fdsoftc[fdunit(dev)];
532: if ((dk->dk_drives & (1 << sc->sc_type)) == 0)
533: return (EINVAL);
534: sc->sc_dk = dk;
535: return (D_SUCCESS);
536: }
537:
538: /*
539: * Format a floppy.
540: */
541: int
542: fdformat(dev, arg)
543: dev_t dev;
544: union io_arg *arg;
545: {
546: int i, j, sect, error = 0;
547: unsigned track, num_trks;
548: struct buf *bp;
549: struct fddk *dk;
550: struct format_info *fmt;
551:
552: dk = fdsoftc[fdunit(dev)].sc_dk;
553: num_trks = arg->ia_fmt.num_trks;
554: track = arg->ia_fmt.start_trk;
555: if (num_trks == 0 || track + num_trks > (dk->dk_ncyl << 1)
556: || arg->ia_fmt.intlv >= dk->dk_nspt)
557: return (EINVAL);
558:
559: bp = (struct buf *)geteblk(SECSIZE);
560: bp->b_dev = dev;
561: bp->b_bcount = dk->dk_nspt * sizeof(struct format_info);
562: bp->b_blkno = track * dk->dk_nspt;
563:
564: while (num_trks-- > 0) {
565: /*
566: * Set up format information.
567: */
568: fmt = (struct format_info *)bp->b_un.b_addr;
569: for (i = 0; i < dk->dk_nspt; i++)
570: fmt[i].sector = 0;
571: for (i = 0, j = 0, sect = 1; i < dk->dk_nspt; i++) {
572: fmt[j].cyl = track >> 1;
573: fmt[j].head = track & 1;
574: fmt[j].sector = sect++;
575: fmt[j].secsize = 2;
576: if ((j += arg->ia_fmt.intlv) < dk->dk_nspt)
577: continue;
578: for (j -= dk->dk_nspt; j < dk->dk_nspt; j++)
579: if (fmt[j].sector == 0)
580: break;
581: }
582: bp->b_flags = B_FORMAT;
583: fdstrategy(bp);
584: biowait(bp);
585: if (bp->b_flags & B_ERROR) {
586: error = bp->b_error;
587: break;
588: }
589: bp->b_blkno += dk->dk_nspt;
590: track++;
591: }
592: bp->b_flags &= ~B_FORMAT;
593: brelse(bp);
594: return (error);
595: }
596:
597: /*
598: * Strategy routine.
599: * Enqueue a request on drive queue.
600: */
601: int
602: fdstrategy(bp)
603: struct buf *bp;
604: {
605: int unit = fdunit(bp->b_dev), s;
606: int bn, sz, maxsz;
607: struct buf *dp;
608: struct bus_device *ui = fddinfo[unit];
609: struct fddk *dk = fdsoftc[unit].sc_dk;
610:
611: bn = bp->b_blkno;
612: sz = (bp->b_bcount + SECSIZE - 1) / SECSIZE;
613: maxsz = dk->dk_nspu;
614: if (bn < 0 || bn + sz > maxsz) {
615: if (bn == maxsz) {
616: bp->b_resid = bp->b_bcount;
617: goto done;
618: }
619: sz = maxsz - bn;
620: if (sz <= 0) {
621: bp->b_error = EINVAL;
622: bp->b_flags |= B_ERROR;
623: goto done;
624: }
625: bp->b_bcount = sz * SECSIZE;
626: }
627: bp->b_cylin = bn / dk->dk_nspc;
628: dp = &fdutab[unit];
629: s = splbio();
630: disksort(dp, bp);
631: if (!dp->b_active) {
632: fdustart(ui);
633: if (!fdtab[ui->mi->unit].b_active)
634: fdstart(ui->mi);
635: }
636: splx(s);
637: return;
638: done:
639: biodone(bp);
640: return;
641: }
642:
643: /*
644: * Unit start routine.
645: * Move request from drive to controller queue.
646: */
647: int
648: fdustart(ui)
649: struct bus_device *ui;
650: {
651: struct buf *bp;
652: struct buf *dp;
653:
654: bp = &fdutab[ui->unit];
655: if (bp->b_actf == 0)
656: return;
657: dp = &fdtab[ui->mi->unit];
658: if (dp->b_actf == 0)
659: dp->b_actf = bp;
660: else
661: dp->b_actl->b_forw = bp;
662: bp->b_forw = 0;
663: dp->b_actl = bp;
664: bp->b_active++;
665: }
666:
667: /*
668: * Start output on controller.
669: */
670: int
671: fdstart(um)
672: struct bus_ctlr *um;
673: {
674: struct buf *bp;
675: struct buf *dp;
676: struct fdsoftc *sc;
677: struct fdcsoftc *fdc;
678: struct bus_device *ui;
679: struct fddk *dk;
680:
681: /*
682: * Pull a request from the controller queue.
683: */
684: dp = &fdtab[um->unit];
685: if ((bp = dp->b_actf) == 0)
686: return;
687: bp = bp->b_actf;
688:
689: fdc = &fdcsoftc[um->unit];
690: ui = fddinfo[fdunit(bp->b_dev)];
691: sc = &fdsoftc[ui->unit];
692: dk = sc->sc_dk;
693:
694: /*
695: * Mark controller busy.
696: */
697: dp->b_active++;
698:
699: /*
700: * Figure out where this request is going.
701: */
702: fdc->sc_cn = bp->b_cylin;
703: fdc->sc_sn = bp->b_blkno % dk->dk_nspc;
704: fdc->sc_tn = fdc->sc_sn / dk->dk_nspt;
705: fdc->sc_sn %= dk->dk_nspt;
706:
707: /*
708: * Set up for multi-sector transfer.
709: */
710: fdc->sc_op = ((bp->b_flags & B_FORMAT) ? CMD_FORMAT
711: : ((bp->b_flags & B_READ) ? CMD_READ : CMD_WRITE));
712: fdc->sc_mode = (bp->b_flags & B_READ) ? DMA_WRITE : DMA_READ;
713: fdc->sc_addr = bp->b_un.b_addr;
714: fdc->sc_resid = bp->b_bcount;
715: fdc->sc_wticks = 0;
716: fdc->sc_recalerr = 0;
717: fdc->sc_seekerr = 0;
718: fdc->sc_ioerr = 0;
719:
720: /*
721: * Set initial transfer state.
722: */
723: if (fdc->sc_flags & FDF_RESET)
724: fdc->sc_state = RESET;
725: else if (sc->sc_flags & FDF_RECAL)
726: fdc->sc_state = RECAL;
727: else if (sc->sc_cyl != fdc->sc_cn)
728: fdc->sc_state = SEEK;
729: else
730: fdc->sc_state = TRANSFER;
731:
732: /*
733: * Set transfer rate.
734: */
735: if (fdc->sc_rate != dk->dk_rate) {
736: fdc->sc_rate = dk->dk_rate;
737: outb(FD_RATE(um->address), fdc->sc_rate);
738: }
739: /*
740: * Turn on drive motor.
741: * Don't start I/O if drive is spinning up.
742: */
743: if (fdmotoron(ui)) {
744: timeout(fdspinup, (void *)um, hz / 2);
745: return;
746: }
747: /*
748: * Call transfer state routine to do the actual I/O.
749: */
750: fdstate(um);
751: }
752:
753: /*
754: * Interrupt routine.
755: */
756: int
757: fdintr(ctlr)
758: int ctlr;
759: {
760: int timedout;
761: u_char results[7];
762: struct buf *bp;
763: struct bus_device *ui;
764: struct fdsoftc *sc;
765: struct buf *dp = &fdtab[ctlr];
766: struct fdcsoftc *fdc = &fdcsoftc[ctlr];
767: struct bus_ctlr *um = fdminfo[ctlr];
768:
769: if (!dp->b_active) {
770: printf("fdc%d: stray interrupt\n", ctlr);
771: return;
772: }
773: timedout = fdc->sc_wticks >= OP_TIMEOUT;
774: fdc->sc_wticks = 0;
775: bp = dp->b_actf->b_actf;
776: ui = fddinfo[fdunit(bp->b_dev)];
777: sc = &fdsoftc[ui->unit];
778:
779: /*
780: * Operation timed out, terminate request.
781: */
782: if (timedout) {
783: fderror("timed out", ui);
784: fdmotoroff(ui);
785: sc->sc_flags |= FDF_RECAL;
786: bp->b_flags |= B_ERROR;
787: bp->b_error = ENXIO;
788: fddone(ui, bp);
789: return;
790: }
791: /*
792: * Read results from FDC.
793: * For transfer completion they can be read immediately.
794: * For anything else, we must issue a Sense Interrupt
795: * Status Command. We keep issuing this command till
796: * FDC returns invalid command status. The Controller Busy
797: * bit in the status register indicates completion of a
798: * read/write/format operation.
799: */
800: if (inb(FD_STATUS(um->address)) & ST_CB) {
801: if (!fdresults(um, fdc->sc_results))
802: return;
803: } else {
804: while (1) {
805: fdc->sc_cmd[0] = CMD_SENSEI;
806: if (!fdcmd(um, 1)) {
807: DEBUGF(2, printf(2, "fd%d: SENSEI failed\n"));
808: return;
809: }
810: if (!fdresults(um, results))
811: return;
812: if ((results[0] & ST0_IC) == 0x80)
813: break;
814: if ((results[0] & ST0_US) == ui->slave) {
815: fdc->sc_results[0] = results[0];
816: fdc->sc_results[1] = results[1];
817: }
818: }
819: }
820: /*
821: * Let transfer state routine handle the rest.
822: */
823: fdstate(um);
824: }
825:
826: /*
827: * Transfer finite state machine driver.
828: */
829: int
830: fdstate(um)
831: struct bus_ctlr *um;
832: {
833: int unit, max, pa, s;
834: struct buf *bp;
835: struct fdsoftc *sc;
836: struct bus_device *ui;
837: struct fddk *dk;
838: struct fdcsoftc *fdc = &fdcsoftc[um->unit];
839:
840: bp = fdtab[um->unit].b_actf->b_actf;
841: ui = fddinfo[fdunit(bp->b_dev)];
842: sc = &fdsoftc[ui->unit];
843: dk = sc->sc_dk;
844:
845: while (1) switch (fdc->sc_state) {
846:
847: case RESET:
848: /*
849: * Reset the controller.
850: */
851: fdreset(um);
852: return;
853:
854: case RESETDONE:
855: /*
856: * Reset complete.
857: * Mark all drives as needing recalibration
858: * and issue specify command.
859: */
860: for (unit = 0; unit < NFD; unit++)
861: if (fddinfo[unit] && fddinfo[unit]->alive
862: && fddinfo[unit]->mi == um)
863: fdsoftc[unit].sc_flags |= FDF_RECAL;
864: fdc->sc_cmd[0] = CMD_SPECIFY;
865: fdc->sc_cmd[1] = SRTHUT;
866: fdc->sc_cmd[2] = HLTND;
867: if (!fdcmd(um, 3))
868: return;
869: fdc->sc_flags &= ~FDF_RESET;
870: fdc->sc_state = RECAL;
871: break;
872:
873: case RECAL:
874: /*
875: * Recalibrate drive.
876: */
877: fdc->sc_state = RECALDONE;
878: fdc->sc_cmd[0] = CMD_RECAL;
879: fdc->sc_cmd[1] = ui->slave;
880: fdcmd(um, 2);
881: return;
882:
883: case RECALDONE:
884: /*
885: * Recalibration complete.
886: */
887: if ((fdc->sc_st0 & ST0_IC) || (fdc->sc_st0 & ST0_EC)) {
888: if (++fdc->sc_recalerr == 2) {
889: fderror("recalibrate failed", ui);
890: goto bad;
891: }
892: fdc->sc_state = RESET;
893: break;
894: }
895: sc->sc_flags &= ~FDF_RECAL;
896: fdc->sc_recalerr = 0;
897: sc->sc_cyl = -1;
898: fdc->sc_state = SEEK;
899: break;
900:
901: case SEEK:
902: /*
903: * Perform seek operation.
904: */
905: fdc->sc_state = SEEKDONE;
906: fdc->sc_cmd[0] = CMD_SEEK;
907: fdc->sc_cmd[1] = (fdc->sc_tn << 2) | ui->slave;
908: fdc->sc_cmd[2] = fdc->sc_cn;
909: if (dk->dk_step)
910: fdc->sc_cmd[2] <<= 1;
911: fdcmd(um, 3);
912: return;
913:
914: case SEEKDONE:
915: /*
916: * Seek complete.
917: */
918: if (dk->dk_step)
919: fdc->sc_pcn >>= 1;
920: if ((fdc->sc_st0 & ST0_IC) || (fdc->sc_st0 & ST0_SE) == 0
921: || fdc->sc_pcn != fdc->sc_cn) {
922: if (++fdc->sc_seekerr == 2) {
923: fderror("seek failed", ui);
924: goto bad;
925: }
926: fdc->sc_state = RESET;
927: break;
928: }
929: fdc->sc_seekerr = 0;
930: sc->sc_cyl = fdc->sc_pcn;
931: fdc->sc_state = TRANSFER;
932: break;
933:
934: case TRANSFER:
935: /*
936: * Perform I/O transfer.
937: */
938: fdc->sc_flags &= ~FDF_BOUNCE;
939: pa = pmap_extract(kernel_pmap, fdc->sc_addr);
940: if (fdc->sc_op == CMD_FORMAT) {
941: max = sizeof(struct format_info) * dk->dk_nspt;
942: } else if (fdc->sc_flags & FDF_LIMIT) {
943: fdc->sc_flags &= ~FDF_LIMIT;
944: max = SECSIZE;
945: } else {
946: max = (dk->dk_nspc - dk->dk_nspt * fdc->sc_tn
947: - fdc->sc_sn) * SECSIZE;
948: }
949: if (max > fdc->sc_resid)
950: max = fdc->sc_resid;
951: if (pa >= 16*1024*1024) {
952: fdc->sc_flags |= FDF_BOUNCE;
953: pa = fdc->sc_buf;
954: if (max < DMABSIZE)
955: fdc->sc_amt = max;
956: else
957: fdc->sc_amt = DMABSIZE;
958: } else {
959: int prevpa, curpa, omax;
960: vm_offset_t va;
961:
962: omax = max;
963: if (max > 65536 - (pa & 0xffff))
964: max = 65536 - (pa & 0xffff);
965: fdc->sc_amt = I386_PGBYTES - (pa & (I386_PGBYTES - 1));
966: va = (vm_offset_t)fdc->sc_addr + fdc->sc_amt;
967: prevpa = pa & ~(I386_PGBYTES - 1);
968: while (fdc->sc_amt < max) {
969: curpa = pmap_extract(kernel_pmap, va);
970: if (curpa >= 16*1024*1024
971: || curpa != prevpa + I386_PGBYTES)
972: break;
973: fdc->sc_amt += I386_PGBYTES;
974: va += I386_PGBYTES;
975: prevpa = curpa;
976: }
977: if (fdc->sc_amt > max)
978: fdc->sc_amt = max;
979: if (fdc->sc_op == CMD_FORMAT) {
980: if (fdc->sc_amt != omax) {
981: fdc->sc_flags |= FDF_BOUNCE;
982: pa = fdc->sc_buf;
983: fdc->sc_amt = omax;
984: }
985: } else if (fdc->sc_amt != fdc->sc_resid) {
986: if (fdc->sc_amt < SECSIZE) {
987: fdc->sc_flags |= FDF_BOUNCE;
988: pa = fdc->sc_buf;
989: if (omax > DMABSIZE)
990: fdc->sc_amt = DMABSIZE;
991: else
992: fdc->sc_amt = omax;
993: } else
994: fdc->sc_amt &= ~(SECSIZE - 1);
995: }
996: }
997:
998: DEBUGF(2, printf("fd%d: TRANSFER: amt %d cn %d tn %d sn %d\n",
999: ui->unit, fdc->sc_amt, fdc->sc_cn,
1000: fdc->sc_tn, fdc->sc_sn + 1));
1001:
1002: if ((fdc->sc_flags & FDF_BOUNCE) && fdc->sc_op != CMD_READ) {
1003: fdc->sc_flags &= ~FDF_BOUNCE;
1004: bcopy(fdc->sc_addr, (caddr_t)phystokv(fdc->sc_buf),
1005: fdc->sc_amt);
1006: }
1007: /*
1008: * Set up DMA.
1009: */
1010: s = sploff();
1011: outb(DMA_SINGLEMSK, 0x04 | 0x02);
1012: outb(DMA_FLIPFLOP, 0);
1013: outb(DMA_MODE, fdc->sc_mode);
1014: outb(DMA2_ADDR, pa);
1015: outb(DMA2_ADDR, pa >> 8);
1016: outb(DMA2_PAGE, pa >> 16);
1017: outb(DMA2_COUNT, fdc->sc_amt - 1);
1018: outb(DMA2_COUNT, (fdc->sc_amt - 1) >> 8);
1019: outb(DMA_SINGLEMSK, 0x02);
1020: splon(s);
1021:
1022: /*
1023: * Issue command to FDC.
1024: */
1025: fdc->sc_state = TRANSFERDONE;
1026: fdc->sc_cmd[0] = fdc->sc_op;
1027: fdc->sc_cmd[1] = (fdc->sc_tn << 2) | ui->slave;
1028: if (fdc->sc_op == CMD_FORMAT) {
1029: fdc->sc_cmd[2] = 0x02;
1030: fdc->sc_cmd[3] = dk->dk_nspt;
1031: fdc->sc_cmd[4] = dk->dk_fgap;
1032: fdc->sc_cmd[5] = 0xda;
1033: fdcmd(um, 6);
1034: } else {
1035: fdc->sc_cmd[2] = fdc->sc_cn;
1036: fdc->sc_cmd[3] = fdc->sc_tn;
1037: fdc->sc_cmd[4] = fdc->sc_sn + 1;
1038: fdc->sc_cmd[5] = 0x02;
1039: fdc->sc_cmd[6] = dk->dk_nspt;
1040: fdc->sc_cmd[7] = dk->dk_gap;
1041: fdc->sc_cmd[8] = 0xff;
1042: fdcmd(um, 9);
1043: }
1044: return;
1045:
1046: case TRANSFERDONE:
1047: /*
1048: * Transfer complete.
1049: */
1050: if (fdc->sc_st0 & ST0_IC) {
1051: fdc->sc_ioerr++;
1052: if (sc->sc_flags & FDF_AUTO) {
1053: /*
1054: * Give up on second try if
1055: * media detection is in progress.
1056: */
1057: if (fdc->sc_ioerr == 2)
1058: goto bad;
1059: fdc->sc_state = RECAL;
1060: break;
1061: }
1062: if (fdc->sc_ioerr == MAX_RETRIES) {
1063: fderror(fderrmsg(ui), ui);
1064: goto bad;
1065: }
1066: /*
1067: * Give up immediately on write-protected diskettes.
1068: */
1069: if (fdc->sc_st1 & ST1_NW) {
1070: fderror("write-protected diskette", ui);
1071: goto bad;
1072: }
1073: /*
1074: * Limit transfer to a single sector.
1075: */
1076: fdc->sc_flags |= FDF_LIMIT;
1077: /*
1078: * Every fourth attempt recalibrate the drive.
1079: * Every eight attempt reset the controller.
1080: * Also, every eighth attempt inform user
1081: * about the error.
1082: */
1083: if (fdc->sc_ioerr & 3)
1084: fdc->sc_state = TRANSFER;
1085: else if (fdc->sc_ioerr & 7)
1086: fdc->sc_state = RECAL;
1087: else {
1088: fdc->sc_state = RESET;
1089: fderror(fderrmsg(ui), ui);
1090: }
1091: break;
1092: }
1093: /*
1094: * Transfer completed successfully.
1095: * Advance counters/pointers, and if more
1096: * is left, initiate I/O.
1097: */
1098: if (fdc->sc_flags & FDF_BOUNCE) {
1099: fdc->sc_flags &= ~FDF_BOUNCE;
1100: bcopy((caddr_t)phystokv(fdc->sc_buf), fdc->sc_addr,
1101: fdc->sc_amt);
1102: }
1103: if ((fdc->sc_resid -= fdc->sc_amt) == 0) {
1104: bp->b_resid = 0;
1105: fddone(ui, bp);
1106: return;
1107: }
1108: fdc->sc_state = TRANSFER;
1109: fdc->sc_ioerr = 0;
1110: fdc->sc_addr += fdc->sc_amt;
1111: if (fdc->sc_op == CMD_FORMAT) {
1112: fdc->sc_sn = 0;
1113: if (fdc->sc_tn == 1) {
1114: fdc->sc_tn = 0;
1115: fdc->sc_cn++;
1116: fdc->sc_state = SEEK;
1117: } else
1118: fdc->sc_tn = 1;
1119: } else {
1120: fdc->sc_sn += fdc->sc_amt / SECSIZE;
1121: while (fdc->sc_sn >= dk->dk_nspt) {
1122: fdc->sc_sn -= dk->dk_nspt;
1123: if (fdc->sc_tn == 1) {
1124: fdc->sc_tn = 0;
1125: fdc->sc_cn++;
1126: fdc->sc_state = SEEK;
1127: } else
1128: fdc->sc_tn = 1;
1129: }
1130: }
1131: break;
1132:
1133: default:
1134: printf("fd%d: invalid state\n", ui->unit);
1135: panic("fdstate");
1136: /*NOTREACHED*/
1137: }
1138: bad:
1139: bp->b_flags |= B_ERROR;
1140: bp->b_error = EIO;
1141: sc->sc_flags |= FDF_RECAL;
1142: fddone(ui, bp);
1143: }
1144:
1145: /*
1146: * Terminate current request and start
1147: * any others that are queued.
1148: */
1149: int
1150: fddone(ui, bp)
1151: struct bus_device *ui;
1152: struct buf *bp;
1153: {
1154: struct bus_ctlr *um = ui->mi;
1155: struct fdsoftc *sc = &fdsoftc[ui->unit];
1156: struct fdcsoftc *fdc = &fdcsoftc[um->unit];
1157: struct buf *dp = &fdtab[um->unit];
1158:
1159: DEBUGF(1, printf("fd%d: fddone()\n", ui->unit));
1160:
1161: /*
1162: * Remove this request from queue.
1163: */
1164: if (bp) {
1165: fdutab[ui->unit].b_actf = bp->b_actf;
1166: biodone(bp);
1167: bp = &fdutab[ui->unit];
1168: dp->b_actf = bp->b_forw;
1169: } else
1170: bp = &fdutab[ui->unit];
1171:
1172: /*
1173: * Mark controller and drive idle.
1174: */
1175: dp->b_active = 0;
1176: bp->b_active = 0;
1177: fdc->sc_state = IDLE;
1178: sc->sc_mticks = 0;
1179: fdc->sc_flags &= ~(FDF_LIMIT|FDF_BOUNCE);
1180:
1181: /*
1182: * Start up other requests.
1183: */
1184: fdustart(ui);
1185: fdstart(um);
1186:
1187: /*
1188: * Wakeup anyone waiting for drive or controller.
1189: */
1190: if (sc->sc_flags & FDF_WANT) {
1191: sc->sc_flags &= ~FDF_WANT;
1192: wakeup((void *)sc);
1193: }
1194: if (fdc->sc_flags & FDF_WANT) {
1195: fdc->sc_flags &= ~FDF_WANT;
1196: wakeup((void *)fdc);
1197: }
1198: }
1199:
1200: /*
1201: * Check if diskette change has occured since the last open.
1202: */
1203: int
1204: fddskchg(ui)
1205: struct bus_device *ui;
1206: {
1207: int s, dir;
1208: struct fdsoftc *sc = &fdsoftc[ui->unit];
1209: struct bus_ctlr *um = ui->mi;
1210: struct fdcsoftc *fdc = &fdcsoftc[um->unit];
1211:
1212: /*
1213: * Get access to controller.
1214: */
1215: s = splbio();
1216: while (fdtab[um->unit].b_active) {
1217: fdc->sc_flags |= FDF_WANT;
1218: assert_wait((event_t)fdc, FALSE);
1219: thread_block((void (*)())0);
1220: }
1221: fdtab[um->unit].b_active = 1;
1222: fdutab[ui->unit].b_active = 1;
1223:
1224: /*
1225: * Turn on drive motor and read digital input register.
1226: */
1227: if (fdmotoron(ui)) {
1228: timeout(wakeup, (void *)fdc, hz / 2);
1229: assert_wait((event_t)fdc, FALSE);
1230: thread_block((void (*)())0);
1231: }
1232: dir = inb(FD_DIR(um->address));
1233: fddone(ui, NULL);
1234: splx(s);
1235:
1236: if (dir & DIR_DSKCHG) {
1237: printf("fd%d: diskette change detected\n", ui->unit);
1238: sc->sc_flags |= FDF_SEEK;
1239: return (1);
1240: }
1241: return (0);
1242: }
1243:
1244: /*
1245: * Do media detection.
1246: */
1247: int
1248: fdauto(dev)
1249: dev_t dev;
1250: {
1251: int i, error = 0;
1252: struct buf *bp;
1253: struct bus_device *ui = fddinfo[fdunit(dev)];
1254: struct fdsoftc *sc = &fdsoftc[ui->unit];
1255: struct fddk *dk, *def = 0;
1256:
1257: sc->sc_flags |= FDF_AUTO;
1258: bp = (struct buf *)geteblk(SECSIZE);
1259: for (i = 0, dk = fddk; i < NDKTYPES; i++, dk++) {
1260: if ((dk->dk_drives & (1 << sc->sc_type)) == 0)
1261: continue;
1262: if (def == 0)
1263: def = dk;
1264: sc->sc_dk = dk;
1265: bp->b_flags = B_READ;
1266: bp->b_dev = dev;
1267: bp->b_bcount = SECSIZE;
1268: if (sc->sc_flags & FDF_SEEK) {
1269: sc->sc_flags &= ~FDF_SEEK;
1270: bp->b_blkno = 100;
1271: } else
1272: bp->b_blkno = 0;
1273: fdstrategy(bp);
1274: biowait(bp);
1275: if ((bp->b_flags & B_ERROR) == 0 || bp->b_error == ENXIO)
1276: break;
1277: }
1278: if (i == NDKTYPES) {
1279: printf("fd%d: couldn't detect type, using %s\n",
1280: ui->unit, def->dk_name);
1281: sc->sc_dk = def;
1282: } else if ((bp->b_flags & B_ERROR) == 0)
1283: printf("fd%d: detected %s\n", ui->unit, sc->sc_dk->dk_name);
1284: else
1285: error = ENXIO;
1286: sc->sc_flags &= ~FDF_AUTO;
1287: brelse(bp);
1288: return (error);
1289: }
1290:
1291: /*
1292: * Turn on drive motor and select drive.
1293: */
1294: int
1295: fdmotoron(ui)
1296: struct bus_device *ui;
1297: {
1298: int bit;
1299: struct bus_ctlr *um = ui->mi;
1300: struct fdcsoftc *fdc = &fdcsoftc[um->unit];
1301:
1302: bit = 1 << (ui->slave + 4);
1303: if ((fdc->sc_dor & bit) == 0) {
1304: fdc->sc_dor &= ~3;
1305: fdc->sc_dor |= bit | ui->slave;
1306: outb(FD_DOR(um->address), fdc->sc_dor);
1307: return (1);
1308: }
1309: if ((fdc->sc_dor & 3) != ui->slave) {
1310: fdc->sc_dor &= ~3;
1311: fdc->sc_dor |= ui->slave;
1312: outb(FD_DOR(um->address), fdc->sc_dor);
1313: }
1314: return (0);
1315: }
1316:
1317: /*
1318: * Turn off drive motor.
1319: */
1320: int
1321: fdmotoroff(ui)
1322: struct bus_device *ui;
1323: {
1324: struct bus_ctlr *um = ui->mi;
1325: struct fdcsoftc *fdc = &fdcsoftc[um->unit];
1326:
1327: fdc->sc_dor &= ~(1 << (ui->slave + 4));
1328: outb(FD_DOR(um->address), fdc->sc_dor);
1329: }
1330:
1331: /*
1332: * This routine is invoked via timeout() by fdstart()
1333: * to call fdstate() at splbio.
1334: */
1335: void
1336: fdspinup(um)
1337: struct bus_ctlr *um;
1338: {
1339: int s;
1340:
1341: s = splbio();
1342: fdstate(um);
1343: splx(s);
1344: }
1345:
1346: /*
1347: * Watchdog routine.
1348: * Check for hung operations.
1349: * Turn off motor of idle drives.
1350: */
1351: void
1352: fdwatch()
1353: {
1354: int unit, s;
1355: struct bus_device *ui;
1356:
1357: timeout(fdwatch, 0, hz);
1358: s = splbio();
1359: for (unit = 0; unit < NFDC; unit++)
1360: if (fdtab[unit].b_active
1361: && ++fdcsoftc[unit].sc_wticks == OP_TIMEOUT)
1362: fdintr(unit);
1363: for (unit = 0; unit < NFD; unit++) {
1364: if ((ui = fddinfo[unit]) == 0 || ui->alive == 0)
1365: continue;
1366: if (fdutab[unit].b_active == 0
1367: && (fdcsoftc[ui->mi->unit].sc_dor & (1 << (ui->slave + 4)))
1368: && ++fdsoftc[unit].sc_mticks == MOTOR_TIMEOUT)
1369: fdmotoroff(ui);
1370: }
1371: splx(s);
1372: }
1373:
1374: /*
1375: * Print an error message.
1376: */
1377: int
1378: fderror(msg, ui)
1379: char *msg;
1380: struct bus_device *ui;
1381: {
1382: struct fdcsoftc *fdc = &fdcsoftc[ui->mi->unit];
1383:
1384: printf("fd%d: %s, %sing cn %d tn %d sn %d\n", ui->unit, msg,
1385: (fdc->sc_op == CMD_READ ? "read"
1386: : (fdc->sc_op == CMD_WRITE ? "writ" : "formatt")),
1387: fdc->sc_cn, fdc->sc_tn, fdc->sc_sn + 1);
1388: }
1389:
1390: /*
1391: * Return an error message for an I/O error.
1392: */
1393: char *
1394: fderrmsg(ui)
1395: struct bus_device *ui;
1396: {
1397: struct fdcsoftc *fdc = &fdcsoftc[ui->mi->unit];
1398:
1399: if (fdc->sc_st1 & ST1_EC)
1400: return ("invalid sector");
1401: if (fdc->sc_st1 & ST1_DE)
1402: return ("CRC error");
1403: if (fdc->sc_st1 & ST1_OR)
1404: return ("DMA overrun");
1405: if (fdc->sc_st1 & ST1_ND)
1406: return ("sector not found");
1407: if (fdc->sc_st1 & ST1_NW)
1408: return ("write-protected diskette");
1409: if (fdc->sc_st1 & ST1_MA)
1410: return ("missing address mark");
1411: return ("hard error");
1412: }
1413:
1414: /*
1415: * Output a command to FDC.
1416: */
1417: int
1418: fdcmd(um, n)
1419: struct bus_ctlr *um;
1420: int n;
1421: {
1422: int i, j;
1423: struct fdcsoftc *fdc = &fdcsoftc[um->unit];
1424:
1425: for (i = j = 0; i < 200; i++) {
1426: if ((inb(FD_STATUS(um->address)) & (ST_RQM|ST_DIO)) != ST_RQM)
1427: continue;
1428: outb(FD_DATA(um->address), fdc->sc_cmd[j++]);
1429: if (--n == 0)
1430: return (1);
1431: }
1432: /*
1433: * Controller is not responding, reset it.
1434: */
1435: DEBUGF(1, printf("fdc%d: fdcmd() failed\n", um->unit));
1436: fdreset(um);
1437: return (0);
1438: }
1439:
1440: /*
1441: * Read results from FDC.
1442: */
1443: int
1444: fdresults(um, rp)
1445: struct bus_ctlr *um;
1446: u_char *rp;
1447: {
1448: int i, j, status;
1449:
1450: for (i = j = 0; i < 200; i++) {
1451: status = inb(FD_STATUS(um->address));
1452: if ((status & ST_RQM) == 0)
1453: continue;
1454: if ((status & ST_DIO) == 0)
1455: return (j);
1456: if (j == 7)
1457: break;
1458: *rp++ = inb(FD_DATA(um->address));
1459: j++;
1460: }
1461: /*
1462: * Controller is not responding, reset it.
1463: */
1464: DEBUGF(1, printf("fdc%d: fdresults() failed\n", um->unit));
1465: fdreset(um);
1466: return (0);
1467: }
1468:
1469: /*
1470: * Reset controller.
1471: */
1472: int
1473: fdreset(um)
1474: struct bus_ctlr *um;
1475: {
1476: struct fdcsoftc *fdc = &fdcsoftc[um->unit];
1477:
1478: outb(FD_DOR(um->address), fdc->sc_dor & ~(DOR_RSTCLR|DOR_IENABLE));
1479: fdc->sc_state = RESETDONE;
1480: fdc->sc_flags |= FDF_RESET;
1481: outb(FD_DOR(um->address), fdc->sc_dor);
1482: }
1483:
1484: #endif /* NFD > 0 */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.