|
|
1.1 ! root 1: /* ! 2: * Mach Operating System ! 3: * Copyright (c) 1993,1991,1990,1989 Carnegie Mellon University ! 4: * All Rights Reserved. ! 5: * ! 6: * Permission to use, copy, modify and distribute this software and its ! 7: * documentation is hereby granted, provided that both the copyright ! 8: * notice and this permission notice appear in all copies of the ! 9: * software, derivative works or modified versions, and any portions ! 10: * thereof, and that both notices appear in supporting documentation. ! 11: * ! 12: * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" ! 13: * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR ! 14: * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. ! 15: * ! 16: * Carnegie Mellon requests users of this software to return to ! 17: * ! 18: * Software Distribution Coordinator or [email protected] ! 19: * School of Computer Science ! 20: * Carnegie Mellon University ! 21: * Pittsburgh PA 15213-3890 ! 22: * ! 23: * any improvements or extensions that they make and grant Carnegie Mellon ! 24: * the rights to redistribute these changes. ! 25: */ ! 26: /* ! 27: Copyright 1988, 1989 by Intel Corporation, Santa Clara, California. ! 28: ! 29: All Rights Reserved ! 30: ! 31: Permission to use, copy, modify, and distribute this software and ! 32: its documentation for any purpose and without fee is hereby ! 33: granted, provided that the above copyright notice appears in all ! 34: copies and that both the copyright notice and this permission notice ! 35: appear in supporting documentation, and that the name of Intel ! 36: not be used in advertising or publicity pertaining to distribution ! 37: of the software without specific, written prior permission. ! 38: ! 39: INTEL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE ! 40: INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, ! 41: IN NO EVENT SHALL INTEL BE LIABLE FOR ANY SPECIAL, INDIRECT, OR ! 42: CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM ! 43: LOSS OF USE, DATA OR PROFITS, WHETHER IN ACTION OF CONTRACT, ! 44: NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION ! 45: WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ! 46: */ ! 47: ! 48: /* Copyright (c) 1987, 1988 TOSHIBA Corp. */ ! 49: /* All Rights Reserved */ ! 50: ! 51: #if 0 ! 52: ! 53: #include <fd.h> ! 54: ! 55: #ifdef MACH_KERNEL ! 56: #include <sys/types.h> ! 57: #include <sys/ioctl.h> ! 58: #include <device/buf.h> ! 59: #include <device/errno.h> ! 60: #else MACH_KERNEL ! 61: #include <sys/buf.h> ! 62: #include <sys/errno.h> ! 63: #include <sys/user.h> ! 64: #include <sys/ioctl.h> ! 65: #endif MACH_KERNEL ! 66: #include <i386/pio.h> ! 67: #include <i386/machspl.h> ! 68: #include <chips/busses.h> ! 69: #include <i386at/fdreg.h> ! 70: #include <i386at/disk.h> ! 71: #include <vm/vm_kern.h> ! 72: ! 73: #ifdef DEBUG ! 74: #define D(x) x ! 75: #define DD(x) x ! 76: #else /* DEBUG */ ! 77: #define D(x) ! 78: #define DD(x) ! 79: #endif /* DEBUG */ ! 80: ! 81: /* ! 82: * Floppy Device-Table Definitions (drtabs) ! 83: * ! 84: * Cyls,Sec,spc,part,Mtype,RWFpl,FGpl ! 85: */ ! 86: struct fddrtab m765f[] = { /* format table */ ! 87: 80, 18, 1440, 9, 0x88, 0x2a, 0x50, /* [0] 3.50" 720 Kb */ ! 88: 80, 36, 2880, 18, 0x08, 0x1b, 0x6c, /* [1] 3.50" 1.44 Meg */ ! 89: 40, 18, 720, 9, 0xa8, 0x2a, 0x50, /* [2] 5.25" 360 Kb */ ! 90: 80, 30, 2400, 15, 0x08, 0x1b, 0x54 /* [3] 5.25" 1.20 Meg */ ! 91: }; ! 92: ! 93: /* ! 94: * The following are static initialization variables ! 95: * which are based on the configuration. ! 96: */ ! 97: struct ctrl_info ctrl_info[MAXUNIT>>1] = { /* device data table */ ! 98: { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } , ! 99: { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } ! 100: }; ! 101: ! 102: struct unit_info unit_info[MAXUNIT]; /* unit buffer headers */ ! 103: ! 104: char *fderr = "FD Error on unit"; ! 105: char *fdmsg[] = { ! 106: "?", ! 107: "Missing data address mark", ! 108: "Write protected", ! 109: "Sector not found", ! 110: "Data Overrun", /* Over run error */ ! 111: "Uncorrectable data read error", /* CRC Error */ ! 112: "FDC Error", ! 113: "Illegal format type", ! 114: "Drive not ready", ! 115: "diskette not present - please insert", ! 116: "Illegal interrupt type" ! 117: }; ! 118: ! 119: struct buf fdrbuf[MAXUNIT]; /* data transfer buffer structures */ ! 120: ! 121: int fdminphys(); ! 122: int fdintr(), fdprobe(), fdslave(); ! 123: void fdattach(); ! 124: int FdDmaEISA = 0; ! 125: int FdDmaThreshold = 16 * 1024 * 1024; ! 126: vm_offset_t FdDmaPage = (vm_offset_t) 0; ! 127: vm_offset_t fd_std[NFD] = { 0 }; ! 128: struct bus_device *fd_dinfo[NFD*2]; ! 129: struct bus_ctlr *fd_minfo[NFD]; ! 130: struct bus_driver fddriver = ! 131: {fdprobe, fdslave, fdattach, 0, fd_std, "fd", fd_dinfo, "fdc", fd_minfo, 0}; ! 132: ! 133: int m765verify[MAXUNIT] = {1,1,1,1}; /* write after read flag */ ! 134: /* 0 != verify mode */ ! 135: /* 0 == not verify mode */ ! 136: #ifdef MACH_KERNEL ! 137: extern struct buf *geteblk(); ! 138: #endif MACH_KERNEL ! 139: ! 140: #define trfrate(uip, type) outb(VFOREG(uip->addr),(((type)&RATEMASK)>>6)) ! 141: #define rbskrate(uip, type) trfrate(uip,(type)&RAPID?RPSEEK:NMSEEK) ! 142: #define getparm(type) ((type<0||type>3)?(struct fddrtab *)ERROR:&m765f[type]) ! 143: #define relative(s1,s2) ((s1)>(s2)?(s1)-(s2):(s2)-(s1)) ! 144: ! 145: fdprobe(port, ctlr) ! 146: struct bus_ctlr *ctlr; ! 147: { ! 148: int spot = STSREG((int) ctlr->address); ! 149: struct ctrl_info *cip = &ctrl_info[ctlr->unit]; ! 150: int i, in; ! 151: ! 152: outb(spot, DATAOK); ! 153: for (i = 1000; i--;) { ! 154: in = inb(spot); ! 155: if ((in&DATAOK) == DATAOK && !(in&0x0f)) { ! 156: take_ctlr_irq(ctlr); ! 157: cip->b_cmd.c_rbmtr = 0; /* recalibrate/moter flag */ ! 158: cip->b_cmd.c_intr = CMDRST; /* interrupt flag */ ! 159: cip->b_unitf = 0; ! 160: cip->b_uip = 0; ! 161: cip->b_rwerr = cip->b_seekerr = cip->b_rberr = 0; ! 162: cip->usebuf = 0; ! 163: if (FdDmaPage) { ! 164: cip->b_pbuf = FdDmaPage + PAGE_SIZE * ctlr->unit; ! 165: if (kmem_alloc_pageable(kernel_map, ! 166: (vm_offset_t *)&cip->b_vbuf, ! 167: PAGE_SIZE) != KERN_SUCCESS) { ! 168: printf("%s%d: can not kmem_alloc_pageable.\n", ! 169: ctlr->name, ctlr->unit); ! 170: return 0; ! 171: } ! 172: (void)pmap_map(cip->b_vbuf, ! 173: (vm_offset_t)cip->b_pbuf, ! 174: (vm_offset_t)cip->b_pbuf+PAGE_SIZE, ! 175: VM_PROT_READ | VM_PROT_WRITE); ! 176: } ! 177: printf("%s%d: port = %x, spl = %d, pic = %d.\n", ctlr->name, ! 178: ctlr->unit, ctlr->address, ctlr->sysdep, ctlr->sysdep1); ! 179: return(1); ! 180: } ! 181: } ! 182: return(0); ! 183: } ! 184: ! 185: fdslave(dev, xxxx) ! 186: struct bus_device *dev; ! 187: { ! 188: return(1); /* gross hack */ ! 189: } ! 190: ! 191: void fdattach(dev) ! 192: struct bus_device *dev; ! 193: { ! 194: struct unit_info *uip = &unit_info[dev->unit]; ! 195: struct ctrl_info *cip = &ctrl_info[dev->ctlr]; ! 196: ! 197: uip->dev = dev; ! 198: dev->address = dev->mi->address; ! 199: uip->addr = dev->address; ! 200: uip->b_cmd = &cip->b_cmd; ! 201: uip->b_seekaddr = 0; ! 202: uip->av_forw = 0; ! 203: uip->wakeme = 0; ! 204: if (cip->b_unitf) { ! 205: uip->b_unitf=cip->b_unitf->b_unitf; ! 206: cip->b_unitf->b_unitf=uip; ! 207: } else { ! 208: uip->b_unitf=uip; ! 209: cip->b_unitf=uip; ! 210: } ! 211: uip->d_drtab.dr_type &= ~OKTYPE; ! 212: ! 213: printf(", port = %x, spl = %d, pic = %d.", ! 214: dev->address, dev->sysdep, dev->sysdep1); ! 215: ! 216: rstout(uip); ! 217: specify(uip); ! 218: } ! 219: /***************************************************************************** ! 220: * ! 221: * TITLE: fdopen ! 222: * ! 223: * ABSTRACT: Open a unit. ! 224: * ! 225: ****************************************************************************/ ! 226: fdopen(dev, flag, otyp) ! 227: dev_t dev; ! 228: int flag; /* not used */ ! 229: int otyp; /* not used */ ! 230: { ! 231: struct fddrtab *driv; ! 232: struct buf *wbp; ! 233: spl_t x = SPL(); ! 234: int error = 0; ! 235: int unit = UNIT(dev); ! 236: struct unit_info *uip = &unit_info[unit]; ! 237: int slave = uip->dev->slave; ! 238: struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr]; ! 239: struct fdcmd *cmdp = uip->b_cmd; ! 240: if (unit < MAXUNIT){ ! 241: /* Since all functions that use this are called from open, we only ! 242: set this once, right here. */ ! 243: rstout(uip); ! 244: cip->b_wup = uip; ! 245: openchk(cmdp); ! 246: cmdp->c_devflag |= FDMCHK; ! 247: chkbusy(cmdp); ! 248: cmdp->c_stsflag |= MTRFLAG; ! 249: mtr_on(uip); ! 250: if(inb(VFOREG(uip->addr))&OPENBIT || ! 251: !(uip->d_drtab.dr_type&OKTYPE)){ ! 252: uip->d_drtab.dr_type &= ~OKTYPE; ! 253: if(!rbrate(RAPID, uip)) ! 254: fdseek(RAPID, uip, 2); ! 255: if(inb(VFOREG(uip->addr))&OPENBIT) ! 256: error = ENXIO; ! 257: } ! 258: cmdp->c_stsflag &= ~MTRFLAG; ! 259: mtr_on(uip); ! 260: openfre(cmdp); ! 261: if(!error && !(uip->d_drtab.dr_type & OKTYPE)) { ! 262: if (MEDIATYPE(dev)>3) ! 263: goto endopen; ! 264: driv = &m765f[MEDIATYPE(dev)]; ! 265: wbp = geteblk(BLKSIZE); ! 266: m765sweep(uip, driv); ! 267: cmdp->c_rbmtr &= ~(1<<(RBSHIFT+(slave))); ! 268: ++cip->b_rwerr; ! 269: wbp->b_dev = dev; wbp->b_error = 0; wbp->b_resid = 0; ! 270: wbp->b_flags = (B_READ|B_VERIFY); wbp->b_bcount = 512; ! 271: wbp->b_pfcent = 2*driv->dr_spc + driv->dr_nsec - 1; ! 272: setqueue(wbp, uip); ! 273: biowait(wbp); ! 274: brelse(wbp); ! 275: error = 0; ! 276: uip->d_drtab.dr_type |= OKTYPE; ! 277: } ! 278: } else ! 279: error = ENXIO; ! 280: endopen: ! 281: splx(x); ! 282: return(error); ! 283: } ! 284: /***************************************************************************** ! 285: * ! 286: * TITLE: fdclose ! 287: * ! 288: * ABSTRACT: Close a unit. ! 289: * ! 290: * Called on last close. mark the unit closed and not-ready. ! 291: * ! 292: * Unix doesn't actually "open" an inode for rootdev, swapdev or pipedev. ! 293: * If UNIT(swapdev) != UNIT(rootdev), then must add code in init() to ! 294: * "open" swapdev. These devices should never be closed. ! 295: * ! 296: *****************************************************************************/ ! 297: fdclose(dev, flag, otyp, offset) ! 298: dev_t dev; /* major, minor numbers */ ! 299: int flag; /* not used */ ! 300: int otyp; /* not used */ ! 301: off_t offset; /* not used */ ! 302: { ! 303: extern dev_t rootdev, swapdev; ! 304: struct unit_info *uip = &unit_info[UNIT(dev)]; ! 305: spl_t s; ! 306: ! 307: #ifdef MACH_KERNEL ! 308: #else MACH_KERNEL ! 309: if ((dev == rootdev) || (dev == swapdev)) /* never close these */ ! 310: return(0); ! 311: #endif MACH_KERNEL ! 312: ! 313: /* Clear the bit. ! 314: * If last close of drive insure drtab queue is empty before returning. ! 315: */ ! 316: s = SPL(); ! 317: while(uip->av_forw != 0) { ! 318: uip->wakeme = 1; ! 319: sleep(uip, PRIBIO); ! 320: } ! 321: splx(s); ! 322: #ifdef MACH_KERNEL ! 323: return(0); ! 324: #else MACH_KERNEL ! 325: close(0); ! 326: #endif MACH_KERNEL ! 327: } ! 328: /***************************************************************************** ! 329: * ! 330: * TITLE: fdstrategy ! 331: * ! 332: * ABSTRACT: Queue an I/O Request, and start it if not busy already. ! 333: * ! 334: * Reject request if unit is not-ready. ! 335: * ! 336: * Note: check for not-ready done here ==> could get requests ! 337: * queued prior to unit going not-ready. ! 338: * not-ready status to those requests that are attempted ! 339: * before a new volume is inserted. Once a new volume is ! 340: * inserted, would get good I/O's to wrong volume. ! 341: * ! 342: * CALLS: iodone(),setqueue() ! 343: * ! 344: * CALLING ROUTINES: fdread (indirectly, thru physio) ! 345: * fdwrite (indirectly, thru physio) ! 346: * ! 347: ****************************************************************************/ ! 348: fdstrategy(bp) ! 349: struct buf *bp; /* buffer header */ ! 350: { ! 351: unsigned bytes_left; ! 352: daddr_t secno; ! 353: struct unit_info *uip = &unit_info[UNIT(bp->b_dev)]; ! 354: struct fddrtab *dr = &uip->d_drtab; ! 355: struct fddrtab *sdr; ! 356: ! 357: bp->b_error = 0; ! 358: /* set b_resid to b_bcount because we haven't done anything yet */ ! 359: bp->b_resid = bp->b_bcount; ! 360: if (!(dr->dr_type & OKTYPE) || ! 361: ((sdr = getparm(MEDIATYPE(bp->b_dev)))==(struct fddrtab *)ERROR) || ! 362: /* wrong parameters */ ! 363: (sdr->dr_ncyl != dr->dr_ncyl) || (sdr->dr_nsec != dr->dr_nsec) || ! 364: ((sdr->dr_type|OKTYPE) != dr->dr_type) || ! 365: (sdr->dr_rwgpl != dr->dr_rwgpl) || ! 366: (sdr->dr_fgpl != dr->dr_fgpl)) { ! 367: bp->b_flags |= B_ERROR; ! 368: bp->b_error = EIO; ! 369: biodone(bp); ! 370: return(0); ! 371: } ! 372: /* ! 373: * Figure "secno" from b_blkno. Adjust sector # for partition. ! 374: * ! 375: * If reading just past the end of the device, it's ! 376: * End of File. If not reading, or if read starts further in ! 377: * than the first sector after the partition, it's an error. ! 378: * ! 379: * secno is logical blockno / # of logical blocks per sector */ ! 380: secno = (bp->b_blkno * NBPSCTR) >> 9; ! 381: if (secno >= dr->p_nsec) { ! 382: if (!((bp->b_flags & B_READ) && (secno == dr->p_nsec))){ ! 383: /* off the deep end */ ! 384: bp->b_flags |= B_ERROR; ! 385: bp->b_error = ENXIO; ! 386: } ! 387: biodone(bp); ! 388: return(0); ! 389: } ! 390: /* At this point, it is no longer possible to directly return from strategy. ! 391: We now set b_resid to the number of bytes we cannot transfer because ! 392: they lie beyond the end of the request's partition. This value is 0 ! 393: if the entire request is within the partition. */ ! 394: bytes_left = (dr->p_nsec - secno) << 9; ! 395: bp->b_resid = ((bp->b_bcount<=bytes_left)?0:(bp->b_bcount-bytes_left)); ! 396: bp->b_pfcent = secno; ! 397: setqueue(bp, uip); ! 398: return(0); ! 399: } ! 400: ! 401: /*************************************************************************** ! 402: * ! 403: * set queue to buffer ! 404: * ! 405: ***************************************************************************/ ! 406: setqueue(bp, uip) ! 407: struct buf *bp; ! 408: struct unit_info *uip; ! 409: { ! 410: spl_t x = SPL(); ! 411: struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr]; ! 412: struct fdcmd *cmdp = uip->b_cmd; ! 413: ! 414: openchk(cmdp); /* openning check */ ! 415: cmdp->c_devflag |= STRCHK; ! 416: fd_disksort(uip, bp); /* queue the request */ ! 417: /* ! 418: * If no requests are in progress, start this one up. Else ! 419: * leave it on the queue, and fdintr will call m765io later. ! 420: */ ! 421: if(!cip->b_uip) ! 422: m765io(uip); ! 423: splx(x); ! 424: } ! 425: /*************************************************************************** ! 426: * ! 427: * check io_busy routine ! 428: * ! 429: ***************************************************************************/ ! 430: chkbusy(cmdp) ! 431: struct fdcmd *cmdp; ! 432: { ! 433: while(cmdp->c_devflag & STRCHK){ ! 434: cmdp->c_devflag |= STRWAIT; ! 435: sleep(&cmdp->c_devflag,PZERO); ! 436: } ! 437: } ! 438: /*************************************************************************** ! 439: * ! 440: * check fdopen() routine ! 441: * ! 442: ***************************************************************************/ ! 443: openchk(cmdp) ! 444: struct fdcmd *cmdp; ! 445: { ! 446: while(cmdp->c_devflag & FDMCHK ){ ! 447: cmdp->c_devflag |= FDWAIT; ! 448: sleep(&cmdp->c_devflag,PZERO); ! 449: } ! 450: } ! 451: /*************************************************************************** ! 452: * ! 453: * free fdopen() routine ! 454: * ! 455: ***************************************************************************/ ! 456: openfre(cmdp) ! 457: struct fdcmd *cmdp; ! 458: { ! 459: cmdp->c_devflag &= ~FDMCHK; ! 460: if(cmdp->c_devflag & FDWAIT){ ! 461: cmdp->c_devflag &= ~FDWAIT; ! 462: wakeup(&cmdp->c_devflag); ! 463: } ! 464: } ! 465: /***************************************************************************** ! 466: * ! 467: * TITLE: m765io ! 468: * ! 469: * ABSTRACT: Start handling an I/O request. ! 470: * ! 471: ****************************************************************************/ ! 472: m765io(uip) ! 473: struct unit_info *uip; ! 474: { ! 475: extern int(m765iosub)(); ! 476: register struct buf *bp; ! 477: struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr]; ! 478: ! 479: bp = uip->av_forw; /*move bp to ctrl_info[ctrl].b_buf*/ ! 480: cip->b_buf = bp; ! 481: cip->b_uip = uip; ! 482: cip->b_xferaddr = bp->b_un.b_addr; ! 483: cip->b_xfercount = bp->b_bcount - bp->b_resid; ! 484: cip->b_sector = bp->b_pfcent; ! 485: uip->b_cmd->c_stsflag |= MTRFLAG; ! 486: if(!mtr_start(uip)) ! 487: timeout(m765iosub, uip, HZ); ! 488: else ! 489: m765iosub(uip); ! 490: } ! 491: /**************************************************************************** ! 492: * ! 493: * m765io subroutine ! 494: * ! 495: ****************************************************************************/ ! 496: m765iosub(uip) ! 497: struct unit_info *uip; ! 498: { ! 499: struct fddrtab *dr = &uip->d_drtab; ! 500: int startsec; ! 501: int slave = uip->dev->slave; ! 502: struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr]; ! 503: struct fdcmd *cmdp = uip->b_cmd; ! 504: ! 505: rwcmdset(uip); ! 506: if(cip->b_buf->b_flags&B_FORMAT) ! 507: goto skipchk; ! 508: startsec = (cmdp->c_rwdata[3] * dr->dr_nsec) + cmdp->c_rwdata[4]; ! 509: if(startsec+(cip->b_xfercount>>9)-1 > dr->dr_spc) ! 510: cip->b_xferdma = (dr->dr_spc-startsec+1) << 9; ! 511: else ! 512: skipchk: cip->b_xferdma = cip->b_xfercount; ! 513: if(!(cmdp->c_rbmtr & (1<<(RBSHIFT+slave)))) ! 514: cip->b_status = rbirate(uip); ! 515: else if(uip->b_seekaddr != cmdp->c_saddr) ! 516: cip->b_status = fdiseek(uip,cmdp->c_saddr); ! 517: else ! 518: cip->b_status = outicmd(uip); ! 519: if(cip->b_status) ! 520: intrerr0(uip); ! 521: return; ! 522: } ! 523: /*************************************************************************** ! 524: * ! 525: * read / write / format / verify command set to command table ! 526: * ! 527: ***************************************************************************/ ! 528: rwcmdset(uip) ! 529: struct unit_info *uip; ! 530: { ! 531: short resid; ! 532: int slave = uip->dev->slave; ! 533: struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr]; ! 534: struct fdcmd *cmdp = uip->b_cmd; ! 535: ! 536: switch(cip->b_buf->b_flags&(B_FORMAT|B_VERIFY|B_READ|B_WRITE)){ ! 537: case B_VERIFY|B_WRITE: /* VERIFY after WRITE */ ! 538: cmdp->c_rwdata[0] = RDMV; ! 539: break; ! 540: case B_FORMAT: ! 541: cmdp->c_dcount = FMTCNT; ! 542: cmdp->c_rwdata[0] = FMTM; ! 543: cmdp->c_saddr = cip->b_sector / uip->d_drtab.dr_spc; ! 544: resid = cip->b_sector % uip->d_drtab.dr_spc; ! 545: cmdp->c_rwdata[1] = slave|((resid/uip->d_drtab.dr_nsec)<<2); ! 546: cmdp->c_rwdata[2] = ! 547: ((struct fmttbl *)cip->b_buf->b_un.b_addr)->s_type; ! 548: cmdp->c_rwdata[3] = uip->d_drtab.dr_nsec; ! 549: cmdp->c_rwdata[4] = uip->d_drtab.dr_fgpl; ! 550: cmdp->c_rwdata[5] = FMTDATA; ! 551: break; ! 552: case B_WRITE: ! 553: case B_READ: ! 554: case B_READ|B_VERIFY: ! 555: cmdp->c_dcount = RWCNT; ! 556: if(cip->b_buf->b_flags&B_READ) ! 557: if(cip->b_buf->b_flags&B_VERIFY) ! 558: cmdp->c_rwdata[0] = RDMV; ! 559: else ! 560: cmdp->c_rwdata[0] = RDM; ! 561: else ! 562: cmdp->c_rwdata[0] = WTM; /* format or write */ ! 563: resid = cip->b_sector % uip->d_drtab.dr_spc; ! 564: cmdp->c_rwdata[3] = resid / uip->d_drtab.dr_nsec; ! 565: cmdp->c_rwdata[1] = slave|(cmdp->c_rwdata[3]<<2); ! 566: cmdp->c_rwdata[2] = cmdp->c_saddr = ! 567: cip->b_sector / uip->d_drtab.dr_spc; ! 568: cmdp->c_rwdata[4] = (resid % uip->d_drtab.dr_nsec) + 1; ! 569: cmdp->c_rwdata[5] = 2; ! 570: cmdp->c_rwdata[6] = uip->d_drtab.dr_nsec; ! 571: cmdp->c_rwdata[7] = uip->d_drtab.dr_rwgpl; ! 572: cmdp->c_rwdata[8] = DTL; ! 573: D(printf("SET %x %x C%x H%x S%x %x %x %x %x ", ! 574: cmdp->c_rwdata[0], cmdp->c_rwdata[1], ! 575: cmdp->c_rwdata[2], cmdp->c_rwdata[3], ! 576: cmdp->c_rwdata[4], cmdp->c_rwdata[5], ! 577: cmdp->c_rwdata[6], cmdp->c_rwdata[7], ! 578: cmdp->c_rwdata[8])); ! 579: break; ! 580: } ! 581: } ! 582: /***************************************************************************** ! 583: * ! 584: * TITLE: fdread ! 585: * ! 586: * ABSTRACT: "Raw" read. Use physio(). ! 587: * ! 588: * CALLS: m765breakup (indirectly, thru physio) ! 589: * ! 590: ****************************************************************************/ ! 591: fdread(dev, uio) ! 592: register dev_t dev; ! 593: struct uio *uio; ! 594: { ! 595: #ifdef MACH_KERNEL ! 596: /* no need for page-size restriction */ ! 597: return (block_io(fdstrategy, minphys, uio)); ! 598: #else MACH_KERNEL ! 599: return(physio(fdstrategy,&fdrbuf[UNIT(dev)],dev,B_READ,fdminphys,uio)); ! 600: #endif MACH_KERNEL ! 601: } ! 602: /***************************************************************************** ! 603: * ! 604: * TITLE: fdwrite ! 605: * ! 606: * ABSTRACT: "Raw" write. Use physio(). ! 607: * ! 608: * CALLS: m765breakup (indirectly, thru physio) ! 609: * ! 610: ****************************************************************************/ ! 611: fdwrite(dev, uio) ! 612: register dev_t dev; ! 613: struct uio *uio; ! 614: { ! 615: #ifdef MACH_KERNEL ! 616: /* no need for page-size restriction */ ! 617: return (block_io(fdstrategy, minphys, uio)); ! 618: #else MACH_KERNEL ! 619: return(physio(fdstrategy,&fdrbuf[UNIT(dev)],dev,B_WRITE,fdminphys,uio)); ! 620: #endif MACH_KERNEL ! 621: } ! 622: /***************************************************************************** ! 623: * ! 624: * TITLE: fdminphys ! 625: * ! 626: * ABSTRACT: Trim buffer length if buffer-size is bigger than page size ! 627: * ! 628: * CALLS: physio ! 629: * ! 630: ****************************************************************************/ ! 631: fdminphys(bp) ! 632: struct buf *bp; ! 633: { ! 634: if (bp->b_bcount > PAGESIZ) ! 635: bp->b_bcount = PAGESIZ; ! 636: } ! 637: #ifdef MACH_KERNEL ! 638: /* IOC_OUT only and not IOC_INOUT */ ! 639: io_return_t fdgetstat(dev, flavor, data, count) ! 640: dev_t dev; ! 641: int flavor; ! 642: int * data; /* pointer to OUT array */ ! 643: unsigned int *count; /* OUT */ ! 644: { ! 645: switch (flavor) { ! 646: ! 647: /* Mandatory flavors */ ! 648: ! 649: case DEV_GET_SIZE: { ! 650: int ret; ! 651: struct disk_parms p; ! 652: ! 653: ret = fd_getparms(dev, &p); ! 654: if (ret) return ret; ! 655: data[DEV_GET_SIZE_DEVICE_SIZE] = p.dp_pnumsec * NBPSCTR; ! 656: data[DEV_GET_SIZE_RECORD_SIZE] = NBPSCTR; ! 657: *count = DEV_GET_SIZE_COUNT; ! 658: break; ! 659: } ! 660: ! 661: /* Extra flavors */ ! 662: ! 663: case V_GETPARMS: ! 664: if (*count < sizeof (struct disk_parms)/sizeof (int)) ! 665: return (D_INVALID_OPERATION); ! 666: *count = sizeof (struct disk_parms)/sizeof(int); ! 667: return (fd_getparms(dev, data)); ! 668: default: ! 669: return (D_INVALID_OPERATION); ! 670: } ! 671: } ! 672: /* IOC_VOID or IOC_IN or IOC_INOUT */ ! 673: /*ARGSUSED*/ ! 674: io_return_t fdsetstat(dev, flavor, data, count) ! 675: dev_t dev; ! 676: int flavor; ! 677: int * data; ! 678: unsigned int count; ! 679: { ! 680: int unit = UNIT(dev); ! 681: switch (flavor) { ! 682: case V_SETPARMS: /* Caller wants reset_parameters */ ! 683: return(fd_setparms(unit,*(int *)data)); ! 684: case V_FORMAT: ! 685: return(fd_format(dev,data)); ! 686: case V_VERIFY: /* cmdarg : 0 == no verify, 0 != verify */ ! 687: m765verify[unit] = *(int *)data; ! 688: return(D_SUCCESS); ! 689: default: ! 690: return(D_INVALID_OPERATION); ! 691: } ! 692: } ! 693: ! 694: /* ! 695: * Get block size ! 696: */ ! 697: int ! 698: fddevinfo(dev, flavor, info) ! 699: dev_t dev; ! 700: int flavor; ! 701: char *info; ! 702: { ! 703: register struct fddrtab *dr; ! 704: register struct fdpart *p; ! 705: register int result = D_SUCCESS; ! 706: ! 707: switch (flavor) { ! 708: case D_INFO_BLOCK_SIZE: ! 709: dr = &unit_info[UNIT(dev)].d_drtab; ! 710: ! 711: if(dr->dr_type & OKTYPE) ! 712: *((int *) info) = 512; ! 713: else ! 714: result = D_INVALID_OPERATION; ! 715: ! 716: break; ! 717: default: ! 718: result = D_INVALID_OPERATION; ! 719: } ! 720: ! 721: return(result); ! 722: } ! 723: #else MACH_KERNEL ! 724: /***************************************************************************** ! 725: * ! 726: * TITLE: fdioctl ! 727: * ! 728: * ABSTRACT: m765 driver special functions. ! 729: * ! 730: * CALLING ROUTINES: kernel ! 731: * ! 732: ****************************************************************************/ ! 733: int ! 734: fdioctl(dev, cmd, cmdarg, flag) ! 735: dev_t dev; /* major, minor numbers */ ! 736: int cmd; /* command code */ ! 737: int *cmdarg; /* user structure with parameters */ ! 738: int flag; /* not used */ ! 739: { ! 740: register unsigned unit = UNIT(dev); ! 741: switch (cmd) { ! 742: case V_SETPARMS: /* Caller wants reset_parameters */ ! 743: return(fd_setparms(unit,*cmdarg)); ! 744: case V_GETPARMS: /* Caller wants device parameters */ ! 745: return(fd_getparms(dev,cmdarg)); ! 746: case V_FORMAT: ! 747: return(fd_format(dev,cmdarg)); ! 748: case V_VERIFY: /* cmdarg : 0 == no verify, 0 != verify */ ! 749: m765verify[unit] = *cmdarg; ! 750: return(0); ! 751: } ! 752: return(EINVAL); ! 753: } ! 754: #endif MACH_KERNEL ! 755: /**************************************************************************** ! 756: * ! 757: * set fd parameters ! 758: * ! 759: ****************************************************************************/ ! 760: int ! 761: fd_setparms(unit, cmdarg) ! 762: register unsigned int unit; ! 763: long cmdarg; ! 764: { ! 765: struct fddrtab *fdparm; ! 766: spl_t x; ! 767: struct unit_info *uip = &unit_info[unit]; ! 768: struct fdcmd *cmdp = uip->b_cmd; ! 769: ! 770: cmdp->c_rbmtr &= ~(1<<(RBSHIFT+uip->dev->slave)); ! 771: if ((fdparm = getparm(MEDIATYPE(cmdarg))) == (struct fddrtab *)ERROR) ! 772: return(EINVAL); ! 773: x = SPL(); ! 774: openchk(cmdp); ! 775: cmdp->c_devflag |= FDMCHK; ! 776: chkbusy(cmdp); ! 777: m765sweep(uip, fdparm); ! 778: uip->d_drtab.dr_type |= OKTYPE; ! 779: openfre(cmdp); ! 780: splx(x); ! 781: return(0); ! 782: } ! 783: /**************************************************************************** ! 784: * ! 785: * get fd parameters ! 786: * ! 787: ****************************************************************************/ ! 788: int ! 789: fd_getparms(dev,cmdarg) ! 790: dev_t dev; /* major, minor numbers */ ! 791: int *cmdarg; ! 792: { ! 793: struct disk_parms *diskp = (struct disk_parms *)cmdarg; ! 794: register struct fddrtab *dr = &unit_info[UNIT(dev)].d_drtab; ! 795: ! 796: if(dr->dr_type & OKTYPE){ ! 797: diskp->dp_type = DPT_FLOPPY; ! 798: diskp->dp_heads = 2; ! 799: diskp->dp_sectors = dr->dr_nsec; ! 800: diskp->dp_pstartsec = 0; ! 801: diskp->dp_cyls = dr->dr_ncyl; ! 802: diskp->dp_pnumsec = dr->p_nsec; ! 803: return(0); ! 804: } ! 805: return(ENXIO); ! 806: } ! 807: /**************************************************************************** ! 808: * ! 809: * format command ! 810: * ! 811: ****************************************************************************/ ! 812: fd_format(dev,cmdarg) ! 813: dev_t dev; /* major, minor numbers */ ! 814: int *cmdarg; ! 815: ! 816: { ! 817: register struct buf *bp; ! 818: register daddr_t track; ! 819: union io_arg *varg; ! 820: u_short num_trks; ! 821: register struct fddrtab *dr = &unit_info[UNIT(dev)].d_drtab; ! 822: ! 823: if(!(dr->dr_type & OKTYPE)) ! 824: return(EINVAL); ! 825: varg = (union io_arg *)cmdarg; ! 826: num_trks = varg->ia_fmt.num_trks; ! 827: track = (daddr_t)(varg->ia_fmt.start_trk*dr->dr_nsec); ! 828: if((track + (num_trks*dr->dr_nsec))>dr->p_nsec) ! 829: return(EINVAL); ! 830: bp = geteblk(BLKSIZE); /* get struct buf area */ ! 831: while (num_trks>0) { ! 832: bp->b_flags &= ~B_DONE; ! 833: bp->b_dev = dev; ! 834: bp->b_error = 0; bp->b_resid = 0; ! 835: bp->b_flags = B_FORMAT; ! 836: bp->b_bcount = dr->dr_nsec * FMTID; ! 837: bp->b_blkno = (daddr_t)((track << 9) / NBPSCTR); ! 838: if(makeidtbl(bp->b_un.b_addr,dr, ! 839: varg->ia_fmt.start_trk++,varg->ia_fmt.intlv)) ! 840: return(EINVAL); ! 841: fdstrategy(bp); ! 842: biowait(bp); ! 843: if(bp->b_error) ! 844: if((bp->b_error == (char)EBBHARD) || ! 845: (bp->b_error == (char)EBBSOFT)) ! 846: return(EIO); ! 847: else ! 848: return(bp->b_error); ! 849: num_trks--; ! 850: track += dr->dr_nsec; ! 851: } ! 852: brelse(bp); ! 853: return(0); ! 854: } ! 855: /**************************************************************************** ! 856: * ! 857: * make id table for format ! 858: * ! 859: ****************************************************************************/ ! 860: makeidtbl(tblpt,dr,track,intlv) ! 861: struct fmttbl *tblpt; ! 862: struct fddrtab *dr; ! 863: unsigned short track; ! 864: unsigned short intlv; ! 865: { ! 866: register int i,j,secno; ! 867: ! 868: if(intlv >= dr->dr_nsec) ! 869: return(1); ! 870: for(i=0; i<dr->dr_nsec; i++) ! 871: tblpt[i].sector = 0; ! 872: for(i=0,j=0,secno=1; i<dr->dr_nsec; i++){ ! 873: tblpt[j].cyl = track >> 1; ! 874: tblpt[j].head = track & 1; ! 875: tblpt[j].sector = secno++; ! 876: tblpt[j].s_type = 2; ! 877: if((j+=intlv) < dr->dr_nsec) ! 878: continue; ! 879: for(j-=dr->dr_nsec; j < dr->dr_nsec ; j++) ! 880: if(!tblpt[j].sector) ! 881: break; ! 882: } ! 883: return(0); ! 884: } ! 885: /***************************************************************************** ! 886: * ! 887: * TITLE: fdintr ! 888: * ! 889: * ABSTRACT: Handle interrupt. ! 890: * ! 891: * Interrupt procedure for m765 driver. Gets status of last ! 892: * operation and performs service function according to the ! 893: * type of interrupt. If it was an operation complete interrupt, ! 894: * switches on the current driver state and either declares the ! 895: * operation done, or starts the next operation ! 896: * ! 897: ****************************************************************************/ ! 898: fdintr(ctrl) ! 899: int ctrl; ! 900: { ! 901: extern int(m765intrsub)(); ! 902: struct unit_info *uip = ctrl_info[ctrl].b_uip; ! 903: struct unit_info *wup = ctrl_info[ctrl].b_wup; ! 904: struct fdcmd *cmdp = &ctrl_info[ctrl].b_cmd; ! 905: if(cmdp->c_stsflag & INTROUT) ! 906: untimeout(fdintr, ctrl); ! 907: cmdp->c_stsflag &= ~INTROUT; ! 908: switch(cmdp->c_intr){ ! 909: case RWFLAG: ! 910: rwintr(uip); ! 911: break; ! 912: case SKFLAG: ! 913: case SKEFLAG|SKFLAG: ! 914: case RBFLAG: ! 915: timeout(m765intrsub, uip, SEEKWAIT); ! 916: break; ! 917: case WUPFLAG: ! 918: cmdp->c_intr &= ~WUPFLAG; ! 919: wakeup(wup); ! 920: } ! 921: return(0); ! 922: } ! 923: /***************************************************************************** ! 924: * ! 925: * interrup subroutine (seek recalibrate) ! 926: * ! 927: *****************************************************************************/ ! 928: m765intrsub(uip) ! 929: struct unit_info *uip; ! 930: { ! 931: struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr]; ! 932: ! 933: if((cip->b_status = sis(uip))!= ST0OK) ! 934: switch(uip->b_cmd->c_intr){ ! 935: case SKFLAG: ! 936: seekintr(uip); ! 937: break; ! 938: case SKEFLAG|SKFLAG: ! 939: seekintre(uip); ! 940: break; ! 941: case RBFLAG: ! 942: rbintr(uip); ! 943: } ! 944: } ! 945: /***************************************************************************** ! 946: * ! 947: * read / write / format / verify interrupt routine ! 948: * ! 949: *****************************************************************************/ ! 950: rwintr(uip) ! 951: struct unit_info *uip; ! 952: { ! 953: int rsult[7]; ! 954: register int rtn, count; ! 955: struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr]; ! 956: struct fdcmd *cmdp = uip->b_cmd; ! 957: ! 958: cmdp->c_intr &= ~RWFLAG; ! 959: if((cip->b_buf->b_flags&(B_READ|B_VERIFY))!=(B_READ|B_VERIFY)) ! 960: if(inb(VFOREG(uip->addr))&OPENBIT){ ! 961: if(cip->b_buf->b_flags&B_FORMAT){ ! 962: cip->b_status = TIMEOUT; ! 963: intrerr0(uip); ! 964: } else { ! 965: if((inb(STSREG(uip->addr))&ST0OK)!=ST0OK) ! 966: printf("%s %d : %s\n", ! 967: fderr, ! 968: uip-unit_info, ! 969: fdmsg[DOORERR]); ! 970: rstout(uip); ! 971: specify(uip); ! 972: cmdp->c_rbmtr &= RBRST; ! 973: cmdp->c_intr |= SKEFLAG; ! 974: if(cmdp->c_saddr > 2) ! 975: fdiseek(uip, cmdp->c_saddr-2); ! 976: else ! 977: fdiseek(uip, cmdp->c_saddr+2); ! 978: } ! 979: return; ! 980: } ! 981: for( count = 0 ; count < 7 ; count++ ){ ! 982: if(rtn = fdc_sts(FD_ISTS, uip)) /* status check */ ! 983: goto rwend; ! 984: rsult[count] = inb(DATAREG(uip->addr)); ! 985: } ! 986: rtn = 0; ! 987: if(rsult[0]&0xc0){ ! 988: rtn = cmdp->c_rwdata[0]<<8; ! 989: if(rsult[0]&0x80){ rtn |= FDCERR; goto rwend; } ! 990: if(rsult[1]&0x80){ rtn |= NOREC; goto rwend; } ! 991: if(rsult[1]&0x20){ rtn |= CRCERR; goto rwend; } ! 992: if(rsult[1]&0x10){ rtn |= OVERRUN; goto rwend; } ! 993: if(rsult[1]&0x04){ rtn |= NOREC; goto rwend; } ! 994: if(rsult[1]&0x02){ rtn |= WTPRT; goto rwend; } ! 995: if(rsult[1]&0x01){ rtn |= ADDRERR; goto rwend; } ! 996: rtn |= FDCERR; ! 997: rwend: outb(0x0a, 0x06); ! 998: } ! 999: if(cip->b_status = rtn) { ! 1000: D(printf("\n->rwierr %x ", rtn)); ! 1001: rwierr(uip); ! 1002: } else { /* write command */ ! 1003: if(((cip->b_buf->b_flags&(B_FORMAT|B_READ|B_WRITE))==B_WRITE) ! 1004: && !(cip->b_buf->b_flags & B_VERIFY)) { ! 1005: D(printf("->w/v ")); ! 1006: cip->b_buf->b_flags |= B_VERIFY; ! 1007: rwcmdset(uip); ! 1008: if(cip->b_status = outicmd(uip)) ! 1009: intrerr0(uip); ! 1010: return; ! 1011: } ! 1012: /* clear retry count */ ! 1013: if (cip->usebuf) { ! 1014: bcopy(cip->b_vbuf, cip->b_xferaddr, cip->b_xferdma); ! 1015: DD(printf("R(%x, %x, %x)\n", ! 1016: cip->b_vbuf, cip->b_xferaddr, cip->b_xferdma)); ! 1017: } ! 1018: cip->b_buf->b_flags &= ~B_VERIFY; ! 1019: cip->b_rwerr = cip->b_seekerr = cip->b_rberr = 0; ! 1020: cip->b_xfercount -= cip->b_xferdma; ! 1021: cip->b_xferaddr += cip->b_xferdma; ! 1022: cip->b_sector = cip->b_sector+(cip->b_xferdma>>9); ! 1023: D(printf("->done%s\n", cip->b_xfercount?"":"." )); ! 1024: /* next address (cyl,head,sec) */ ! 1025: if((int)cip->b_xfercount>0) ! 1026: m765iosub(uip); ! 1027: else ! 1028: quechk(uip); ! 1029: } ! 1030: } ! 1031: /***************************************************************************** ! 1032: * ! 1033: * read / write / format / verify error routine ! 1034: * ! 1035: *****************************************************************************/ ! 1036: rwierr(uip) ! 1037: struct unit_info *uip; ! 1038: { ! 1039: short status; ! 1040: struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr]; ! 1041: struct fdcmd *cmdp = uip->b_cmd; ! 1042: ! 1043: D(printf("%x-%x-%x ", cip->b_rwerr&SRMASK, cip->b_rwerr&MRMASK, cip->b_rwerr&LRMASK)); ! 1044: if((cip->b_buf->b_flags&(B_READ|B_VERIFY))==(B_READ|B_VERIFY)){ ! 1045: if((cip->b_rwerr&SRMASK)<MEDIARD) ! 1046: goto rwrtry; ! 1047: if((cip->b_rwerr&MRMASK)<MEDIASEEK) ! 1048: goto rwseek; ! 1049: goto rwexit; ! 1050: } else ! 1051: if(cip->b_buf->b_flags&B_VERIFY){ ! 1052: cip->b_buf->b_flags &= ~B_VERIFY; ! 1053: rwcmdset(uip); ! 1054: } ! 1055: rwrtry: status = cip->b_status; ! 1056: if((++cip->b_rwerr&SRMASK)<SRETRY) ! 1057: cip->b_status = outicmd(uip); ! 1058: else { ! 1059: rwseek: cip->b_rwerr = (cip->b_rwerr&RMRMASK)+MINC; ! 1060: if((cip->b_rwerr&MRMASK)<MRETRY){ ! 1061: cmdp->c_intr |= SKEFLAG; ! 1062: if(cmdp->c_saddr > 2) ! 1063: cip->b_status=fdiseek(uip,cmdp->c_saddr-2); ! 1064: else ! 1065: cip->b_status=fdiseek(uip,cmdp->c_saddr+2); ! 1066: } else { ! 1067: cip->b_rwerr = (cip->b_rwerr&LRMASK)+LINC; ! 1068: if((cip->b_rwerr&LRMASK)<LRETRY) ! 1069: cip->b_status=rbirate(uip); ! 1070: } ! 1071: } ! 1072: if(cip->b_status){ ! 1073: D(printf("ERR->intrerr0 ")); ! 1074: cip->b_status = status; ! 1075: rwexit: intrerr0(uip); ! 1076: } ! 1077: } ! 1078: /***************************************************************************** ! 1079: * ! 1080: * recalibrate interrupt routine ! 1081: * ! 1082: *****************************************************************************/ ! 1083: rbintr(uip) ! 1084: struct unit_info *uip; ! 1085: { ! 1086: struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr]; ! 1087: struct fdcmd *cmdp = uip->b_cmd; ! 1088: ! 1089: cmdp->c_intr &= ~RBFLAG; ! 1090: if(cip->b_status) { ! 1091: if(++cip->b_rberr<SRETRY) ! 1092: cip->b_status = rbirate(uip); ! 1093: } else { ! 1094: cmdp->c_rbmtr |= 1<<(RBSHIFT+uip->dev->slave); ! 1095: uip->b_seekaddr = 0; ! 1096: cip->b_rberr = 0; ! 1097: cip->b_status=fdiseek(uip, cmdp->c_saddr); ! 1098: } ! 1099: if(cip->b_status) ! 1100: intrerr0(uip); ! 1101: } ! 1102: /****************************************************************************** ! 1103: * ! 1104: * seek interrupt routine ! 1105: * ! 1106: *****************************************************************************/ ! 1107: seekintr(uip) ! 1108: struct unit_info *uip; ! 1109: { ! 1110: struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr]; ! 1111: struct fdcmd *cmdp = uip->b_cmd; ! 1112: ! 1113: cmdp->c_intr &= ~SKFLAG; ! 1114: if(cip->b_status) ! 1115: seekierr(uip, cmdp->c_saddr); ! 1116: else { ! 1117: uip->b_seekaddr = cmdp->c_saddr; ! 1118: cip->b_status = outicmd(uip); ! 1119: } ! 1120: if(cip->b_status) ! 1121: intrerr0(uip); ! 1122: else ! 1123: cip->b_seekerr = 0; ! 1124: } ! 1125: /***************************************************************************** ! 1126: * ! 1127: * seek error retry interrupt routine ! 1128: * ! 1129: *****************************************************************************/ ! 1130: seekintre(uip) ! 1131: struct unit_info *uip; ! 1132: { ! 1133: register char seekpoint; ! 1134: struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr]; ! 1135: struct fdcmd *cmdp = uip->b_cmd; ! 1136: ! 1137: cmdp->c_intr &= ~(SKEFLAG|SKFLAG); ! 1138: if(cmdp->c_saddr > 2) ! 1139: seekpoint = cmdp->c_saddr-2; ! 1140: else ! 1141: seekpoint = cmdp->c_saddr+2; ! 1142: if(cip->b_status) ! 1143: seekierr(uip, seekpoint); ! 1144: else { ! 1145: uip->b_seekaddr = seekpoint; ! 1146: cip->b_status = fdiseek(uip, cmdp->c_saddr); ! 1147: } ! 1148: if(cip->b_status) ! 1149: intrerr0(uip); ! 1150: else ! 1151: cip->b_seekerr = 0; ! 1152: } ! 1153: /***************************************************************************** ! 1154: * ! 1155: * seek error routine ! 1156: * ! 1157: *****************************************************************************/ ! 1158: seekierr(uip, seekpoint) ! 1159: struct unit_info *uip; ! 1160: register char seekpoint; ! 1161: { ! 1162: struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr]; ! 1163: ! 1164: if((++cip->b_seekerr&SRMASK)<SRETRY) ! 1165: cip->b_status=fdiseek(uip, seekpoint); ! 1166: else { ! 1167: cip->b_seekerr = (cip->b_seekerr&MRMASK) + MINC; ! 1168: if((cip->b_seekerr&MRMASK)<MRETRY) ! 1169: cip->b_status=rbirate(uip); ! 1170: } ! 1171: if(cip->b_status) ! 1172: intrerr0(uip); ! 1173: } ! 1174: /***************************************************************************** ! 1175: * ! 1176: * TITLE: m765sweep ! 1177: * ! 1178: * ABSTRACT: Perform an initialization sweep. ! 1179: * ! 1180: **************************************************************************/ ! 1181: m765sweep(uip, cdr) ! 1182: struct unit_info *uip; ! 1183: register struct fddrtab *cdr; /* device initialization data */ ! 1184: { ! 1185: register struct fddrtab *dr = &uip->d_drtab; ! 1186: ! 1187: dr->dr_ncyl = cdr->dr_ncyl; ! 1188: dr->dr_nsec = cdr->dr_nsec; ! 1189: dr->dr_spc = cdr->dr_spc; ! 1190: dr->p_nsec = cdr->p_nsec; ! 1191: dr->dr_type = cdr->dr_type; ! 1192: dr->dr_rwgpl= cdr->dr_rwgpl; ! 1193: dr->dr_fgpl = cdr->dr_fgpl; ! 1194: } ! 1195: /***************************************************************************** ! 1196: * ! 1197: * TITLE: m765disksort ! 1198: * ! 1199: *****************************************************************************/ ! 1200: fd_disksort(uip, bp) ! 1201: struct unit_info *uip; /* Pointer to head of active queue */ ! 1202: register struct buf *bp; /* Pointer to buffer to be inserted */ ! 1203: { ! 1204: register struct buf *bp2; /* Pointer to next buffer in queue */ ! 1205: register struct buf *bp1; /* Pointer where to insert buffer */ ! 1206: ! 1207: if (!(bp1 = uip->av_forw)) { ! 1208: /* No other buffers to compare against */ ! 1209: uip->av_forw = bp; ! 1210: bp->av_forw = 0; ! 1211: return; ! 1212: } ! 1213: bp2 = bp1->av_forw; ! 1214: while(bp2 && (relative(bp1->b_pfcent,bp->b_pfcent) >= ! 1215: relative(bp1->b_pfcent,bp2->b_pfcent))) { ! 1216: bp1 = bp2; ! 1217: bp2 = bp1->av_forw; ! 1218: } ! 1219: bp1->av_forw = bp; ! 1220: bp->av_forw = bp2; ! 1221: } ! 1222: /***************************************************************************** ! 1223: * ! 1224: * Set Interrupt error and FDC reset ! 1225: * ! 1226: *****************************************************************************/ ! 1227: intrerr0(uip) ! 1228: struct unit_info *uip; ! 1229: { ! 1230: struct buf *bp; /* Pointer to next buffer in queue */ ! 1231: int resid; ! 1232: struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr]; ! 1233: struct fdcmd *cmdp = uip->b_cmd; ! 1234: register struct fddrtab *dr = &uip->d_drtab; ! 1235: ! 1236: if((cip->b_buf->b_flags&(B_READ|B_VERIFY))!=(B_READ|B_VERIFY)){ ! 1237: resid = cip->b_xfercount = cip->b_xferdma-1-inb(DMACNT)*0x101; ! 1238: resid = (cip->b_sector + (resid>>9)) % dr->dr_spc; ! 1239: printf("%s %d : %s\n", ! 1240: fderr, ! 1241: uip->dev->slave, ! 1242: fdmsg[cip->b_status&BYTEMASK]); ! 1243: printf("cylinder = %d ",cmdp->c_saddr); ! 1244: printf("head = %d sector = %d byte/sec = %d\n", ! 1245: resid / dr->dr_nsec , (resid % dr->dr_nsec)+1 , 512); ! 1246: } ! 1247: cip->b_rwerr = cip->b_seekerr = cip->b_rberr = 0; ! 1248: cmdp->c_intr = CMDRST; ! 1249: if(((cip->b_buf->b_flags&(B_READ|B_VERIFY))!=(B_READ|B_VERIFY)) && ! 1250: uip->dev->slave) ! 1251: dr->dr_type &= ~OKTYPE; ! 1252: bp = cip->b_buf; ! 1253: bp->b_flags |= B_ERROR; ! 1254: switch(cip->b_status&BYTEMASK){ ! 1255: case ADDRERR: ! 1256: case OVERRUN: ! 1257: case FDCERR: ! 1258: case TIMEOUT: ! 1259: bp->b_error = EIO; ! 1260: break; ! 1261: case WTPRT: ! 1262: #ifdef MACH_KERNEL ! 1263: bp->b_error = ENXIO; ! 1264: #else ! 1265: bp->b_error = ENODEV; ! 1266: #endif ! 1267: break; ! 1268: case NOREC: ! 1269: bp->b_error = EBBHARD; ! 1270: break; ! 1271: case CRCERR: ! 1272: bp->b_error = EBBSOFT; ! 1273: } ! 1274: rstout(uip); ! 1275: specify(uip); ! 1276: cmdp->c_rbmtr &= RBRST; ! 1277: quechk(uip); ! 1278: } ! 1279: /***************************************************************************** ! 1280: * ! 1281: * Next queue check routine ! 1282: * ! 1283: *****************************************************************************/ ! 1284: quechk(uip) ! 1285: struct unit_info *uip; ! 1286: { ! 1287: register struct buf *bp = uip->av_forw; ! 1288: struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr]; ! 1289: struct unit_info *loop; ! 1290: struct fdcmd *cmdp = uip->b_cmd; ! 1291: /* clear retry count */ ! 1292: cip->b_rwerr = cip->b_seekerr = cip->b_rberr = 0; ! 1293: bp->b_resid = bp->b_resid + cip->b_xfercount; ! 1294: uip->av_forw=bp->av_forw; ! 1295: if (!uip->av_forw && uip->wakeme) { ! 1296: uip->wakeme = 0; ! 1297: wakeup(uip); ! 1298: } ! 1299: biodone(bp); ! 1300: loop = uip; ! 1301: do { ! 1302: loop=loop->b_unitf; ! 1303: if (loop->av_forw) { ! 1304: m765io(loop); ! 1305: return; ! 1306: } ! 1307: } while (loop!=uip); ! 1308: cip->b_uip = 0; ! 1309: cmdp->c_stsflag &= ~MTRFLAG; ! 1310: mtr_on(uip); ! 1311: cmdp->c_devflag &= ~STRCHK; ! 1312: if(cmdp->c_devflag & STRWAIT){ ! 1313: cmdp->c_devflag &= ~STRWAIT; ! 1314: wakeup(&cmdp->c_devflag); ! 1315: } ! 1316: } ! 1317: fdprint(dev,str) ! 1318: dev_t dev; ! 1319: char *str; ! 1320: { ! 1321: printf("floppy disk driver: %s on bad dev %d, partition %d\n", ! 1322: str, UNIT(dev), 0); ! 1323: } ! 1324: fdsize() ! 1325: { ! 1326: printf("fdsize() -- not implemented\n"); ! 1327: } ! 1328: fddump() ! 1329: { ! 1330: printf("fddump() -- not implemented\n"); ! 1331: } ! 1332: /***************************************************************************** ! 1333: * ! 1334: * fdc reset routine ! 1335: * ! 1336: *****************************************************************************/ ! 1337: rstout(uip) ! 1338: struct unit_info *uip; ! 1339: { ! 1340: register int outd; ! 1341: ! 1342: outd = ((uip->b_cmd->c_rbmtr&MTRMASK)<<MTR_ON)|uip->dev->slave; ! 1343: outb(CTRLREG(uip->addr), outd); ! 1344: outd |= FDC_RST; ! 1345: outb(CTRLREG(uip->addr), outd); ! 1346: outd |= DMAREQ; ! 1347: outb(CTRLREG(uip->addr), outd); ! 1348: } ! 1349: /***************************************************************************** ! 1350: * ! 1351: * specify command routine ! 1352: * ! 1353: *****************************************************************************/ ! 1354: specify(uip) ! 1355: struct unit_info *uip; ! 1356: { ! 1357: /* status check */ ! 1358: if(fdc_sts(FD_OSTS, uip)) ! 1359: return; ! 1360: /* Specify command */ ! 1361: outb(DATAREG(uip->addr), SPCCMD); ! 1362: /* status check */ ! 1363: if(fdc_sts(FD_OSTS, uip)) ! 1364: return; ! 1365: /* Step rate,Head unload time */ ! 1366: outb(DATAREG(uip->addr), SRTHUT); ! 1367: /* status check */ ! 1368: if(fdc_sts(FD_OSTS, uip)) ! 1369: return; ! 1370: /* Head load time,Non DMA Mode*/ ! 1371: outb(DATAREG(uip->addr), HLTND); ! 1372: return; ! 1373: } ! 1374: /**************************************************************************** ! 1375: * ! 1376: * recalibrate command routine ! 1377: * ! 1378: ****************************************************************************/ ! 1379: rbrate(mtype,uip) ! 1380: char mtype; ! 1381: struct unit_info *uip; ! 1382: { ! 1383: register int rtn = 1, rty_flg=2; ! 1384: spl_t x; ! 1385: struct fdcmd *cmdp = uip->b_cmd; ! 1386: ! 1387: rbskrate(uip, mtype); /* set transfer rate */ ! 1388: while((rty_flg--)&&rtn){ ! 1389: if(rtn = fdc_sts(FD_OSTS, uip)) /* status check */ ! 1390: break; ! 1391: /*recalibrate command*/ ! 1392: outb(DATAREG(uip->addr), RBCMD); ! 1393: if(rtn = fdc_sts(FD_OSTS, uip)) /* status check */ ! 1394: break; ! 1395: /* Device to wake up specified in open */ ! 1396: cmdp->c_intr |= WUPFLAG; ! 1397: x = SPL(); ! 1398: outb(DATAREG(uip->addr), uip->dev->slave); ! 1399: rtn = ERROR; ! 1400: while(rtn) { ! 1401: uip->wakeme = 1; ! 1402: sleep(uip, PZERO); ! 1403: if((rtn = sis(uip)) == ST0OK) ! 1404: /* Device to wake up specified in open */ ! 1405: cmdp->c_intr |= WUPFLAG; ! 1406: else ! 1407: break; ! 1408: } ! 1409: splx(x); ! 1410: } ! 1411: return(rtn); ! 1412: } ! 1413: /***************************************************************************** ! 1414: * ! 1415: * seek command routine ! 1416: * ! 1417: ****************************************************************************/ ! 1418: fdseek(mtype, uip, cylno) ! 1419: register char mtype; ! 1420: struct unit_info *uip; ! 1421: register int cylno; ! 1422: { ! 1423: spl_t x; ! 1424: int rtn; ! 1425: struct fdcmd *cmdp = uip->b_cmd; ! 1426: ! 1427: rbskrate(uip, mtype); ! 1428: if(rtn = fdc_sts(FD_OSTS, uip)) /* status check */ ! 1429: return(rtn); ! 1430: outb(DATAREG(uip->addr), SEEKCMD); /* seek command */ ! 1431: if(rtn = fdc_sts(FD_OSTS, uip)) /* status check */ ! 1432: return(rtn); ! 1433: outb(DATAREG(uip->addr), uip->dev->slave); /* drive number */ ! 1434: if(rtn = fdc_sts(FD_OSTS, uip)) /* status check */ ! 1435: return(rtn); ! 1436: x = SPL(); ! 1437: /* Device to wake up specified in open */ ! 1438: cmdp->c_intr |= WUPFLAG; ! 1439: outb(DATAREG(uip->addr), cylno); /* seek count */ ! 1440: rtn = ERROR; ! 1441: while(rtn){ ! 1442: uip->wakeme = 1; ! 1443: sleep(uip, PZERO); ! 1444: if((rtn = sis(uip)) == ST0OK) ! 1445: /* Device to wake up specified in open */ ! 1446: cmdp->c_intr |= WUPFLAG; ! 1447: else ! 1448: break; ! 1449: } ! 1450: splx(x); ! 1451: return(rtn); ! 1452: } ! 1453: /***************************************************************************** ! 1454: * ! 1455: * seek commnd routine(use interrupt) ! 1456: * ! 1457: *****************************************************************************/ ! 1458: fdiseek(uip, cylno) ! 1459: struct unit_info *uip; ! 1460: int cylno; ! 1461: { ! 1462: register int rtn; ! 1463: ! 1464: D(printf("SK %x ", cylno)); ! 1465: rbskrate(uip, uip->d_drtab.dr_type);/* set transfer rate */ ! 1466: if(rtn = fdc_sts(FD_OSTS, uip)) /* status check */ ! 1467: goto fdiend; ! 1468: outb(DATAREG(uip->addr), SEEKCMD); /* seek command */ ! 1469: if(rtn = fdc_sts(FD_OSTS, uip)) /* status check */ ! 1470: goto fdiend; ! 1471: outb(DATAREG(uip->addr), uip->dev->slave); /* drive number */ ! 1472: if(rtn = fdc_sts(FD_OSTS, uip)) /* status check */ ! 1473: goto fdiend; ! 1474: uip->b_seekaddr = cylno; ! 1475: if(uip->d_drtab.dr_type&DOUBLE) ! 1476: cylno = cylno * 2; ! 1477: uip->b_cmd->c_intr |= SKFLAG; ! 1478: outb(DATAREG(uip->addr), cylno); /* seek count */ ! 1479: fdiend: ! 1480: if(rtn) ! 1481: rtn |= SEEKCMD<<8; ! 1482: return(rtn); ! 1483: } ! 1484: /***************************************************************************** ! 1485: * ! 1486: * recalibrate command routine(use interrupt) ! 1487: * ! 1488: *****************************************************************************/ ! 1489: rbirate(uip) ! 1490: struct unit_info *uip; ! 1491: { ! 1492: register int rtn; ! 1493: ! 1494: rbskrate(uip, uip->d_drtab.dr_type);/* set transfer rate */ ! 1495: if(!(rtn = fdc_sts(FD_OSTS, uip))) { /* status check */ ! 1496: /* recalibrate command */ ! 1497: outb(DATAREG(uip->addr), RBCMD); ! 1498: if(!(rtn = fdc_sts(FD_OSTS, uip))) { /* status check */ ! 1499: uip->b_cmd->c_intr |= RBFLAG; ! 1500: outb(DATAREG(uip->addr), uip->dev->slave); ! 1501: } ! 1502: } ! 1503: return(rtn ? rtn|RBCMD<<8 : 0); ! 1504: } ! 1505: /***************************************************************************** ! 1506: * ! 1507: * read / write / format / verify command out routine(use interrupt) ! 1508: * ! 1509: *****************************************************************************/ ! 1510: outicmd(uip) ! 1511: struct unit_info *uip; ! 1512: { ! 1513: int rtn; ! 1514: register int *data,cnt0,dmalen; ! 1515: register long address; ! 1516: struct ctrl_info *cip = &ctrl_info[uip->dev->ctlr]; ! 1517: struct fdcmd *cmdp = uip->b_cmd; ! 1518: spl_t x = splhi(); ! 1519: ! 1520: outb(DMACMD1,DMADATA0); /* DMA #1 command register */ ! 1521: outb(DMAMSK1,DMADATA1); /* DMA #1 all mask register */ ! 1522: /* Perhaps outb(0x0a,0x02); might work better on line above? */ ! 1523: switch(cmdp->c_rwdata[0]){ ! 1524: case RDM: ! 1525: D(printf("RDM")); ! 1526: outb(DMABPFF,DMARD); ! 1527: outb(DMAMODE,DMARD); ! 1528: break; ! 1529: case WTM: ! 1530: case FMTM: ! 1531: D(printf("W")); ! 1532: outb(DMABPFF,DMAWT); ! 1533: outb(DMAMODE,DMAWT); ! 1534: break; ! 1535: case RDMV: ! 1536: D(printf("RDMV")); ! 1537: outb(DMABPFF,DMAVRF); ! 1538: outb(DMAMODE,DMAVRF); ! 1539: } ! 1540: /* get work buffer physical address */ ! 1541: address = kvtophys(cip->b_xferaddr); ! 1542: dmalen = i386_trunc_page(address) + I386_PGBYTES - address; ! 1543: if ( (cip->b_rwerr&MRMASK) >= 0x10) ! 1544: dmalen = 0x200; ! 1545: if (dmalen<=cip->b_xferdma) ! 1546: cip->b_xferdma = dmalen; ! 1547: else ! 1548: dmalen = cip->b_xferdma; ! 1549: if (address >= FdDmaThreshold) { ! 1550: DD(printf(">(%x[%x], %x[%x] L%x\n", ! 1551: address, cip->b_pbuf, ! 1552: cip->b_xferaddr, cip->b_vbuf, dmalen)); ! 1553: if (!FdDmaEISA) { ! 1554: cip->usebuf = 1; ! 1555: address = (long)cip->b_pbuf; ! 1556: if (cmdp->c_rwdata[0] == WTM || cmdp->c_rwdata[0] == FMTM) { ! 1557: bcopy(cip->b_xferaddr, cip->b_vbuf, dmalen); ! 1558: DD(printf("W(%x, %x, %x)\n", ! 1559: cip->b_xferaddr, cip->b_vbuf, dmalen)); ! 1560: } ! 1561: } else ! 1562: cip->usebuf = 0; ! 1563: } else ! 1564: cip->usebuf = 0; ! 1565: D(printf(" %x L%x ", address, dmalen)); ! 1566: /* set buffer address */ ! 1567: outb(DMAADDR,(int)address&BYTEMASK); ! 1568: outb(DMAADDR,(((int)address>>8)&BYTEMASK)); ! 1569: outb(DMAPAGE,(((int)address>>16)&BYTEMASK)); ! 1570: if (FdDmaEISA) ! 1571: outb(FdDmaEISA+DMAPAGE-0x80,(((int)address>>24)&BYTEMASK)); ! 1572: /* set transfer count */ ! 1573: outb(DMACNT,(--dmalen)&BYTEMASK); ! 1574: outb(DMACNT,((dmalen>>8)&BYTEMASK)); ! 1575: outb(DMAMSK,CHANNEL2); ! 1576: splx(x); ! 1577: trfrate(uip, uip->d_drtab.dr_type); /* set transfer rate */ ! 1578: data = &cmdp->c_rwdata[0]; ! 1579: for(cnt0 = 0; cnt0<cmdp->c_dcount; cnt0++,data++){ ! 1580: if(rtn = fdc_sts(FD_OSTS, uip)) /*status check*/ ! 1581: break; ! 1582: outb(DATAREG(uip->addr), *data); ! 1583: } ! 1584: if(!rtn){ ! 1585: cmdp->c_intr |= RWFLAG; ! 1586: cmdp->c_stsflag |= INTROUT; ! 1587: cnt0 = ((cip->b_buf->b_flags&(B_READ|B_VERIFY)) == ! 1588: (B_READ|B_VERIFY))?TOUT:ITOUT; ! 1589: #ifdef MACH_KERNEL ! 1590: timeout(fdintr,uip->dev->ctlr,cnt0); ! 1591: #else MACH_KERNEL ! 1592: cmdp->c_timeid = timeout(fdintr,uip->dev->ctlr,cnt0); ! 1593: #endif MACH_KERNEL ! 1594: } ! 1595: return(rtn); ! 1596: } ! 1597: /***************************************************************************** ! 1598: * ! 1599: * sense interrupt status routine ! 1600: * ! 1601: *****************************************************************************/ ! 1602: sis(uip) ! 1603: struct unit_info *uip; ! 1604: { ! 1605: register int rtn, st0; ! 1606: ! 1607: if(rtn = fdc_sts(FD_OSTS, uip)) /* status check */ ! 1608: return(rtn); ! 1609: outb(DATAREG(uip->addr), SISCMD); ! 1610: if(rtn = fdc_sts(FD_ISTS, uip)) /* status check */ ! 1611: return(rtn); ! 1612: st0 = inb(DATAREG(uip->addr)) & ST0OK; /* get st0 */ ! 1613: if(rtn = fdc_sts(FD_ISTS, uip)) /* status check */ ! 1614: return(rtn); ! 1615: inb(DATAREG(uip->addr)); /* get pcn */ ! 1616: if (st0&(ST0AT|ST0IC)) ! 1617: st0 = FDCERR; ! 1618: return(st0); ! 1619: } ! 1620: ! 1621: /***************************************************************************** ! 1622: * ! 1623: * fdc status get routine ! 1624: * ! 1625: *****************************************************************************/ ! 1626: fdc_sts(mode, uip) ! 1627: register int mode; ! 1628: struct unit_info *uip; ! 1629: { ! 1630: register int ind; ! 1631: int cnt0 = STSCHKCNT; ! 1632: ! 1633: while(cnt0--) ! 1634: if(((ind=inb(STSREG(uip->addr))) & DATAOK) && ! 1635: ((ind & DTOCPU) == mode)) ! 1636: return(0); ! 1637: return(TIMEOUT); ! 1638: } ! 1639: /***************************************************************************** ! 1640: * ! 1641: * motor on routine ! 1642: * ! 1643: *****************************************************************************/ ! 1644: mtr_on(uip) ! 1645: struct unit_info *uip; ! 1646: { ! 1647: extern int(mtr_off)(); ! 1648: extern int(wakeup)(); ! 1649: struct fdcmd *cmdp = uip->b_cmd; ! 1650: ! 1651: if(!(mtr_start(uip))){ ! 1652: timeout(wakeup,&cmdp->c_stsflag,HZ); ! 1653: sleep(&cmdp->c_stsflag,PZERO); ! 1654: } ! 1655: cmdp->c_stsflag |= MTROFF; ! 1656: #ifdef MACH_KERNEL ! 1657: timeout(mtr_off,uip,MTRSTOP); ! 1658: #else MACH_KERNEL ! 1659: cmdp->c_mtrid = timeout(mtr_off,uip,MTRSTOP); ! 1660: #endif MACH_KERNEL ! 1661: } ! 1662: /***************************************************************************** ! 1663: * ! 1664: * motor start routine ! 1665: * ! 1666: *****************************************************************************/ ! 1667: mtr_start(uip) ! 1668: struct unit_info *uip; ! 1669: { ! 1670: int status; ! 1671: int (mtr_off)(); ! 1672: struct fdcmd *cmdp = uip->b_cmd; ! 1673: int slave = uip->dev->slave; ! 1674: if(cmdp->c_stsflag & MTROFF){ ! 1675: untimeout(mtr_off, uip); ! 1676: cmdp->c_stsflag &= ~MTROFF; ! 1677: } ! 1678: status = cmdp->c_rbmtr&(1<<slave); ! 1679: cmdp->c_rbmtr |= (1<<slave); ! 1680: outb(CTRLREG(uip->addr), ((cmdp->c_rbmtr&MTRMASK)<<MTR_ON)| ! 1681: FDC_RST|slave|DMAREQ); ! 1682: return(status); ! 1683: } ! 1684: /***************************************************************************** ! 1685: * ! 1686: * motor off routine ! 1687: * ! 1688: *****************************************************************************/ ! 1689: mtr_off(uip) ! 1690: struct unit_info *uip; ! 1691: { ! 1692: struct fdcmd *cmdp = uip->b_cmd; ! 1693: ! 1694: cmdp->c_stsflag &= ~MTROFF; ! 1695: if(!(cmdp->c_stsflag&MTRFLAG)){ ! 1696: cmdp->c_rbmtr &= MTRRST; ! 1697: outb(CTRLREG(uip->addr), FDC_RST | DMAREQ); ! 1698: } ! 1699: } ! 1700: ! 1701: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.