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