|
|
1.1 root 1: /* (-lgl
2: * COHERENT Driver Kit Version 1.1.0
3: * Copyright (c) 1982, 1990 by Mark Williams Company.
4: * All rights reserved. May not be copied without permission.
5: -lgl) */
6: /*
7: * This is a driver for the IBM AT or PC/XT
8: * floppy, using interrupts and DMA on
9: * the NEC 756 floppy chip. Ugh.
10: * Handles single, double and quad
11: * density drives, 8, 9, 15 or 18 sectors per track.
12: * 15 and 18 sectors per track only available on the IBM_AT.
13: *
14: * Minor device assignments: xxuuhkkk
15: * uu - unit = 0/1/2/3
16: * kkk - kind, struct fdata infra.
17: * h - alternating head rather than side by side
18: *
19: */
20:
21: #include <sys/coherent.h>
22: #include <sys/i8086.h>
23: #include <sys/buf.h>
24: #include <sys/con.h>
25: #include <sys/stat.h>
26: #include <errno.h>
27: #include <sys/uproc.h>
28: #include <sys/fdioctl.h>
29: #include <sys/sched.h>
30: #include <sys/dmac.h>
31: #include <sys/devices.h>
32:
33: #define BIT(n) (1 << (n))
34:
35: /*
36: * Patchable parameters (default to IBM PC/XT values).
37: */
38:
39: int fl_srt = 0xC; /* Floppy seek step rate, in unit 2 millisec */
40: /* NOT DIRECTLY ENCODED */
41: /* COMPAQ wants 0xD */
42: int fl_hlt = 1; /* Floppy head load time, in unit 4 millisec */
43: int fl_hut = 0xF; /* Floppy head unload time, in unit 32 millisec */
44:
45: int flload();
46: int flunload();
47: int flopen();
48: int flblock();
49: int flread();
50: int flwrite();
51: int flioctl();
52: int fldelay();
53: int flintr();
54: int fltimeout();
55: int nulldev();
56: int nonedev();
57:
58: CON flcon = {
59: DFBLK|DFCHR, /* Flags */
60: FL_MAJOR, /* Major index */
61: flopen, /* Open */
62: nulldev, /* Close */
63: flblock, /* Block */
64: flread, /* Read */
65: flwrite, /* Write */
66: flioctl, /* Ioctl */
67: nulldev, /* Powerfail */
68: fltimeout, /* Timeout */
69: flload, /* Load */
70: flunload /* Unload */
71: };
72:
73: #define MTIMER 5 /* Motor timeout */
74: #define FDCDOR 0x3F2 /* Digital output */
75: #define FDCDAT 0x3F5 /* Data register */
76: #define FDCMSR 0x3F4 /* Main status register */
77: #define FDCRATE 0x3F7 /* Transfer rate (500,300,250 Kbps) */
78:
79: #define DORDS 0x03 /* Drive select bits */
80: #define DORNMR 0x04 /* Not master reset */
81: #define DORIEN 0x08 /* Interrupt, DMA enable */
82: #define DORMS 0xF0 /* Motor enables */
83:
84: #define MSRDB 0x0F /* Drive busy */
85: #define MSRCB 0x10 /* Control busy */
86: #define MSRNDMA 0x20 /* Not DMA */
87: #define MSRDIO 0x40 /* Data direction */
88: #define MSRRQM 0x80 /* Request for master */
89:
90: /*
91: * Status Register 0 - Bit Definitions.
92: */
93: #define ST0_US0 0x01 /* Unit Select 0 */
94: #define ST0_US1 0x02 /* Unit Select 1 */
95: #define ST0_HD 0x04 /* Head Address */
96: #define ST0_NR 0x08 /* Not Ready */
97: #define ST0_EC 0x10 /* Equipment Check */
98: #define ST0_SE 0x20 /* Seek End */
99: #define ST0_IC 0xC0 /* Interrupt code */
100: #define ST0_NT 0x00 /* Normal Termination */
101:
102: /*
103: * Status Register 1 - Bit Definitions.
104: */
105: #define ST1_MA 0x01 /* Missing Address Mark */
106: #define ST1_NW 0x02 /* Not writeable */
107: #define ST1_ND 0x04 /* No Data */
108: /* 0x08 */ /* Not used - always 0 */
109: #define ST1_OR 0x10 /* Overrun */
110: #define ST1_DE 0x20 /* Data Error */
111: /* 0x40 */ /* Not used - always 0 */
112: #define ST1_EN 0x80 /* End of Cylinder */
113:
114: /*
115: * Status Register 2 - Bit Definitions.
116: */
117: #define ST2_MD 0x01 /* Missing Address Mark in Data Field */
118: #define ST2_BC 0x02 /* Bad Cylinder */
119: #define ST2_SN 0x04 /* Scan Not Satisfied */
120: #define ST2_SH 0x08 /* Scan Equal Hit */
121: #define ST2_WC 0x10 /* Wrong Cylinder */
122: #define ST2_DD 0x20 /* Data Error in Data Field */
123: #define ST2_CM 0x40 /* Control Mark */
124: /* 0x80 */ /* Not used - always 0 */
125:
126: /*
127: * Status Register 3 - Bit Definitions.
128: */
129: #define ST3_US0 0x01 /* Unit Select 0 */
130: #define ST3_US1 0x02 /* Unit Select 1 */
131: #define ST3_HD 0x04 /* Head Address */
132: #define ST3_TS 0x08 /* Two Sides */
133: #define ST3_T0 0x10 /* Track 0 */
134: #define ST3_RDY 0x20 /* Ready */
135: #define ST3_WP 0x40 /* Write Protected */
136: #define ST3_FT 0x80 /* Fault */
137:
138: /*
139: * Controller Commands.
140: */
141: #define CMDSPEC 0x03 /* Specify */
142: #define CMDRCAL 0x07 /* Recal */
143: #define CMDSEEK 0x0F /* Seek */
144: #define CMDRDAT 0x66 /* Read data */
145: #define CMDWDAT 0x45 /* Write data */
146: #define CMDSINT 0x08 /* Sense status */
147: #define CMDFMT 0x4D /* Format track */
148:
149: /*
150: * Driver States.
151: */
152: #define SIDLE 0 /* Idle */
153: #define SSEEK 1 /* Need seek */
154: #define SRDWR 2 /* Need read/write command */
155: #define SENDIO 3 /* Need end I/O processing */
156: #define SDELAY 4 /* Delay before next disk operation */
157: #define SHDLY 5 /* Head settling delay before r/w */
158: #define SLOCK 6 /* Got DMA controller lock */
159:
160: #define funit(x) (minor(x)>>4) /* Unit/drive number */
161: #define fkind(x) (minor(x)&0x7) /* Kind of format */
162: #define fhbyh(x) (minor(x)&0x8) /* 0=Side by side, 1=Head by head */
163:
164: static
165: struct fdata {
166: int fd_size; /* Blocks per diskette */
167: int fd_nhds; /* Heads per drive */
168: int fd_trks; /* Tracks per side */
169: int fd_offs; /* Sector base */
170: int fd_nspt; /* Sectors per track */
171: char fd_GPL[4]; /* Controller gap param (indexed by rate) */
172: char fd_N; /* Controller size param */
173: char fd_FGPL; /* Format gap length */
174: } fdata[] = {
175: /* 8 sectors per track, surface by surface seek. */
176: { 320,1,40,0, 8, { 0x00,0x23,0x2A }, 2,0x50 }, /* Single sided */
177: { 640,2,40,0, 8, { 0x00,0x23,0x2A }, 2,0x50 }, /* Double sided */
178: { 1280,2,80,0, 8, { 0x00,0x23,0x2A }, 2,0x50 }, /* Quad density */
179: /* 9 sectors per track, surface by surface seek. */
180: { 360,1,40,0, 9, { 0x00,0x23,0x2A }, 2,0x50 }, /* Single sided */
181: { 720,2,40,0, 9, { 0x00,0x23,0x2A }, 2,0x50 }, /* Double sided */
182: { 1440,2,80,0, 9, { 0x00,0x23,0x2A }, 2,0x50 }, /* Quad density */
183: /* 15 sectors per track, surface by surface seek. */
184: { 2400,2,80,0,15, { 0x1B,0x00,0x00 }, 2,0x54 }, /* High capacity */
185: /* 18 sectors per track, surface by surface seek. */
186: { 2880,2,80,0,18, { 0x1B,0x00,0x00 }, 2,0x54 } /* 1.44 3.5" */
187: };
188:
189:
190: static
191: struct fl {
192: BUF *fl_actf; /* Queue, forward */
193: BUF *fl_actl; /* Queue, backward */
194: paddr_t fl_addr; /* Address */
195: int fl_nsec; /* # of sectors */
196: int fl_secn; /* Current sector */
197: struct fdata fl_fd; /* Disk kind data */
198: int fl_fcyl; /* Floppy cylinder # */
199: char fl_incal[4]; /* Disk in cal flags */
200: char fl_ndsk; /* # of 5 1/4" drives */
201: char fl_unit; /* Unit # */
202: char fl_mask; /* Handy unit mask */
203: char fl_hbyh; /* 0/1 = Side by side/Head by head */
204: char fl_nerr; /* Error count */
205: int fl_ncmdstat; /* Number of cmd status bytes recvd */
206: char fl_cmdstat[8]; /* Command Status buffer */
207: int fl_nintstat; /* Number of intr status bytes recvd */
208: char fl_intstat[4]; /* Interrupt Status buffer */
209: int fl_fsec; /* Floppy sector # */
210: int fl_head; /* Floppy head */
211: char fl_init; /* FDC init done flag */
212: char fl_state; /* Processing state */
213: char fl_mstatus; /* Motor status */
214: char fl_time[4]; /* Motor timeout */
215: char fl_rate; /* Data rate: 500,300,250,?? kbps */
216: char fl_type[4]; /* Type of drive: 2 = HiCap */
217: int fl_wflag; /* Write operation */
218: int fl_recov; /* Recovery initiated */
219: } fl;
220:
221: static BUF flbuf;
222: static TIM fltim;
223: static TIM fldmalck; /* DMA lock deferred function structure. */
224:
225: /*
226: * The load routine asks the
227: * switches how many drives are present
228: * in the machine, and sets up the field
229: * in the floppy database. It also grabs
230: * the level 6 interrupt vector.
231: */
232: static
233: flload()
234: {
235: register int eflag;
236: register int s;
237:
238: /*
239: * Ensure DMA channel 2 is turned off.
240: * The Computerland ROM does not disable DMA channel after autoboot
241: * from hard disk. The Western Digital controller board appears to
242: * send a dma burst when the floppy controller chip is reset.
243: */
244: dmaoff( 2 );
245:
246: /*
247: * Read floppy equipment byte from CMOS ram
248: * drive 0 is in high nibble, drive 1 is in low nibble.
249: */
250: outb( 0x70, 0x10 );
251: /* delay */
252: eflag = inb( 0x71 );
253:
254: /*
255: * Flag hardware as an IBM AT if neither equipment byte nibble is
256: * greater than 4 (since 5 through 15 are reserved nibble values - see
257: * IBM AT Technical Reference manual, page 1-50). Note that this
258: * relies on the fact that in the XT, this byte will "float" high.
259: * NOTE: 1.44 Mbyte 3.5 inch drives are type 4
260: */
261: if ( (eflag & 0x88) == 0 ) {
262:
263: /*
264: * Reinitialize patchable parameters for IBM AT.
265: */
266: fl_srt = 0xD; /* Floppy seek step rate, in unit 2 ms */
267: /* NOT DIRECTLY ENCODED */
268: fl_hlt = 25; /* Floppy head load time, in unit 4 ms */
269:
270: /*
271: * Define AT drive information.
272: */
273: fl.fl_type[0] = eflag >> 4;
274: fl.fl_type[1] = eflag & 15;
275: fl.fl_rate = 1; /* Must not be 2 */
276:
277: /*
278: * Determine number of AT floppy drives.
279: */
280: if ( eflag & 0xF0 ) {
281: fl.fl_ndsk++;
282: if ( eflag & 0x0F )
283: fl.fl_ndsk++;
284: }
285: } else {
286: /*
287: * Define XT drive information.
288: */
289: eflag = int11();
290: fl.fl_rate = 2;
291: if ( eflag & 1 )
292: fl.fl_ndsk = ((eflag >> 6) & 0x03) + 1;
293: }
294:
295: if ( fl.fl_ndsk ) {
296:
297: s = sphi();
298: outb(FDCDOR, 0);
299: setivec(6, &flintr);
300:
301: outb(FDCDOR, 0);
302: outb(FDCDOR, DORNMR);
303:
304: if ( fl.fl_rate != 2 )
305: outb(FDCRATE, fl.fl_rate );
306:
307: flput(CMDSPEC);
308: flput((fl_srt<<4)|fl_hut);
309: flput(fl_hlt<<1);
310: spl( s );
311: }
312: }
313:
314: /*
315: * Release resources.
316: */
317: flunload()
318: {
319: /*
320: * Clear interrupt vector.
321: */
322: if ( fl.fl_ndsk )
323: clrivec(6);
324:
325: /*
326: * Cancel timed function.
327: */
328: timeout( &fltim, 0, NULL, NULL );
329:
330: /*
331: * Cancel periodic [1 second] invocation.
332: */
333: drvl[FL_MAJOR].d_time = 0;
334:
335: /*
336: * Turn motors off.
337: */
338: outb(FDCDOR, DORNMR | DORIEN );
339: }
340:
341: /*
342: * The open routine screens out
343: * opens of illegal minor devices and
344: * performs the NEC specify command if
345: * this is the very first floppy disk
346: * open call.
347: */
348:
349: static
350: flopen( dev, mode )
351:
352: dev_t dev;
353: int mode;
354:
355: {
356: /*
357: * Validate existence and data rate [Gap length != 0].
358: */
359: if ( ( funit(dev) >= fl.fl_ndsk )
360: || ( fdata[ fkind(dev) ].fd_GPL[ flrate(dev) ] == 0 ) ) {
361:
362: u.u_error = ENXIO;
363: return;
364: }
365: }
366:
367: /*
368: * The read routine just calls
369: * off to the common raw I/O processing
370: * code, using a static buffer header in
371: * the driver.
372: */
373:
374: static
375: flread( dev, iop )
376:
377: dev_t dev;
378: IO *iop;
379:
380: {
381: dmareq(&flbuf, iop, dev, BREAD);
382: }
383:
384: /*
385: * The write routine is just like the
386: * read routine, except that the function code
387: * is write instead of read.
388: */
389:
390: static
391: flwrite( dev, iop )
392:
393: dev_t dev;
394: IO *iop;
395:
396: {
397: dmareq(&flbuf, iop, dev, BWRITE);
398: }
399:
400: /*
401: * The ioctl routine simply queues a format request
402: * using flbuf.
403: * The only valid command is to format a track.
404: * The parameter block contains the header records supplied to the controller.
405: */
406:
407: static
408: flioctl( dev, com, par )
409:
410: dev_t dev;
411: int com;
412: char *par;
413:
414: {
415: register unsigned s;
416: register struct fdata *fdp;
417: unsigned hd, cyl;
418:
419: if (com != FDFORMAT) {
420: u.u_error = EINVAL;
421: return;
422: }
423:
424: fdp = &fdata[ fkind(dev) ];
425: cyl = getubd(par);
426: hd = getubd(par+1);
427:
428: if (hd > 1 || cyl >= fdp->fd_trks) {
429: u.u_error = EINVAL;
430: return;
431: }
432:
433: /*
434: * The following may need some explanation.
435: * dmareq will:
436: * claim the buffer,
437: * bounds check the parameter buffer,
438: * lock the parameter buffer in memory,
439: * convert io_seek to b_bno,
440: * dispatch the request,
441: * wait for completion,
442: * and unlock the parameter buffer.
443: * The b_bno is reconverted to hd, cyl in flfsm.
444: */
445:
446: s = fhbyh(dev) ? (cyl * fdp->fd_nhds + hd) : (hd * fdp->fd_trks + cyl);
447: s *= fdp->fd_nspt;
448: u.u_io.io_seek = ((long)s) * BSIZE;
449: u.u_io.io_base = par;
450: u.u_io.io_ioc = fdp->fd_nspt * 4;
451: dmareq(&flbuf, &u.u_io, dev, FDFORMAT);
452: }
453:
454: /*
455: * Start up block I/O on a
456: * buffer. Check that the block number
457: * is not out of range, given the style of
458: * the disk. Put the buffer header into the
459: * device queue. Start up the disk if the
460: * device is idle.
461: */
462:
463: static
464: flblock( bp )
465:
466: register BUF *bp;
467:
468: {
469: register int s;
470: register unsigned bno;
471:
472: bno = bp->b_bno + (bp->b_count >> 9) - 1;
473: if ((unsigned)bp->b_bno > fdata[ fkind(bp->b_dev) ].fd_size) {
474: bp->b_flag |= BFERR;
475: bdone(bp);
476: return;
477: }
478: if (bp->b_req != FDFORMAT && bno >= fdata[ fkind(bp->b_dev) ].fd_size) {
479: bp->b_resid = bp->b_count;
480: if (bp->b_flag & BFRAW)
481: bp->b_flag |= BFERR;
482: bdone(bp); /* return w/ b_resid != 0 */
483: return;
484: }
485:
486: if ((bp->b_count&0x1FF) != 0) {
487: if (bp->b_req != FDFORMAT) {
488: bp->b_flag |= BFERR;
489: bdone(bp);
490: return;
491: }
492: }
493:
494: bp->b_actf = NULL;
495: s = sphi(); /* s was already == sphi() on at least PC/XT. */
496:
497: if (fl.fl_actf == NULL)
498: fl.fl_actf = bp;
499: else
500: fl.fl_actl->b_actf = bp;
501:
502: fl.fl_actl = bp;
503:
504: if (fl.fl_state == SIDLE)
505: flfsm();
506:
507: spl( s );
508: }
509:
510: /*
511: * This finite state machine is
512: * responsible for all sequencing on the disk.
513: * It builds the commands, does the seeks, spins up
514: * the drive motor for 1 second on the first call,
515: * and so on.
516: * Note that the format command is rather obscurely shoehorned into this.
517: */
518:
519: static
520: flfsm()
521: {
522: register BUF *bp;
523: register int flcmd;
524: register int i;
525:
526: again:
527: bp = fl.fl_actf;
528:
529: switch (fl.fl_state) {
530:
531: case SIDLE:
532: drvl[FL_MAJOR].d_time = 1;
533:
534: if ( bp == NULL )
535: break;
536:
537: fl.fl_fd = fdata[ fkind(bp->b_dev) ];
538: fl.fl_unit = funit( bp->b_dev );
539: fl.fl_hbyh = fhbyh( bp->b_dev );
540:
541: fl.fl_mask = 0x10 << fl.fl_unit;
542:
543: fl.fl_addr = bp->b_paddr;
544: fl.fl_secn = bp->b_bno;
545: fl.fl_time[fl.fl_unit] = 0;
546:
547: if ((fl.fl_nsec = bp->b_count>>9) == 0)
548: fl.fl_nsec = 1;
549:
550: fl.fl_nerr = 0;
551:
552: /*
553: * Set data rate if changed.
554: * NOTE: XT never changes data rate.
555: */
556: if ( (i = flrate(bp->b_dev)) != fl.fl_rate )
557: outb(FDCRATE, fl.fl_rate = i );
558:
559: /*
560: * Motor is turned off - turn it on, wait 1 second.
561: */
562: if ((fl.fl_mstatus&fl.fl_mask) == 0) {
563:
564: fl.fl_mstatus |= fl.fl_mask;
565: outb(FDCDOR, DORNMR|DORIEN|fl.fl_mstatus|fl.fl_unit);
566: flsense();
567:
568: timeout( &fltim, HZ, fldelay, SSEEK );
569: fl.fl_time[fl.fl_unit] = 0;
570: fl.fl_state = SDELAY;
571: break;
572: }
573: /* no break */
574:
575: case SSEEK:
576: fl.fl_time[fl.fl_unit] = 0;
577: outb(FDCDOR, DORNMR|DORIEN|fl.fl_mstatus|fl.fl_unit);
578: flsense();
579:
580: /*
581: * Drive is not calibrated - seek to track 0.
582: */
583: if (fl.fl_incal[fl.fl_unit] == 0) {
584: ++fl.fl_incal[fl.fl_unit];
585: flput(CMDRCAL);
586: flput(fl.fl_unit);
587: fl.fl_state = SSEEK;
588: break;
589: }
590:
591: fl.fl_fsec = (fl.fl_secn % fl.fl_fd.fd_nspt) + 1;
592:
593: /*
594: * Seek cylinder by cylinder (XENIX/DOS compatible).
595: */
596: if (fl.fl_hbyh) {
597: fl.fl_head = fl.fl_secn / fl.fl_fd.fd_nspt;
598: fl.fl_fcyl = fl.fl_head / fl.fl_fd.fd_nhds;
599: fl.fl_head = fl.fl_head % fl.fl_fd.fd_nhds;
600: }
601:
602: /*
603: * Seek surface by surface.
604: */
605: else {
606: fl.fl_fcyl = fl.fl_secn / fl.fl_fd.fd_nspt;
607: fl.fl_head = fl.fl_fcyl / fl.fl_fd.fd_trks;
608: fl.fl_fcyl = fl.fl_fcyl % fl.fl_fd.fd_trks;
609: }
610:
611: flput(CMDSEEK);
612: flput((fl.fl_head<<2) | fl.fl_unit);
613:
614: if ( fl.fl_fd.fd_trks == 80 )
615: flput(fl.fl_fcyl);
616: else if ( fl.fl_type[fl.fl_unit] == 2 )
617: flput(fl.fl_fcyl << 1); /* double step */
618: else if ( fl.fl_type[fl.fl_unit] == 4 )
619: flput(fl.fl_fcyl << 1); /* double step */
620: else
621: flput(fl.fl_fcyl);
622:
623: fl.fl_state = SHDLY;
624: break;
625:
626: case SHDLY:
627: /*
628: * Delay for minimum 15 milliseconds after seek before w/fmt.
629: * 2 clock ticks would give 10-20 millisecond [100 Hz clock].
630: * 3 clock ticks gives 20-30 millisecond [100 Hz clock].
631: */
632: if ( bp->b_req != BREAD ) {
633: timeout( &fltim, 3, fldelay, SRDWR );
634: fl.fl_state = SDELAY;
635: break;
636: }
637: /* no break */
638:
639: case SRDWR:
640: /*
641: * Disable watchdog timer while waiting to lock DMA controller.
642: */
643: fl.fl_time[fl.fl_unit] = -1;
644:
645: /*
646: * Next state will be DMA locked state.
647: */
648: fl.fl_state = SLOCK;
649:
650: /*
651: * If DMA controller locked by someone else, exit for now.
652: */
653: if ( dmalock( &fldmalck, flfsm, 0 ) != 0 )
654: return;
655:
656: case SLOCK:
657: /*
658: * Reset watchdog timer to restart timeout sequence.
659: */
660: fl.fl_time[fl.fl_unit] = 0;
661:
662: flcmd = CMDRDAT;
663: fl.fl_wflag = 0;
664:
665: if (bp->b_req == BREAD)
666: ;
667:
668: else if (bp->b_req == BWRITE) {
669: fl.fl_wflag = 1;
670: flcmd = CMDWDAT;
671: }
672:
673: else {
674: fl.fl_wflag = 1;
675: flcmd = CMDFMT;
676:
677: if(dmaon(2, fl.fl_addr, bp->b_count, fl.fl_wflag) == 0)
678: goto straddle;
679:
680: else
681: goto command;
682: }
683:
684: if (dmaon(2, fl.fl_addr, 512, fl.fl_wflag) == 0) {
685: straddle:
686: devmsg(bp->b_dev, "fd: DMA page straddle at %x:%x",
687: fl.fl_addr);
688: dmaunlock( &fldmalck );
689: bp->b_flag |= BFERR;
690: fldone( bp );
691: goto again;
692: }
693: command:
694: dmago(2);
695: flput(flcmd);
696: flput((fl.fl_head<<2) | fl.fl_unit);
697:
698: if (bp->b_req == FDFORMAT) {
699: flput(fl.fl_fd.fd_N); /* N */
700: flput(fl.fl_fd.fd_nspt); /* SC */
701: flput(fl.fl_fd.fd_FGPL); /* GPL */
702: flput(0xF6); /* D */
703: }
704:
705: else {
706: flput(fl.fl_fcyl);
707: flput(fl.fl_head);
708: flput(fl.fl_fsec);
709: flput(fl.fl_fd.fd_N); /* N */
710: flput(fl.fl_fd.fd_nspt); /* EOT */
711: flput(fl.fl_fd.fd_GPL[fl.fl_rate]); /* GPL */
712: flput(0xFF); /* DTL */
713: }
714:
715: fl.fl_state = SENDIO;
716: break;
717:
718: case SENDIO:
719: fl.fl_time[fl.fl_unit] = 0;
720: dmaoff(2);
721: dmaunlock( &fldmalck );
722:
723: if ((fl.fl_cmdstat[0]&ST0_IC) != ST0_NT) {
724: if (++fl.fl_nerr < 5) {
725: fl.fl_incal[fl.fl_unit] = 0;
726: fl.fl_state = SSEEK;
727: }
728:
729: else {
730: flstatus();
731: bp->b_flag |= BFERR;
732: fldone(bp);
733: }
734: }
735:
736: else if (--fl.fl_nsec == 0) {
737: bp->b_resid = 0;
738: fldone(bp);
739: }
740:
741: else {
742: ++fl.fl_secn;
743: fl.fl_addr += 512; /* 512 == fl.fl_fd.fd_nbps */
744: fl.fl_state = SSEEK;
745: }
746:
747: /*
748: * Delay for minimum 1.5 msecs after writing before seek.
749: */
750: if ( fl.fl_wflag ) {
751: timeout( &fltim, 2, fldelay, fl.fl_state );
752: fl.fl_state = SDELAY;
753: break;
754: }
755:
756: goto again;
757:
758: case SDELAY:
759: /*
760: * Ignore interrupts until timeout occurs.
761: */
762: break;
763:
764: default:
765: panic("fds");
766: }
767: }
768:
769: /*
770: * Delay before initiating next operation.
771: * This allows the floppy motor to turn on,
772: * the head to settle before writing,
773: * the erase head to turn off after writing, etc.
774: */
775: static
776: fldelay( state )
777: int state;
778: {
779: int s;
780:
781: s = sphi();
782: if ( fl.fl_state == SDELAY ) {
783: fl.fl_state = state;
784: flfsm();
785: }
786: spl( s );
787: }
788:
789: /*
790: * The flrate function returns the data rate for the flopen and flfsm routines.
791: */
792: static int
793: flrate( dev )
794: register dev_t dev;
795: {
796: register int rate;
797:
798: /*
799: * Default is 250 Kbps.
800: */
801: rate = 2;
802:
803: /*
804: * Check for high capacity drive.
805: */
806: if ( fl.fl_type[ funit(dev) ] == 2 ) {
807:
808: /*
809: * 300 Kbps.
810: */
811: rate--;
812:
813: /*
814: * Check for high capacity media.
815: */
816: if ( fdata[ fkind(dev) ].fd_nspt == 15 ) {
817:
818: /*
819: * 500 Kbps.
820: */
821: rate--;
822: }
823: } else if (fl.fl_type[funit(dev)] == 4 && fkind(dev) == 7)
824: rate = 0;
825:
826: return( rate );
827: }
828:
829: /*
830: * This routine is called by the
831: * clock handler every second. If the drive
832: * has been idle for a long time it turns off
833: * the motor and shuts off the timeouts.
834: */
835:
836: static
837: fltimeout()
838: {
839: register int unit;
840: register int mask;
841: register int s;
842:
843: s = sphi();
844:
845: /*
846: * Scan all drives, looking for motor timeouts.
847: */
848: for ( unit=0, mask=0x10; unit < 4; unit++, mask <<= 1 ) {
849:
850: /*
851: * Ignore drives which aren't spinning.
852: */
853: if ( (fl.fl_mstatus & mask) == 0 )
854: continue;
855:
856: /*
857: * If timer is disabled (i.e. we are waiting for the DMA
858: * controller), go on to the next drive.
859: */
860: if ( fl.fl_time[unit] < 0 )
861: continue;
862:
863: /*
864: * Leave recently accessed (in last 4 seconds) drives spinning.
865: */
866: if ( ++fl.fl_time[unit] < MTIMER )
867: continue;
868:
869: /*
870: * Timeout drives which have been inactive for 5 seconds.
871: */
872: fl.fl_mstatus &= ~mask;
873:
874: /*
875: * Not selected drive, or selected drive is idle.
876: */
877: if ( (unit != fl.fl_unit) || (fl.fl_state == SIDLE) )
878: continue;
879:
880: /*
881: * Active drive did not complete operation within 5 seconds.
882: * Attempt recovery.
883: */
884: flrecov();
885:
886: /*
887: * Initiate next block request.
888: */
889: if ( fl.fl_state == SIDLE )
890: flfsm();
891: }
892:
893: /*
894: * Physically turn off drives which timed out.
895: */
896: outb(FDCDOR, DORNMR | DORIEN | fl.fl_mstatus | fl.fl_unit);
897:
898: /*
899: * Stop checking once all drives have been stopped.
900: */
901: if ( fl.fl_mstatus == 0 )
902: drvl[FL_MAJOR].d_time = 0;
903:
904: spl(s);
905: }
906:
907: /*
908: * The recovery routine resets and reprograms the floppy controller,
909: * and discards any queued requests on the current drive.
910: * This is required if the floppy door is open, or diskette is missing.
911: */
912:
913: flrecov()
914: {
915: register BUF * bp;
916: register dev_t dev;
917:
918: /*
919: * Disable DMA transfer.
920: * Reset floppy controller.
921: */
922: dmaoff( 2 );
923:
924: /*
925: * Unlock the controller if locked by us.
926: */
927: dmaunlock( &fldmalck );
928:
929: outb(FDCDOR, 0);
930: outb(FDCDOR, DORNMR);
931:
932: /*
933: * Program transfer bps.
934: */
935: if ( fl.fl_rate != 2 )
936: outb( FDCRATE, fl.fl_rate );
937:
938: /*
939: * Program floppy controller.
940: */
941: flput( CMDSPEC );
942: flput( (fl_srt << 4) | fl_hut );
943: flput( fl_hlt << 1 );
944:
945: /*
946: * Drives are no longer in calibration.
947: */
948: fl.fl_incal[0] =
949: fl.fl_incal[1] =
950: fl.fl_incal[2] =
951: fl.fl_incal[3] = 0;
952:
953: /*
954: * Abort all block requests on current drive after 1st recov attempt.
955: */
956: if ( bp = fl.fl_actf ) {
957: printf("fd%d: <Door Open>\n", fl.fl_unit );
958: dev = bp->b_dev;
959: do {
960: bp->b_flag |= BFERR;
961: fldone( bp );
962: } while ( (bp = fl.fl_actf) && (bp->b_dev == dev) );
963: }
964:
965: /*
966: * Delay before setting controller state to idle.
967: * This gives time for spurious floppy interrupts to occur.
968: * NOTE: Can't call flfsm(), since it may call us [future revision].
969: */
970: timeout( &fltim, HZ/4, fldelay, SIDLE );
971: fl.fl_state = SDELAY;
972: }
973:
974: /*
975: * The interrupt routine gets all
976: * the status bytes the controller chip
977: * will give it, then issues a sense interrupt
978: * status command (which is necessary for a seek
979: * to complete!) and throws all of the status
980: * bytes away.
981: */
982:
983: static
984: flintr()
985: {
986: register int s;
987:
988: s = sphi();
989: flsense();
990:
991: if (fl.fl_state != SIDLE)
992: flfsm();
993:
994: spl(s);
995: }
996:
997: /*
998: * Fldone() returns current request to operating system.
999: */
1000: fldone( bp )
1001: register BUF * bp;
1002: {
1003: fl.fl_actf = bp->b_actf;
1004: fl.fl_state = SIDLE;
1005: bdone( bp );
1006: }
1007:
1008: /*
1009: * Flsense() issues a sense interrupt status command
1010: * to restore the controller to a quiescent state.
1011: */
1012:
1013: static
1014: flsense()
1015: {
1016: register int b;
1017: register int n;
1018: register int i = 0;
1019: register int s;
1020:
1021: s = sphi();
1022:
1023: /*
1024: * Read all the status bytes the controller will give us.
1025: */
1026: n = 0;
1027:
1028: for (;;) {
1029: while (((b=inb(FDCMSR))&MSRRQM) == 0) {
1030: if ( --i == 0 ) {
1031: printf("flintr: timeout\n");
1032: break;
1033: }
1034: }
1035:
1036: if ((b&MSRDIO) == 0)
1037: break;
1038:
1039: b = inb(FDCDAT);
1040: if ( n < sizeof(fl.fl_cmdstat) )
1041: fl.fl_cmdstat[n++] = b;
1042: }
1043:
1044: fl.fl_ncmdstat = n;
1045:
1046: /*
1047: * Issue a sense interrupt command and discard result.
1048: */
1049: outb(FDCDAT, CMDSINT);
1050:
1051: n = 0;
1052: for (;;) {
1053: while (((b=inb(FDCMSR))&MSRRQM) == 0) {
1054: if ( --i == 0 ) {
1055: printf("flsense: timeout\n");
1056: break;
1057: }
1058: }
1059:
1060: if ((b&MSRDIO) == 0)
1061: break;
1062:
1063: b = inb(FDCDAT);
1064: if ( n < sizeof(fl.fl_intstat) )
1065: fl.fl_intstat[n++] = b;
1066: }
1067: fl.fl_nintstat = n;
1068:
1069: spl( s );
1070: }
1071:
1072: /*
1073: * Send a command byte to the
1074: * NEC chip, first waiting until the chip
1075: * says that it is ready. No timeout is
1076: * performed; if the chip dies, we do too!
1077: */
1078:
1079: static
1080: flput( b )
1081:
1082: int b;
1083:
1084: {
1085: register int i = 0;
1086:
1087: while ( (inb(FDCMSR) & (MSRRQM|MSRDIO)) != MSRRQM ) {
1088: if ( --i == 0 ) {
1089: printf("flput: timeout\n");
1090: return;
1091: }
1092: }
1093:
1094: outb(FDCDAT, b);
1095: }
1096:
1097: /*
1098: * Dissassemble the floppy error status for user reference.
1099: */
1100:
1101: static
1102: flstatus()
1103: {
1104: printf("fd%d: head=%u cyl=%u",
1105: fl.fl_cmdstat[0] & 3,
1106: fl.fl_head, fl.fl_fcyl );
1107:
1108: /*
1109: * Report on ST0 bits.
1110: */
1111: if ( fl.fl_ncmdstat >= 1 ) {
1112: if ( fl.fl_cmdstat[0] & ST0_NR )
1113: printf(" <Not Ready>");
1114:
1115: if ( fl.fl_cmdstat[0] & ST0_EC )
1116: printf(" <Equipment Check>");
1117: }
1118:
1119: /*
1120: * Report on ST1 bits.
1121: */
1122: if ( fl.fl_ncmdstat >= 2 ) {
1123: if ( fl.fl_cmdstat[1] & ST1_MA )
1124: printf(" <Missing Address Mark>");
1125:
1126: if ( fl.fl_cmdstat[1] & ST1_NW )
1127: printf(" <Write Protected>");
1128:
1129: if ( fl.fl_cmdstat[1] & ST1_ND )
1130: printf(" <No Data>");
1131:
1132: if ( fl.fl_cmdstat[1] & ST1_OR )
1133: printf(" <Overrun>");
1134:
1135: if ( fl.fl_cmdstat[1] & ST1_DE )
1136: printf(" <Data Error>");
1137:
1138: if ( fl.fl_cmdstat[1] & ST1_EN )
1139: printf(" <End of Cyl>");
1140: }
1141:
1142: /*
1143: * Report on ST2 bits.
1144: */
1145: if ( fl.fl_ncmdstat >= 3 ) {
1146: if ( fl.fl_cmdstat[2] & ST2_MD )
1147: printf(" <Missing Data Address Mark>");
1148:
1149: if ( fl.fl_cmdstat[2] & ST2_BC )
1150: printf(" <Bad Cylinder>");
1151:
1152: if ( fl.fl_cmdstat[2] & ST2_WC )
1153: printf(" <Wrong Cylinder>");
1154:
1155: if ( fl.fl_cmdstat[2] & ST2_DD )
1156: printf(" <Bad Data CRC>");
1157:
1158: if ( fl.fl_cmdstat[2] & ST2_CM )
1159: printf(" <Data Deleted>");
1160: }
1161:
1162: printf("\n");
1163: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.