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