|
|
1.1.1.2 ! root 1: /* 1.1 root 2: * Mach Operating System 3: * Copyright (c) 1993,1991,1990,1989 Carnegie Mellon University 4: * All Rights Reserved. 1.1.1.2 ! root 5: * 1.1 root 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. 1.1.1.2 ! root 11: * 1.1 root 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. 1.1.1.2 ! root 15: * 1.1 root 16: * Carnegie Mellon requests users of this software to return to 1.1.1.2 ! root 17: * 1.1 root 18: * Software Distribution Coordinator or [email protected] 19: * School of Computer Science 20: * Carnegie Mellon University 21: * Pittsburgh PA 15213-3890 1.1.1.2 ! root 22: * 1.1 root 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> 1.1.1.2 ! root 60: #else /* MACH_KERNEL */ 1.1 root 61: #include <sys/buf.h> 62: #include <sys/errno.h> 63: #include <sys/user.h> 64: #include <sys/ioctl.h> 1.1.1.2 ! root 65: #endif /* MACH_KERNEL */ 1.1 root 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]; 1.1.1.2 ! root 130: struct bus_driver fddriver = 1.1 root 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 */ 1.1.1.2 ! root 134: /* 0 != verify mode */ 1.1 root 135: /* 0 == not verify mode */ 136: #ifdef MACH_KERNEL 137: extern struct buf *geteblk(); 1.1.1.2 ! root 138: #endif /* MACH_KERNEL */ 1.1 root 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, 1.1.1.2 ! root 173: (vm_offset_t)cip->b_pbuf, 1.1 root 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: } 1.1.1.2 ! root 211: uip->d_drtab.dr_type &= ~OKTYPE; 1.1 root 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: * 1.1.1.2 ! root 223: * ABSTRACT: Open a unit. 1.1 root 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); 1.1.1.2 ! root 250: if(inb(VFOREG(uip->addr))&OPENBIT || 1.1 root 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. 1.1.1.2 ! root 293: * If UNIT(swapdev) != UNIT(rootdev), then must add code in init() to 1.1 root 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 1.1.1.2 ! root 308: #else /* MACH_KERNEL */ 1.1 root 309: if ((dev == rootdev) || (dev == swapdev)) /* never close these */ 310: return(0); 1.1.1.2 ! root 311: #endif /* MACH_KERNEL */ 1.1 root 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); 1.1.1.2 ! root 324: #else /* MACH_KERNEL */ 1.1 root 325: close(0); 1.1.1.2 ! root 326: #endif /* MACH_KERNEL */ 1.1 root 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; 1.1.1.2 ! root 360: if (!(dr->dr_type & OKTYPE) || 1.1 root 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); 1.1.1.2 ! root 436: } 1.1 root 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); 1.1.1.2 ! root 449: } 1.1 root 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: 1.1.1.2 ! root 541: cmdp->c_dcount = FMTCNT; 1.1 root 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); 1.1.1.2 ! root 546: cmdp->c_rwdata[2] = 1.1 root 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); 1.1.1.2 ! root 566: cmdp->c_rwdata[2] = cmdp->c_saddr = 1.1 root 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; 1.1.1.2 ! root 594: { 1.1 root 595: #ifdef MACH_KERNEL 596: /* no need for page-size restriction */ 597: return (block_io(fdstrategy, minphys, uio)); 1.1.1.2 ! root 598: #else /* MACH_KERNEL */ 1.1 root 599: return(physio(fdstrategy,&fdrbuf[UNIT(dev)],dev,B_READ,fdminphys,uio)); 1.1.1.2 ! root 600: #endif /* MACH_KERNEL */ 1.1 root 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)); 1.1.1.2 ! root 618: #else /* MACH_KERNEL */ 1.1 root 619: return(physio(fdstrategy,&fdrbuf[UNIT(dev)],dev,B_WRITE,fdminphys,uio)); 1.1.1.2 ! root 620: #endif /* MACH_KERNEL */ 1.1 root 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: } 1.1.1.2 ! root 723: #else /* MACH_KERNEL */ 1.1 root 724: /***************************************************************************** 725: * 726: * TITLE: fdioctl 727: * 728: * ABSTRACT: m765 driver special functions. 729: * 730: * CALLING ROUTINES: kernel 731: * 732: ****************************************************************************/ 1.1.1.2 ! root 733: int 1.1 root 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: } 1.1.1.2 ! root 754: #endif /* MACH_KERNEL */ 1.1 root 755: /**************************************************************************** 756: * 1.1.1.2 ! root 757: * set fd parameters 1.1 root 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: * 1.1.1.2 ! root 785: * get fd parameters 1.1 root 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)) 1.1.1.2 ! root 824: return(EINVAL); 1.1 root 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; 1.1.1.2 ! root 835: bp->b_flags = B_FORMAT; 1.1 root 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) 1.1.1.2 ! root 844: if((bp->b_error == (char)EBBHARD) || 1.1 root 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); 1.1.1.2 ! root 907: cmdp->c_stsflag &= ~INTROUT; 1.1 root 908: switch(cmdp->c_intr){ 909: case RWFLAG: 910: rwintr(uip); 1.1.1.2 ! root 911: break; 1.1 root 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 */ 1.1.1.2 ! root 1003: if(((cip->b_buf->b_flags&(B_FORMAT|B_READ|B_WRITE))==B_WRITE) 1.1 root 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: * 1.1.1.2 ! root 1178: * ABSTRACT: Perform an initialization sweep. 1.1 root 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) 1.1.1.2 ! root 1251: dr->dr_type &= ~OKTYPE; 1.1 root 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; 1.1.1.2 ! root 1441: while(rtn){ 1.1 root 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: *****************************************************************************/ 1.1.1.2 ! root 1458: fdiseek(uip, cylno) 1.1 root 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 */ 1.1.1.2 ! root 1479: fdiend: 1.1 root 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; 1.1.1.2 ! root 1545: if (dmalen<=cip->b_xferdma) 1.1 root 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); 1.1.1.2 ! root 1591: #else /* MACH_KERNEL */ 1.1 root 1592: cmdp->c_timeid = timeout(fdintr,uip->dev->ctlr,cnt0); 1.1.1.2 ! root 1593: #endif /* MACH_KERNEL */ 1.1 root 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--) 1.1.1.2 ! root 1634: if(((ind=inb(STSREG(uip->addr))) & DATAOK) && 1.1 root 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); 1.1.1.2 ! root 1658: #else /* MACH_KERNEL */ 1.1 root 1659: cmdp->c_mtrid = timeout(mtr_off,uip,MTRSTOP); 1.1.1.2 ! root 1660: #endif /* MACH_KERNEL */ 1.1 root 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.