|
|
1.1 root 1: /*-
2: * Copyright (c) 1990 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * This code is derived from software contributed to Berkeley by
6: * Don Ahn.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed by the University of
19: * California, Berkeley and its contributors.
20: * 4. Neither the name of the University nor the names of its contributors
21: * may be used to endorse or promote products derived from this software
22: * without specific prior written permission.
23: *
24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34: * SUCH DAMAGE.
35: *
36: * @(#)fd.c 7.4 (Berkeley) 5/25/91
37: */
38:
39: #include "fd.h"
1.1.1.4 ! root 40: #if NFDC > 0
1.1 root 41:
42: #include "param.h"
43: #include "dkbad.h"
44: #include "systm.h"
45: #include "conf.h"
46: #include "file.h"
47: #include "ioctl.h"
48: #include "buf.h"
49: #include "uio.h"
50: #include "i386/isa/isa_device.h"
51: #include "i386/isa/fdreg.h"
52: #include "i386/isa/icu.h"
1.1.1.3 root 53: #include "i386/isa/rtc.h"
1.1 root 54:
1.1.1.2 root 55: #define FDUNIT(s) ((s>>3)&1)
56: #define FDTYPE(s) ((s)&7)
1.1 root 57:
58: #define b_cylin b_resid
59: #define b_step b_resid
60: #define FDBLK 512
1.1.1.4 ! root 61: #define NUMTYPES 4+1
1.1 root 62:
63: struct fd_type {
64: int sectrac; /* sectors per track */
65: int secsize; /* size code for sectors */
66: int datalen; /* data len when secsize = 0 */
67: int gap; /* gap len between sectors */
68: int tracks; /* total num of tracks */
69: int size; /* size of disk in sectors */
70: int steptrac; /* steps per cylinder */
71: int trans; /* transfer speed code */
72: };
73:
74: struct fd_type fd_types[NUMTYPES] = {
1.1.1.4 ! root 75: { 0 }, /* non-existant */
1.1 root 76: { 18,2,0xFF,0x1B,80,2880,1,0 }, /* 1.44 meg HD 3.5in floppy */
77: { 15,2,0xFF,0x1B,80,2400,1,0 }, /* 1.2 meg HD floppy */
78: { 9,2,0xFF,0x23,40,720,2,1 }, /* 360k floppy in 1.2meg drive */
79: { 9,2,0xFF,0x2A,40,720,1,1 }, /* 360k floppy in DD drive */
80: };
81:
82: struct fd_u {
83: int type; /* Drive type (HD, DD */
84: int active; /* Drive activity boolean */
85: int motor; /* Motor on flag */
86: struct buf head; /* Head of buf chain */
87: struct buf rhead; /* Raw head of buf chain */
88: int reset;
89: } fd_unit[NFD];
90:
91:
1.1.1.3 root 92: struct buf fdtab, fdutab[NFD]; /* controller activity */
1.1 root 93: extern int hz;
94:
95: /* state needed for current transfer */
96: static fdc; /* floppy disk controller io base register */
1.1.1.3 root 97: int fd_dmachan;
1.1 root 98: static int fd_skip;
99: static int fd_state;
100: static int fd_retry;
101: static int fd_drive;
1.1.1.3 root 102: static int fd_hddrv;
1.1 root 103: static int fd_track = -1;
104: static int fd_status[7];
105:
106: /****************************************************************************/
107: /* autoconfiguration stuff */
108: /****************************************************************************/
1.1.1.4 ! root 109: int fdprobe(struct isa_device *);
! 110: int fdattach(struct isa_device *);
! 111: int fd_turnoff(int);
1.1 root 112:
1.1.1.4 ! root 113: struct isa_driver fdcdriver = {
! 114: fdprobe, fdattach, "fdc",
1.1 root 115: };
116:
1.1.1.3 root 117: /*
118: * probe for existance of controller
119: */
1.1.1.4 ! root 120: fdprobe(struct isa_device *dev)
1.1 root 121: {
1.1.1.3 root 122: fdc = dev->id_iobase;
123:
124: /* see if it can handle a command */
125: if (out_fdc(NE7CMD_SPECIFY) < 0) {
126: fdc = 0;
127: return(0);
128: }
129: out_fdc(0xDF);
130: out_fdc(2);
1.1.1.4 ! root 131: return 8;
1.1 root 132: }
133:
1.1.1.3 root 134: /*
135: * wire controller into system, look for floppy units
136: */
1.1.1.4 ! root 137: fdattach(struct isa_device *dev)
1.1.1.3 root 138: {
1.1.1.4 ! root 139: unsigned fdt, unit, fddrive, fdunit;
! 140: extern struct isa_device isa_biotab_fdc[];
! 141: struct isa_device *fdutab;
! 142: unsigned st0, cyl;
1.1.1.3 root 143:
144: fd_dmachan = dev->id_drq;
145:
146: fdt = rtcin(RTC_FDISKETTE);
1.1.1.4 ! root 147: unit = dev->id_unit;
! 148: if (unit >= NFDC)
! 149: return;
1.1.1.3 root 150:
1.1.1.4 ! root 151: for (fdutab = isa_biotab_fdc; fdutab->id_driver != 0; fdutab++) {
! 152: fdunit = fdutab->id_unit;
! 153: if (fdunit >= NFD)
! 154: continue;
! 155: fddrive = fdutab->id_physid;
! 156: if (fddrive == 1)
! 157: fdt <<= 4;
! 158:
1.1.1.3 root 159: /* is there a unit? */
1.1.1.4 ! root 160: if ((fdt & 0xf0) == RTCFDT_NONE) {
! 161: /*printf("fd%d: <no drive> on fdc%d slave %d\n", fddrive,
! 162: dev->id_unit, fdunit);*/
1.1.1.3 root 163: continue;
1.1.1.4 ! root 164: }
1.1.1.3 root 165:
1.1.1.4 ! root 166: fd_turnon(fddrive);
1.1.1.3 root 167: DELAY(10000);
168: out_fdc(NE7CMD_RECAL); /* Recalibrate Function */
1.1.1.4 ! root 169: out_fdc(fddrive);
! 170: DELAY(30000);
! 171: out_fdc(NE7CMD_SENSEI); /* anything responding */
1.1.1.3 root 172: st0 = in_fdc();
173: cyl = in_fdc();
174: if (st0 & 0xd0)
175: continue;
176:
177: if ((fdt & 0xf0) == RTCFDT_12M) {
1.1.1.4 ! root 178: printf("fd%d at fdc%d slave %d: <1.2M>\n", fddrive,
! 179: dev->id_unit, fdunit);
! 180: fd_unit[fdunit].type = 2;
1.1.1.3 root 181: }
182: if ((fdt & 0xf0) == RTCFDT_144M) {
1.1.1.4 ! root 183: printf("fd%d at fdc%d slave %d: <1.44M>\n", fddrive,
! 184: dev->id_unit, fdunit);
! 185: fd_unit[fdunit].type = 1;
1.1.1.3 root 186: }
187:
1.1.1.4 ! root 188: outb(fdc+fdctl,0); /* Set transfer to 500kbps */
1.1 root 189:
1.1.1.4 ! root 190: fd_turnoff(fddrive);
! 191: }
1.1 root 192: }
193:
194: int
195: fdsize(dev)
196: dev_t dev;
197: {
1.1.1.3 root 198: return(0);
1.1 root 199: }
200:
201: /****************************************************************************/
202: /* fdstrategy */
203: /****************************************************************************/
204: fdstrategy(bp)
205: register struct buf *bp; /* IO operation to perform */
206: {
207: register struct buf *dp,*dp0,*dp1;
208: long nblocks,blknum;
209: int unit, type, s;
210:
211: unit = FDUNIT(minor(bp->b_dev));
1.1.1.3 root 212: /*type = FDTYPE(minor(bp->b_dev));*/
213: type = fd_unit[unit].type;
1.1.1.4 ! root 214: if(type == 0) {
! 215: bp->b_error = EINVAL;
! 216: bp->b_flags |= B_ERROR;
! 217: goto bad;
! 218: }
1.1 root 219:
220: #ifdef FDTEST
221: printf("fdstrat%d, blk = %d, bcount = %d, addr = %x|",
222: unit, bp->b_blkno, bp->b_bcount,bp->b_un.b_addr);
223: #endif
224: if ((unit >= NFD) || (bp->b_blkno < 0)) {
225: printf("fdstrat: unit = %d, blkno = %d, bcount = %d\n",
226: unit, bp->b_blkno, bp->b_bcount);
227: pg("fd:error in fdstrategy");
228: bp->b_error = EINVAL;
229: bp->b_flags |= B_ERROR;
230: goto bad;
231: }
232: /*
233: * Set up block calculations.
234: */
235: blknum = (unsigned long) bp->b_blkno * DEV_BSIZE/FDBLK;
236: nblocks = fd_types[type].size;
237: if (blknum + (bp->b_bcount / FDBLK) > nblocks) {
238: if (blknum == nblocks) {
239: bp->b_resid = bp->b_bcount;
240: } else {
241: bp->b_error = ENOSPC;
242: bp->b_flags |= B_ERROR;
243: }
244: goto bad;
245: }
246: bp->b_cylin = blknum / (fd_types[type].sectrac * 2);
247: dp = &fd_unit[unit].head;
248: dp->b_step = (fd_types[fd_unit[unit].type].steptrac);
249: s = splbio();
250: disksort(dp, bp);
1.1.1.3 root 251: if (dp->b_active == 0) {
1.1 root 252: #ifdef FDDEBUG
253: printf("T|");
254: #endif
255: dp->b_active = 1;
256: fd_drive = unit;
257: fd_track = -1; /* force seek on first xfer */
258: untimeout(fd_turnoff,unit);
259: fdstart(unit); /* start drive if idle */
260: }
261: splx(s);
262: return;
263:
264: bad:
265: biodone(bp);
266: }
267:
268: /****************************************************************************/
269: /* motor control stuff */
270: /****************************************************************************/
271: set_motor(unit,reset)
272: int unit,reset;
273: {
274: int m0,m1;
275: m0 = fd_unit[0].motor;
276: m1 = fd_unit[1].motor;
1.1.1.3 root 277: outb(fdc+fdout, (unit&FDO_FDSEL)
278: | (reset ? 0 : (FDO_FRST|FDO_FDMAEN))
279: | (m0 ? FDO_MOEN0 : 0)
280: | (m1 ? FDO_MOEN1 : 0));
1.1 root 281: }
282:
283: fd_turnoff(unit)
284: int unit;
285: {
286: fd_unit[unit].motor = 0;
287: if (unit) set_motor(0,0);
288: else set_motor(1,0);
289: }
290:
291: fd_turnon(unit)
292: int unit;
293: {
294: fd_unit[unit].motor = 1;
295: set_motor(unit,0);
296: }
297:
298: /****************************************************************************/
299: /* fdc in/out */
300: /****************************************************************************/
301: int
302: in_fdc()
303: {
1.1.1.3 root 304: int i, j = 100000;
305: while ((i = inb(fdc+fdsts) & (NE7_DIO|NE7_RQM)) != (NE7_DIO|NE7_RQM) && j-- > 0)
1.1 root 306: if (i == NE7_RQM) return -1;
1.1.1.3 root 307: if (j <= 0)
308: return(-1);
1.1 root 309: return inb(fdc+fddata);
310: }
311:
312: out_fdc(x)
313: int x;
314: {
1.1.1.3 root 315: int i = 100000;
1.1 root 316:
1.1.1.3 root 317: while ((inb(fdc+fdsts) & NE7_DIO) && i-- > 0);
318: while ((inb(fdc+fdsts) & NE7_RQM) == 0 && i-- > 0);
319: if (i <= 0) return (-1);
320: outb(fdc+fddata,x);
321: return (0);
1.1 root 322: }
323:
1.1.1.3 root 324: static fdopenf;
1.1 root 325: /****************************************************************************/
326: /* fdopen/fdclose */
327: /****************************************************************************/
328: Fdopen(dev, flags)
329: dev_t dev;
330: int flags;
331: {
332: int unit = FDUNIT(minor(dev));
1.1.1.4 ! root 333: int type = fd_unit[unit].type;
1.1 root 334: int s;
335:
1.1.1.3 root 336: fdopenf = 1;
1.1 root 337: /* check bounds */
338: if (unit >= NFD) return(ENXIO);
1.1.1.4 ! root 339: if (type >= NUMTYPES || type==0)
! 340: return ENXIO;
1.1 root 341:
342: /* Set proper disk type, only allow one type */
343: return 0;
344: }
345:
346: fdclose(dev, flags)
347: dev_t dev;
348: {
1.1.1.2 root 349: return(0);
1.1 root 350: }
351:
352:
353: /****************************************************************************/
354: /* fdstart */
355: /****************************************************************************/
356: fdstart(unit)
357: int unit;
358: {
359: register struct buf *dp,*bp;
360: int s;
361:
362: #ifdef FDTEST
363: printf("st%d|",unit);
364: #endif
1.1.1.3 root 365: dp = &fd_unit[unit].head;
366: bp = dp->b_actf;
1.1 root 367: s = splbio();
368: if (!fd_unit[unit].motor) {
369: fd_turnon(unit);
1.1.1.3 root 370: #ifdef notdef
371: if ((bp->b_flags & B_READ) == 0) {
372: /* Wait for 1 sec */
373: #endif
374: timeout(fdstart,unit,hz);
375: /*}*/
376: } else
1.1 root 377: {
378: /* make sure drive is selected as well as on */
379:
380: fd_retry = 0;
381: if (fd_unit[unit].reset) fd_state = 1;
382: else {
383: /* DO a RESET */
384: fd_unit[unit].reset = 1;
385: fd_state = 5;
386: }
387: fd_skip = 0;
388: #ifdef FDDEBUG
389: printf("Seek %d %d\n", bp->b_cylin, dp->b_step);
390: #endif
391: if (bp->b_cylin != fd_track) {
392: /* Seek necessary, never quite sure where head is at! */
1.1.1.3 root 393: out_fdc(NE7CMD_SEEK); /* Seek function */
1.1 root 394: out_fdc(unit); /* Drive number */
395: out_fdc(bp->b_cylin * dp->b_step);
1.1.1.3 root 396: fd_state = 6;
397: } else {
398: fd_state = 1;
399: fdintr(0xff);
400: }
1.1 root 401: }
402: splx(s);
403: }
404:
405: fd_timeout(x)
406: int x;
407: {
1.1.1.3 root 408: int st0, st3, cyl;
1.1 root 409: struct buf *dp,*bp;
410:
411: dp = &fd_unit[fd_drive].head;
412: bp = dp->b_actf;
413:
1.1.1.3 root 414: out_fdc(NE7CMD_SENSED);
415: out_fdc(fd_hddrv);
416: st3 = in_fdc();
417:
418: out_fdc(NE7CMD_SENSEI);
419: st0 = in_fdc();
420: cyl = in_fdc();
421: printf("fd%d: Operation timeout ST0 %b cyl %d ST3 %b\n", fd_drive,
422: st0, NE7_ST0BITS, cyl, st3, NE7_ST3BITS);
1.1 root 423:
1.1.1.3 root 424: if (bp) {
425: fd_state = 4;
426: fdintr(fd_drive);
427: }
1.1 root 428: }
429:
430: /****************************************************************************/
431: /* fdintr */
432: /****************************************************************************/
433: fdintr(unit)
434: {
435: register struct buf *dp,*bp;
436: struct buf *dpother;
1.1.1.3 root 437: int read,head,trac,sec,i,s,sectrac,cyl,st0;
1.1 root 438: unsigned long blknum;
439: struct fd_type *ft;
440:
441: #ifdef FDTEST
442: printf("state %d, unit %d, dr %d|",fd_state,unit,fd_drive);
443: #endif
444:
1.1.1.3 root 445: if (!fdopenf) return;
1.1 root 446: dp = &fd_unit[fd_drive].head;
447: bp = dp->b_actf;
448: read = bp->b_flags & B_READ;
1.1.1.3 root 449: /*ft = &fd_types[FDTYPE(bp->b_dev)];*/
450: ft = &fd_types[fd_unit[fd_drive].type];
1.1 root 451:
452: switch (fd_state) {
453: case 1 : /* SEEK DONE, START DMA */
454: /* Make sure seek really happened*/
455: if (unit != 0xff) {
1.1.1.3 root 456: int descyl = bp->b_cylin * dp->b_step;
457: out_fdc(NE7CMD_SENSEI);
1.1 root 458: i = in_fdc();
459: cyl = in_fdc();
1.1.1.3 root 460: if (cyl != descyl) {
461: printf("fd%d: Seek to cyl %d failed; am at cyl %d (ST0 = %b)\n", fd_drive,
462: descyl, cyl, i, NE7_ST0BITS);
463: fd_state = 4;
1.1 root 464: return;
465: }
466: }
467:
468: fd_track = bp->b_cylin;
1.1.1.3 root 469: isa_dmastart(bp->b_flags, bp->b_un.b_addr+fd_skip,
470: FDBLK, fd_dmachan);
1.1 root 471: blknum = (unsigned long)bp->b_blkno*DEV_BSIZE/FDBLK
472: + fd_skip/FDBLK;
473: sectrac = ft->sectrac;
474: sec = blknum % (sectrac * 2);
475: head = sec / sectrac;
476: sec = sec % sectrac + 1;
1.1.1.3 root 477: fd_hddrv = ((head&1)<<2)+fd_drive;
1.1 root 478:
1.1.1.3 root 479: if (read) out_fdc(NE7CMD_READ); /* READ */
480: else out_fdc(NE7CMD_WRITE); /* WRITE */
1.1 root 481: out_fdc(head << 2 | fd_drive); /* head & unit */
482: out_fdc(fd_track); /* track */
483: out_fdc(head);
484: out_fdc(sec); /* sector XXX +1? */
485: out_fdc(ft->secsize); /* sector size */
486: out_fdc(sectrac); /* sectors/track */
487: out_fdc(ft->gap); /* gap size */
488: out_fdc(ft->datalen); /* data length */
489: fd_state = 2;
490: break;
491: case 2 : /* IO DONE, post-analyze */
492: untimeout(fd_timeout,2);
493: for(i=0;i<7;i++) {
494: fd_status[i] = in_fdc();
495: }
496: if (fd_status[0]&0xF8) {
497: #ifdef FDOTHER
498: printf("status0 err %d:",fd_status[0]);
499: #endif
500: goto retry;
501: }
502: /* All OK */
1.1.1.3 root 503: isa_dmadone(bp->b_flags, bp->b_un.b_addr+fd_skip,
504: FDBLK, fd_dmachan);
1.1 root 505: fd_skip += FDBLK;
506: if (fd_skip >= bp->b_bcount) {
507: #ifdef FDTEST
508: printf("DONE %d|", bp->b_blkno);
509: #endif
510: /* ALL DONE */
511: fd_skip = 0;
512: bp->b_resid = 0;
513: dp->b_actf = bp->av_forw;
514: biodone(bp);
515: nextstate(dp);
516:
517: } else {
518: #ifdef FDDEBUG
519: printf("next|");
520: #endif
521: /* set up next transfer */
522: blknum = (unsigned long)bp->b_blkno*DEV_BSIZE/FDBLK
523: + fd_skip/FDBLK;
524: fd_state = 1;
525: bp->b_cylin = (blknum / (ft->sectrac * 2));
526: if (bp->b_cylin != fd_track) {
527: #ifdef FDTEST
528: printf("Seek|");
529: #endif
530: /* SEEK Necessary */
1.1.1.3 root 531: out_fdc(NE7CMD_SEEK); /* Seek function */
1.1 root 532: out_fdc(fd_drive);/* Drive number */
533: out_fdc(bp->b_cylin * dp->b_step);
1.1.1.3 root 534: fd_state = 6;
1.1 root 535: break;
536: } else fdintr(0xff);
537: }
538: break;
539: case 3:
1.1.1.3 root 540: out_fdc(NE7CMD_SENSEI);
541: st0 = in_fdc();
542: cyl = in_fdc();
543: if (cyl != 0)
544: printf("fd%d: recal failed ST0 %b cyl %d\n", fd_drive,
545: st0, NE7_ST0BITS, cyl);
546:
1.1 root 547: /* Seek necessary */
1.1.1.3 root 548: out_fdc(NE7CMD_SEEK); /* Seek function */
1.1 root 549: out_fdc(fd_drive);/* Drive number */
550: out_fdc(bp->b_cylin * dp->b_step);
1.1.1.3 root 551: fd_state = 6;
1.1 root 552: break;
553: case 4:
1.1.1.3 root 554: out_fdc(NE7CMD_SPECIFY); /* specify command */
1.1 root 555: out_fdc(0xDF);
556: out_fdc(2);
1.1.1.3 root 557: out_fdc(NE7CMD_RECAL); /* Recalibrate Function */
1.1 root 558: out_fdc(fd_drive);
1.1.1.3 root 559: fd_state = 7;
1.1 root 560: break;
561: case 5:
562: #ifdef FDOTHER
563: printf("**RESET**\n");
564: #endif
565: /* Try a reset, keep motor on */
566: set_motor(fd_drive,1);
1.1.1.3 root 567: DELAY(100);
1.1 root 568: set_motor(fd_drive,0);
569: outb(fdc+fdctl,ft->trans);
570: fd_retry++;
571: fd_state = 4;
572: break;
1.1.1.3 root 573: case 6:
574: /* allow heads to settle */
575: timeout(fdintr,fd_drive,hz/30);
576: fd_state = 1;
577: return;
578: break;
579:
580: case 7:
581: /* allow heads to settle */
582: timeout(fdintr,fd_drive,hz/3);
583: fd_state = 3;
584: return;
585: break;
586:
1.1 root 587: default:
588: printf("Unexpected FD int->");
1.1.1.3 root 589: out_fdc(NE7CMD_SENSEI);
590: st0 = in_fdc();
591: cyl = in_fdc();
1.1 root 592: printf("ST0 = %lx, PCN = %lx\n",i,sec);
593: out_fdc(0x4A);
594: out_fdc(fd_drive);
595: for(i=0;i<7;i++) {
596: fd_status[i] = in_fdc();
597: }
598: printf("intr status :%lx %lx %lx %lx %lx %lx %lx ",
599: fd_status[0], fd_status[1], fd_status[2], fd_status[3],
600: fd_status[4], fd_status[5], fd_status[6] );
601: break;
602: }
603: return;
604: retry:
605: switch(fd_retry) {
606: case 0: case 1:
1.1.1.3 root 607: case 2:
1.1 root 608: break;
1.1.1.3 root 609: case 3:
1.1 root 610: case 4:
1.1.1.3 root 611: case 5:
612: fd_retry++;
613: fd_state = 4;
614: fdintr(0xff);
615: return;
616: case 6:
1.1 root 617: fd_retry++;
618: fd_state = 5;
619: fdintr(0xff);
620: return;
1.1.1.3 root 621: case 7:
1.1 root 622: break;
623: default:
1.1.1.3 root 624: /*printf("fd%d: hard error (ST0 %b ST1 %b ST2 %b ST3 %b cyl %d hd %d sec %d)\n",
625: fd_drive, fd_status[0], NE7_ST0BITS, fd_status[1], NE7_ST1BITS,
626: fd_status[2], NE7_ST2BITS, fd_status[3], NE7_ST3BITS,
627: fd_status[4], fd_status[5], fd_status[6]);*/
628: printf("fd%d: hard error (ST0 %b ", fd_drive, fd_status[0], NE7_ST0BITS);
629: printf(" ST1 %b ", fd_status[1], NE7_ST1BITS);
630: printf(" ST2 %b ", fd_status[2], NE7_ST2BITS);
631: printf(" ST3 %b ", fd_status[3], NE7_ST3BITS);
632: printf("cyl %d hd %d sec %d)\n", fd_status[4], fd_status[5], fd_status[6]);
1.1 root 633: badtrans(dp,bp);
634: return;
635: }
636: fd_state = 1;
637: fd_retry++;
638: fdintr(0xff);
639: }
640:
641: badtrans(dp,bp)
642: struct buf *dp,*bp;
643: {
644:
645: bp->b_flags |= B_ERROR;
646: bp->b_error = EIO;
647: bp->b_resid = bp->b_bcount - fd_skip;
648: dp->b_actf = bp->av_forw;
649: fd_skip = 0;
650: biodone(bp);
651: nextstate(dp);
652:
653: }
654:
655: /*
656: nextstate : After a transfer is done, continue processing
657: requests on the current drive queue. If empty, go to
658: the other drives queue. If that is empty too, timeout
659: to turn off the current drive in 5 seconds, and go
660: to state 0 (not expecting any interrupts).
661: */
662:
663: nextstate(dp)
664: struct buf *dp;
665: {
666: struct buf *dpother;
667:
668: if (dp->b_actf) fdstart(fd_drive);
1.1.1.3 root 669: else {
1.1 root 670: untimeout(fd_turnoff,fd_drive);
1.1.1.3 root 671: timeout(fd_turnoff,fd_drive,hz);
1.1 root 672: fd_state = 0;
673: dp->b_active = 0;
674: }
675: }
676: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.