|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1988 The Regents of the University of California. ! 3: * All rights reserved. ! 4: * ! 5: * This code is derived from software contributed to Berkeley by ! 6: * Computer Consoles Inc. ! 7: * ! 8: * Redistribution and use in source and binary forms, with or without ! 9: * modification, are permitted provided that the following conditions ! 10: * are met: ! 11: * 1. Redistributions of source code must retain the above copyright ! 12: * notice, this list of conditions and the following disclaimer. ! 13: * 2. Redistributions in binary form must reproduce the above copyright ! 14: * notice, this list of conditions and the following disclaimer in the ! 15: * documentation and/or other materials provided with the distribution. ! 16: * 3. All advertising materials mentioning features or use of this software ! 17: * must display the following acknowledgement: ! 18: * This product includes software developed by the University of ! 19: * California, Berkeley and its contributors. ! 20: * 4. Neither the name of the University nor the names of its contributors ! 21: * may be used to endorse or promote products derived from this software ! 22: * without specific prior written permission. ! 23: * ! 24: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ! 25: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! 26: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ! 27: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE ! 28: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! 29: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS ! 30: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) ! 31: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT ! 32: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY ! 33: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF ! 34: * SUCH DAMAGE. ! 35: * ! 36: * @(#)dr.c 7.9 (Berkeley) 12/16/90 ! 37: */ ! 38: ! 39: #include "dr.h" ! 40: #if NDR > 0 ! 41: /* ! 42: * DRV11-W DMA interface driver. ! 43: * ! 44: * UNTESTED WITH 4.3 ! 45: */ ! 46: #include "../include/mtpr.h" ! 47: #include "../include/pte.h" ! 48: ! 49: #include "sys/param.h" ! 50: #include "sys/conf.h" ! 51: #include "sys/user.h" ! 52: #include "sys/proc.h" ! 53: #include "sys/map.h" ! 54: #include "sys/ioctl.h" ! 55: #include "sys/buf.h" ! 56: #include "sys/vm.h" ! 57: #include "sys/kernel.h" ! 58: ! 59: #include "../vba/vbavar.h" ! 60: #include "../vba/drreg.h" ! 61: ! 62: #define YES 1 ! 63: #define NO 0 ! 64: ! 65: struct vba_device *drinfo[NDR]; ! 66: struct dr_aux dr_aux[NDR]; ! 67: ! 68: unsigned drminphys(); ! 69: int drprobe(), drintr(), drattach(), drtimo(), drrwtimo(); ! 70: int drstrategy(); ! 71: extern struct vba_device *drinfo[]; ! 72: static long drstd[] = { 0 }; ! 73: struct vba_driver drdriver = ! 74: { drprobe, 0, drattach, 0, drstd, "rs", drinfo }; ! 75: ! 76: #define RSUNIT(dev) (minor(dev) & 7) ! 77: #define SPL_UP spl5 ! 78: ! 79: /* -------- Per-unit data -------- */ ! 80: ! 81: extern struct dr_aux dr_aux[]; ! 82: ! 83: #ifdef DR_DEBUG ! 84: long DR11 = 0; ! 85: #endif ! 86: ! 87: drprobe(reg, vi) ! 88: caddr_t reg; ! 89: struct vba_device *vi; ! 90: { ! 91: register int br, cvec; /* must be r12, r11 */ ! 92: struct rsdevice *dr; ! 93: ! 94: #ifdef lint ! 95: br = 0; cvec = br; br = cvec; ! 96: drintr(0); ! 97: #endif ! 98: if (badaddr(reg, 2)) ! 99: return (0); ! 100: dr = (struct rsdevice *)reg; ! 101: dr->dr_intvect = --vi->ui_hd->vh_lastiv; ! 102: #ifdef DR_DEBUG ! 103: printf("dprobe: Set interrupt vector %lx and init\n",dr->dr_intvec); ! 104: #endif ! 105: /* generate interrupt here for autoconfig */ ! 106: dr->dr_cstat = MCLR; /* init board and device */ ! 107: #ifdef DR_DEBUG ! 108: printf("drprobe: Initial status %lx\n", dr->dr_cstat); ! 109: #endif ! 110: br = 0x18, cvec = dr->dr_intvect; /* XXX */ ! 111: return (sizeof (struct rsdevice)); /* DR11 exist */ ! 112: } ! 113: ! 114: /* ARGSUSED */ ! 115: drattach(ui) ! 116: struct vba_device *ui; ! 117: { ! 118: register struct dr_aux *rsd; ! 119: ! 120: rsd = &dr_aux[ui->ui_unit]; ! 121: rsd->dr_flags = DR_PRES; /* This dr11 is present */ ! 122: rsd->dr_addr = (struct rsdevice *)ui->ui_addr; /* Save addr of this dr11 */ ! 123: rsd->dr_istat = 0; ! 124: rsd->dr_bycnt = 0; ! 125: rsd->dr_cmd = 0; ! 126: rsd->currenttimo = 0; ! 127: } ! 128: ! 129: /*ARGSUSED*/ ! 130: dropen(dev, flag) ! 131: dev_t dev; ! 132: int flag; ! 133: { ! 134: register int unit = RSUNIT(dev); ! 135: register struct rsdevice *dr; ! 136: register struct dr_aux *rsd; ! 137: ! 138: if (drinfo[unit] == 0 || !drinfo[unit]->ui_alive) ! 139: return (ENXIO); ! 140: dr = RSADDR(unit); ! 141: rsd = &dr_aux[unit]; ! 142: if (rsd->dr_flags & DR_OPEN) { ! 143: #ifdef DR_DEBUG ! 144: printf("\ndropen: dr11 unit %ld already open",unit); ! 145: #endif ! 146: return (ENXIO); /* DR11 already open */ ! 147: } ! 148: rsd->dr_flags |= DR_OPEN; /* Mark it OPEN */ ! 149: rsd->dr_istat = 0; /* Clear status of previous interrupt */ ! 150: rsd->rtimoticks = hz; /* Set read no stall timout to 1 sec */ ! 151: rsd->wtimoticks = hz*60; /* Set write no stall timout to 1 min */ ! 152: dr->dr_cstat = DR_ZERO; /* Clear function & latches */ ! 153: dr->dr_pulse = (RDMA | RATN); /* clear leftover attn & e-o-r flags */ ! 154: drtimo(dev); /* start the self kicker */ ! 155: return (0); ! 156: } ! 157: ! 158: drclose (dev) ! 159: dev_t dev; ! 160: { ! 161: register int unit = RSUNIT(dev); ! 162: register struct dr_aux *dra; ! 163: register struct rsdevice *rs; ! 164: register short s; ! 165: ! 166: dra = &dr_aux[unit]; ! 167: if ((dra->dr_flags & DR_OPEN) == 0) { ! 168: #ifdef DR_DEBUG ! 169: printf("\ndrclose: DR11 device %ld not open",unit); ! 170: #endif ! 171: return; ! 172: } ! 173: dra->dr_flags &= ~(DR_OPEN|DR_ACTV); ! 174: rs = dra->dr_addr; ! 175: s = SPL_UP(); ! 176: rs->dr_cstat = DR_ZERO; ! 177: if (dra->dr_buf.b_flags & B_BUSY) { ! 178: dra->dr_buf.b_flags &= ~B_BUSY; ! 179: wakeup((caddr_t)&dra->dr_buf.b_flags); ! 180: } ! 181: splx(s); ! 182: return (0); ! 183: } ! 184: ! 185: ! 186: /* drread() works exactly like drwrite() except that the ! 187: B_READ flag is used when physio() is called ! 188: */ ! 189: drread (dev, uio) ! 190: dev_t dev; ! 191: struct uio *uio; ! 192: { register struct dr_aux *dra; ! 193: register struct buf *bp; ! 194: register int spl, err; ! 195: register int unit = RSUNIT(dev); ! 196: ! 197: if (uio->uio_iov->iov_len <= 0 || /* Negative count */ ! 198: uio->uio_iov->iov_len & 1 || /* odd count */ ! 199: (int)uio->uio_iov->iov_base & 1) /* odd destination address */ ! 200: return (EINVAL); ! 201: #ifdef DR_DEBUG ! 202: if (DR11 & 8) ! 203: printf("\ndrread: (len:%ld)(base:%lx)", ! 204: uio->uio_iov->iov_len,(int)uio->uio_iov->iov_base); ! 205: #endif ! 206: dra = &dr_aux[RSUNIT(dev)]; ! 207: dra->dr_op = DR_READ; ! 208: bp = &dra->dr_buf; ! 209: bp->b_resid = 0; ! 210: if (dra->dr_flags & DR_NORSTALL) { ! 211: /* ! 212: * We are in no stall mode, start the timer, ! 213: * raise IPL so nothing can stop us once the ! 214: * timer's running ! 215: */ ! 216: spl = SPL_UP(); ! 217: timeout(drrwtimo, (caddr_t)((dra->currenttimo<<8) | unit), ! 218: (int)dra->rtimoticks); ! 219: err = physio(drstrategy, bp, dev,B_READ, drminphys, uio); ! 220: splx(spl); ! 221: if (err) ! 222: return (err); ! 223: dra->currenttimo++; /* Update current timeout number */ ! 224: /* Did we timeout */ ! 225: if (dra->dr_flags & DR_TMDM) ! 226: dra->dr_flags &= ~DR_TMDM; /* Clear timeout flag */ ! 227: return (err); ! 228: } ! 229: return (physio(drstrategy, bp, dev,B_READ, drminphys, uio)); ! 230: } ! 231: ! 232: drwrite(dev, uio) ! 233: dev_t dev; ! 234: struct uio *uio; ! 235: { register struct dr_aux *dra; ! 236: register struct buf *bp; ! 237: register int unit = RSUNIT(dev); ! 238: int spl, err; ! 239: ! 240: if (uio->uio_iov->iov_len <= 0 || uio->uio_iov->iov_len & 1 || ! 241: (int)uio->uio_iov->iov_base & 1) ! 242: return (EINVAL); ! 243: #ifdef DR_DEBUG ! 244: if (DR11 & 4) ! 245: printf("\ndrwrite: (len:%ld)(base:%lx)", ! 246: uio->uio_iov->iov_len,(int)uio->uio_iov->iov_base); ! 247: #endif ! 248: dra = &dr_aux[RSUNIT(dev)]; ! 249: dra->dr_op = DR_WRITE; ! 250: bp = &dra->dr_buf; ! 251: bp->b_resid = 0; ! 252: if (dra->dr_flags & DR_NOWSTALL) { ! 253: /* ! 254: * We are in no stall mode, start the timer, ! 255: * raise IPL so nothing can stop us once the ! 256: * timer's running ! 257: */ ! 258: spl = SPL_UP(); ! 259: timeout(drrwtimo,(caddr_t)((dra->currenttimo<<8) | unit), ! 260: (int)dra->wtimoticks); ! 261: err = physio (drstrategy, bp, dev,B_WRITE, drminphys, uio); ! 262: splx(spl); ! 263: if (err) ! 264: return (err); ! 265: dra->currenttimo++; /* Update current timeout number */ ! 266: /* Did we timeout */ ! 267: if (dra->dr_flags & DR_TMDM) ! 268: dra->dr_flags &= ~DR_TMDM; /* Clear timeout flag */ ! 269: return (err); ! 270: } ! 271: return (physio(drstrategy, bp, dev,B_WRITE, drminphys, uio)); ! 272: } ! 273: ! 274: /* ! 275: * Routine used by calling program to issue commands to dr11 driver and ! 276: * through it to the device. ! 277: * It is also used to read status from the device and driver and to wait ! 278: * for attention interrupts. ! 279: * Status is returned in an 8 elements unsigned short integer array, the ! 280: * first two elements of the array are also used to pass arguments to ! 281: * drioctl() if required. ! 282: * The function bits to be written to the dr11 are included in the cmd ! 283: * argument. Even if they are not being written to the dr11 in a particular ! 284: * drioctl() call, they will update the copy of cmd that is stored in the ! 285: * driver. When drstrategy() is called, this updated copy is used if a ! 286: * deferred function bit write has been specified. The "side effect" of ! 287: * calls to the drioctl() requires that the last call prior to a read or ! 288: * write has an appropriate copy of the function bits in cmd if they are ! 289: * to be used in drstrategy(). ! 290: * When used as command value, the contents of data[0] is the command ! 291: * parameter. ! 292: */ ! 293: drioctl(dev, cmd, data) ! 294: dev_t dev; ! 295: int cmd; ! 296: long *data; ! 297: { ! 298: register int unit = RSUNIT(dev); ! 299: register struct dr_aux *dra; ! 300: register struct rsdevice *rsaddr = RSADDR(unit); ! 301: int s, error = 0; ! 302: u_short status; ! 303: long temp; ! 304: ! 305: #ifdef DR_DEBUG ! 306: if (DR11 & 0x10) ! 307: printf("\ndrioctl: (dev:%lx)(cmd:%lx)(data:%lx)(data[0]:%lx)", ! 308: dev,cmd,data,data[0]); ! 309: #endif ! 310: dra = &dr_aux[unit]; ! 311: dra->dr_cmd = 0; /* Fresh copy; clear all previous flags */ ! 312: switch (cmd) { ! 313: ! 314: case DRWAIT: /* Wait for attention interrupt */ ! 315: #ifdef DR_DEBUG ! 316: printf("\ndrioctl: wait for attention interrupt"); ! 317: #endif ! 318: s = SPL_UP(); ! 319: /* ! 320: * If the attention flag in dr_flags is set, it probably ! 321: * means that an attention has arrived by the time a ! 322: * previous DMA end-of-range interrupt was serviced. If ! 323: * ATRX is set, we will return with out sleeping, since ! 324: * we have received an attention since the last call to ! 325: * wait on attention. This may not be appropriate for ! 326: * some applications. ! 327: */ ! 328: if ((dra->dr_flags & DR_ATRX) == 0) { ! 329: dra->dr_flags |= DR_ATWT; /* Set waiting flag */ ! 330: /* ! 331: * Enable interrupt; use pulse reg. ! 332: * so function bits are not changed ! 333: */ ! 334: rsaddr->dr_pulse = IENB; ! 335: error = tsleep((caddr_t)&dra->dr_cmd, DRPRI | PCATCH, ! 336: devio, 0); ! 337: } ! 338: splx(s); ! 339: break; ! 340: ! 341: case DRPIOW: /* Write to p-i/o register */ ! 342: rsaddr->dr_data = data[0]; ! 343: break; ! 344: ! 345: case DRPACL: /* Send pulse to device */ ! 346: rsaddr->dr_pulse = FCN2; ! 347: break; ! 348: ! 349: case DRDACL: /* Defer alco pulse until go */ ! 350: dra->dr_cmd |= DR_DACL; ! 351: break; ! 352: ! 353: case DRPCYL: /* Set cycle with next go */ ! 354: dra->dr_cmd |= DR_PCYL; ! 355: break; ! 356: ! 357: case DRDFCN: /* Update function with next go */ ! 358: dra->dr_cmd |= DR_DFCN; ! 359: break; ! 360: ! 361: case DRRATN: /* Reset attention flag */ ! 362: rsaddr->dr_pulse = RATN; ! 363: break; ! 364: ! 365: case DRRDMA: /* Reset DMA e-o-r flag */ ! 366: rsaddr->dr_pulse = RDMA; ! 367: break; ! 368: ! 369: case DRSFCN: /* Set function bits */ ! 370: temp = data[0] & DR_FMSK; ! 371: /* ! 372: * This has a very important side effect -- It clears ! 373: * the interrupt enable flag. That is fine for this driver, ! 374: * but if it is desired to leave interrupt enable at all ! 375: * times, it will be necessary to read the status register ! 376: * first to get IENB, or carry a software flag that indicates ! 377: * whether interrupts are set, and or this into the control ! 378: * register value being written. ! 379: */ ! 380: rsaddr->dr_cstat = temp; ! 381: break; ! 382: ! 383: case DRRPER: /* Clear parity flag */ ! 384: rsaddr->dr_pulse = RPER; ! 385: break; ! 386: ! 387: case DRSETRSTALL: /* Set read stall mode. */ ! 388: dra->dr_flags &= (~DR_NORSTALL); ! 389: break; ! 390: ! 391: case DRSETNORSTALL: /* Set no stall read mode. */ ! 392: dra->dr_flags |= DR_NORSTALL; ! 393: break; ! 394: ! 395: case DRGETRSTALL: /* Returns true if in read stall mode */ ! 396: data[0] = (dra->dr_flags & DR_NORSTALL)? 0 : 1; ! 397: break; ! 398: ! 399: case DRSETRTIMEOUT: /* Set read stall timeout (1/10 secs) */ ! 400: if (data[0] < 1) ! 401: error = EINVAL; ! 402: dra->rtimoticks = (data[0] * hz )/10; ! 403: break; ! 404: ! 405: case DRGETRTIMEOUT: /* Return read stall timeout */ ! 406: data[0] = ((dra->rtimoticks)*10)/hz; ! 407: break; ! 408: ! 409: case DRSETWSTALL: /* Set write stall mode. */ ! 410: dra->dr_flags &= (~DR_NOWSTALL); ! 411: break; ! 412: ! 413: case DRSETNOWSTALL: /* Set write stall mode. */ ! 414: dra->dr_flags |= DR_NOWSTALL; ! 415: break; ! 416: ! 417: case DRGETWSTALL: /* Return true if in write stall mode */ ! 418: data[0] = (dra->dr_flags & DR_NOWSTALL)? 0 : 1; ! 419: break; ! 420: ! 421: case DRSETWTIMEOUT: /* Set write stall timeout (1/10's) */ ! 422: if (data[0] < 1) ! 423: error = EINVAL; ! 424: dra->wtimoticks = (data[0] * hz )/10; ! 425: break; ! 426: ! 427: case DRGETWTIMEOUT: /* Return write stall timeout */ ! 428: data[0] = ((dra->wtimoticks)*10)/hz; ! 429: break; ! 430: ! 431: case DRWRITEREADY: /* Return true if can write data */ ! 432: data[0] = (rsaddr->dr_cstat & STTA)? 1 : 0; ! 433: break; ! 434: ! 435: case DRREADREADY: /* Return true if data to be read */ ! 436: data[0] = (rsaddr->dr_cstat & STTB)? 1 : 0; ! 437: break; ! 438: ! 439: case DRBUSY: /* Return true if device busy */ ! 440: /* ! 441: * Internally this is the DR11-W ! 442: * STAT C bit, but there is a bug in the Omega 500/FIFO ! 443: * interface board that it cannot drive this signal low ! 444: * for certain DR11-W ctlr such as the Ikon. We use the ! 445: * REDY signal of the CSR on the Ikon DR11-W instead. ! 446: */ ! 447: #ifdef notdef ! 448: data[0] = (rsaddr->dr_cstat & STTC)? 1 : 0; ! 449: #else ! 450: data[0] = ((rsaddr->dr_cstat & REDY)? 0 : 1); ! 451: #endif ! 452: break; ! 453: ! 454: case DRRESET: /* Reset device */ ! 455: /* Reset DMA ATN RPER flag */ ! 456: rsaddr->dr_pulse = (MCLR|RDMA|RATN|RPER); ! 457: DELAY(0x1f000); ! 458: while ((rsaddr->dr_cstat & REDY) == 0 && error == 0) ! 459: /* Wakeup by drtimo() */ ! 460: error = tsleep((caddr_t)dra, DRPRI | PCATCH, devio, 0); ! 461: dra->dr_istat = 0; ! 462: dra->dr_cmd = 0; ! 463: dra->currenttimo = 0; ! 464: break; ! 465: ! 466: case DR11STAT: { /* Copy back dr11 status to user */ ! 467: register struct dr11io *dr = (struct dr11io *)data; ! 468: dr->arg[0] = dra->dr_flags; ! 469: dr->arg[1] = rsaddr->dr_cstat; ! 470: dr->arg[2] = dra->dr_istat; /* Status at last interrupt */ ! 471: dr->arg[3] = rsaddr->dr_data; /* P-i/o input data */ ! 472: status = (u_short)((rsaddr->dr_addmod << 8) & 0xff00); ! 473: dr->arg[4] = status | (u_short)(rsaddr->dr_intvect & 0xff); ! 474: dr->arg[5] = rsaddr->dr_range; ! 475: dr->arg[6] = rsaddr->dr_rahi; ! 476: dr->arg[7] = rsaddr->dr_ralo; ! 477: break; ! 478: } ! 479: case DR11LOOP: /* Perform loopback test */ ! 480: /* ! 481: * NB: MUST HAVE LOOPBACK CABLE ATTACHED -- ! 482: * Test results are printed on system console ! 483: */ ! 484: if (error = suser(u.u_cred, &u.u_acflag)) ! 485: break; ! 486: dr11loop(rsaddr, dra, unit); ! 487: break; ! 488: ! 489: default: ! 490: return (EINVAL); ! 491: } ! 492: #ifdef DR_DEBUG ! 493: if (DR11 & 0x10) ! 494: printf("**** (data[0]:%lx)",data[0]); ! 495: #endif ! 496: return (error); ! 497: } ! 498: ! 499: #define NPAT 2 ! 500: #define DMATBL 20 ! 501: u_short tstpat[DMATBL] = { 0xAAAA, 0x5555}; ! 502: long DMAin = 0; ! 503: ! 504: /* ! 505: * Perform loopback test -- MUST HAVE LOOPBACK CABLE ATTACHED ! 506: * Test results are printed on system console ! 507: */ ! 508: dr11loop(dr, dra, unit) ! 509: struct rsdevice *dr; ! 510: struct dr_aux *dra; ! 511: int unit; ! 512: { ! 513: register long result, ix; ! 514: long addr, wait; ! 515: ! 516: dr->dr_cstat = MCLR; /* Clear board & device, disable intr */ ! 517: printf("\n\t ----- DR11 unit %ld loopback test -----", unit); ! 518: printf("\n\t Program I/O ..."); ! 519: for (ix=0;ix<NPAT;ix++) { ! 520: dr->dr_data = tstpat[ix]; /* Write to Data out register */ ! 521: result = dr->dr_data & 0xFFFF; /* Read it back */ ! 522: if (result != tstpat[ix]) { ! 523: printf("Failed, expected : %lx --- actual : %lx", ! 524: tstpat[ix], result); ! 525: return; ! 526: } ! 527: } ! 528: printf("OK\n\t Functions & Status Bits ..."); ! 529: dr->dr_cstat = (FCN1 | FCN3); ! 530: result = dr->dr_cstat & 0xffff; /* Read them back */ ! 531: if ((result & (STTC | STTA)) != (STTC |STTA)) { ! 532: printf("Failed, expected : %lx --- actual : %lx, ISR:%lx", ! 533: (STTA|STTC), (result & (STTA|STTC)), result); ! 534: return; ! 535: } ! 536: dr->dr_cstat = FCN2; ! 537: result = dr->dr_cstat & 0xffff; /* Read them back */ ! 538: if ((result & STTB) != STTB) { ! 539: printf("Failed, expected : %lx --- actual : %lx, ISR:%lx", ! 540: STTB, (result & STTB), result); ! 541: return; ! 542: } ! 543: printf("OK\n\t DMA output ..."); ! 544: if (DMAin) ! 545: goto dmain; ! 546: /* Initialize DMA data buffer */ ! 547: for (ix=0; ix<DMATBL; ix++) ! 548: tstpat[ix] = 0xCCCC + ix; ! 549: tstpat[DMATBL-1] = 0xCCCC; /* Last word output */ ! 550: /* Setup normal DMA */ ! 551: addr = (long)vtoph((struct proc *)0, (unsigned)tstpat); ! 552: dr->dr_walo = (addr >> 1) & 0xffff; ! 553: dr->dr_wahi = (addr >> 17) & 0x7fff; ! 554: /* Set DMA range count: (number of words - 1) */ ! 555: dr->dr_range = DMATBL - 1; ! 556: /* Set address modifier code to be used for DMA access to memory */ ! 557: dr->dr_addmod = DRADDMOD; ! 558: ! 559: /* ! 560: * Clear dmaf and attf to assure a clean dma start, also disable ! 561: * attention interrupt ! 562: */ ! 563: dr->dr_pulse = RDMA|RATN|RMSK; /* Use pulse register */ ! 564: dr->dr_cstat = GO|CYCL; /* GO...... */ ! 565: ! 566: /* Wait for DMA complete; REDY and DMAF are true in ISR */ ! 567: wait = 0; ! 568: while ((result=(dr->dr_cstat & (REDY|DMAF))) != (REDY|DMAF)) { ! 569: printf("\n\tWait for DMA complete...ISR : %lx", result); ! 570: if (++wait > 5) { ! 571: printf("\n\t DMA output fails...timeout!!, ISR:%lx", ! 572: result); ! 573: return; ! 574: } ! 575: } ! 576: result = dr->dr_data & 0xffff; /* Read last word output */ ! 577: if (result != 0xCCCC) { ! 578: printf("\n\t Fails, expected : %lx --- actual : %lx", ! 579: 0xCCCC, result); ! 580: return; ! 581: } ! 582: printf("OK\n\t DMA input ..."); ! 583: dmain: ! 584: dr->dr_data = 0x1111; /* DMA input data */ ! 585: /* Setup normal DMA */ ! 586: addr = (long)vtoph((struct proc *)0, (unsigned)tstpat); ! 587: dr->dr_walo = (addr >> 1) & 0xffff; ! 588: dr->dr_wahi = (addr >> 17) & 0x7fff; ! 589: dr->dr_range = DMATBL - 1; ! 590: dr->dr_addmod = (char)DRADDMOD; ! 591: dr->dr_cstat = FCN1; /* Set FCN1 in ICR to DMA in*/ ! 592: if ((dra->dr_flags & DR_LOOPTST) == 0) { ! 593: /* Use pulse reg */ ! 594: dr->dr_pulse = RDMA|RATN|RMSK|CYCL|GO; ! 595: /* Wait for DMA complete; REDY and DMAF are true in ISR */ ! 596: wait = 0; ! 597: while ((result=(dr->dr_cstat & (REDY|DMAF))) != (REDY|DMAF)) { ! 598: printf("\n\tWait for DMA to complete...ISR:%lx",result); ! 599: if (++wait > 5) { ! 600: printf("\n\t DMA input timeout!!, ISR:%lx", ! 601: result); ! 602: return; ! 603: } ! 604: } ! 605: } else { ! 606: /* Enable DMA e-o-r interrupt */ ! 607: dr->dr_pulse = IENB|RDMA|RATN|CYCL|GO; ! 608: /* Wait for DMA complete; DR_LOOPTST is false in dra->dr_flags*/ ! 609: wait = 0; ! 610: while (dra->dr_flags & DR_LOOPTST) { ! 611: result = dr->dr_cstat & 0xffff; ! 612: printf("\n\tWait for DMA e-o-r intr...ISR:%lx", result); ! 613: if (++wait > 7) { ! 614: printf("\n\t DMA e-o-r timeout!!, ISR:%lx", ! 615: result); ! 616: dra->dr_flags &= ~DR_LOOPTST; ! 617: return; ! 618: } ! 619: } ! 620: dra->dr_flags |= DR_LOOPTST; ! 621: } ! 622: mtpr(P1DC, tstpat); /* Purge cache */ ! 623: mtpr(P1DC, 0x3ff+tstpat); ! 624: for (ix=0; ix<DMATBL; ix++) { ! 625: if (tstpat[ix] != 0x1111) { ! 626: printf("\n\t Fails, ix:%d, expected:%x --- actual:%x", ! 627: ix, 0x1111, tstpat[ix]); ! 628: return; ! 629: } ! 630: } ! 631: if ((dra->dr_flags & DR_LOOPTST) == 0) { ! 632: dra->dr_flags |= DR_LOOPTST; ! 633: printf(" OK..\n\tDMA end of range interrupt..."); ! 634: goto dmain; ! 635: } ! 636: printf(" OK..\n\tAttention interrupt...."); ! 637: dr->dr_pulse = IENB|RDMA; ! 638: dr->dr_pulse = FCN2; ! 639: /* Wait for ATTN interrupt; DR_LOOPTST is false in dra->dr_flags*/ ! 640: wait = 0; ! 641: while (dra->dr_flags & DR_LOOPTST) { ! 642: result = dr->dr_cstat & 0xffff; ! 643: printf("\n\tWait for Attention intr...ISR:%lx",result); ! 644: if (++wait > 7) { ! 645: printf("\n\t Attention interrupt timeout!!, ISR:%lx", ! 646: result); ! 647: dra->dr_flags &= ~DR_LOOPTST; ! 648: return; ! 649: } ! 650: } ! 651: dra->dr_flags &= ~DR_LOOPTST; ! 652: printf(" OK..\n\tDone..."); ! 653: } ! 654: ! 655: /* Reset state on Unibus reset */ ! 656: /*ARGSUSED*/ ! 657: drreset(uban) ! 658: int uban; ! 659: { ! 660: ! 661: } ! 662: ! 663: /* ! 664: * An interrupt is caused either by an error, ! 665: * base address overflow, or transfer complete ! 666: */ ! 667: drintr(dr11) ! 668: int dr11; ! 669: { ! 670: register struct dr_aux *dra = &dr_aux[dr11]; ! 671: register struct rsdevice *rsaddr = RSADDR(dr11); ! 672: register struct buf *bp; ! 673: register short status; ! 674: ! 675: status = rsaddr->dr_cstat & 0xffff; /* get board status register */ ! 676: dra->dr_istat = status; ! 677: #ifdef DR_DEBUG ! 678: if (DR11 & 2) ! 679: printf("\ndrintr: dr11 status : %lx",status & 0xffff); ! 680: #endif ! 681: if (dra->dr_flags & DR_LOOPTST) { /* doing loopback test */ ! 682: dra->dr_flags &= ~DR_LOOPTST; ! 683: return; ! 684: } ! 685: /* ! 686: * Make sure this is not a stray interrupt; at least one of dmaf or attf ! 687: * must be set. Note that if the dr11 interrupt enable latch is reset ! 688: * during a hardware interrupt ack sequence, and by the we get to this ! 689: * point in the interrupt code it will be 0. This is done to give the ! 690: * programmer some control over how the two more-or-less independent ! 691: * interrupt sources on the board are handled. ! 692: * If the attention flag is set when drstrategy() is called to start a ! 693: * dma read or write an interrupt will be generated as soon as the ! 694: * strategy routine enables interrupts for dma end-of-range. This will ! 695: * cause execution of the interrupt routine (not necessarily bad) and ! 696: * will cause the interrupt enable mask to be reset (very bad since the ! 697: * dma end-of-range condition will not be able to generate an interrupt ! 698: * when it occurs) causing the dma operation to time-out (even though ! 699: * the dma transfer will be done successfully) or hang the process if a ! 700: * software time-out capability is not implemented. One way to avoid ! 701: * this situation is to check for a pending attention interrupt (attf ! 702: * set) by calling drioctl() before doing a read or a write. For the ! 703: * time being this driver will solve the problem by clearing the attf ! 704: * flag in the status register before enabling interrupts in ! 705: * drstrategy(). ! 706: * ! 707: * **** The IKON 10084 for which this driver is written will set both ! 708: * attf and dmaf if dma is terminated by an attention pulse. This will ! 709: * cause a wakeup(&dr_aux), which will be ignored since it is not being ! 710: * waited on, and an iodone(bp) which is the desired action. Some other ! 711: * dr11 emulators, in particular the IKON 10077 for the Multibus, donot ! 712: * dmaf in this case. This may require some addtional code in the inter- ! 713: * rupt routine to ensure that en iodone(bp) is issued when dma is term- ! 714: * inated by attention. ! 715: */ ! 716: bp = dra->dr_actf; ! 717: if ((status & (ATTF | DMAF)) == 0) { ! 718: printf("dr%d: stray interrupt, status=%x", dr11, status); ! 719: return; ! 720: } ! 721: if (status & DMAF) { /* End-of-range interrupt */ ! 722: dra->dr_flags |= DR_DMAX; ! 723: ! 724: #ifdef DR_DEBUG ! 725: if (DR11 & 2) ! 726: printf("\ndrintr: e-o-r interrupt,cstat:%lx,dr_flags:%lx", ! 727: status&0xffff, dra->dr_flags & DR_ACTV); ! 728: #endif ! 729: if ((dra->dr_flags & DR_ACTV) == 0) { ! 730: /* We are not doing DMA !! */ ! 731: bp->b_flags |= B_ERROR; ! 732: } else { ! 733: if (dra->dr_op == DR_READ) ! 734: mtpr(P1DC, bp->b_un.b_addr); ! 735: dra->dr_bycnt -= bp->b_bcount; ! 736: if (dra->dr_bycnt >0) { ! 737: bp->b_un.b_addr += bp->b_bcount; ! 738: bp->b_bcount = (dra->dr_bycnt > NBPG) ? NBPG: ! 739: dra->dr_bycnt; ! 740: drstart(rsaddr, dra, bp); ! 741: return; ! 742: } ! 743: } ! 744: dra->dr_flags &= ~DR_ACTV; ! 745: wakeup((caddr_t)dra); /* Wakeup waiting in drwait() */ ! 746: rsaddr->dr_pulse = (RPER|RDMA|RATN); /* reset dma e-o-r flag */ ! 747: } ! 748: /* ! 749: * Now test for attention interrupt -- It may be set in addition to ! 750: * the dma e-o-r interrupt. If we get one we will issue a wakeup to ! 751: * the drioctl() routine which is presumable waiting for one. ! 752: * The program may have to monitor the attention interrupt received ! 753: * flag in addition to doing waits for the interrupt. Futhermore, ! 754: * interrupts are not enabled unless dma is in progress or drioctl() ! 755: * has been called to wait for attention -- this may produce some ! 756: * strange results if attf is set on the dr11 when a read or a write ! 757: * is initiated, since that will enables interrupts. ! 758: * **** The appropriate code for this interrupt routine will probably ! 759: * be rather application dependent. ! 760: */ ! 761: if (status & ATTF) { ! 762: dra->dr_flags |= DR_ATRX; ! 763: dra->dr_flags &= ~DR_ATWT; ! 764: rsaddr->dr_cstat = RATN; /* reset attention flag */ ! 765: /* ! 766: * Some applications which use attention to terminate ! 767: * dma may also want to issue an iodone() here to ! 768: * wakeup physio(). ! 769: */ ! 770: wakeup((caddr_t)&dra->dr_cmd); ! 771: } ! 772: } ! 773: ! 774: unsigned ! 775: drminphys(bp) ! 776: struct buf *bp; ! 777: { ! 778: ! 779: if (bp->b_bcount > 65536) ! 780: bp->b_bcount = 65536; ! 781: } ! 782: ! 783: /* ! 784: * This routine performs the device unique operations on the DR11W ! 785: * it is passed as an argument to and invoked by physio ! 786: */ ! 787: drstrategy (bp) ! 788: register struct buf *bp; ! 789: { ! 790: register int s; ! 791: int unit = RSUNIT(bp->b_dev); ! 792: register struct rsdevice *rsaddr = RSADDR(unit); ! 793: register struct dr_aux *dra = &dr_aux[unit]; ! 794: register int ok; ! 795: #ifdef DR_DEBUG ! 796: register char *caddr; ! 797: long drva(); ! 798: #endif ! 799: ! 800: if ((dra->dr_flags & DR_OPEN) == 0) { /* Device not open */ ! 801: bp->b_error = ENXIO; ! 802: bp->b_flags |= B_ERROR; ! 803: iodone (bp); ! 804: return; ! 805: } ! 806: while (dra->dr_flags & DR_ACTV) ! 807: /* Device is active; should never be in here... */ ! 808: (void) tsleep((caddr_t)&dra->dr_flags, DRPRI, devio, 0); ! 809: dra->dr_actf = bp; ! 810: #ifdef DR_DEBUG ! 811: drva(dra, bp->b_proc, bp->b_un.b_addr, bp->b_bcount); ! 812: #endif ! 813: dra->dr_oba = bp->b_un.b_addr; /* Save original addr, count */ ! 814: dra->dr_obc = bp->b_bcount; ! 815: dra->dr_bycnt = bp->b_bcount; /* Save xfer count used by drintr() */ ! 816: if ((((long)bp->b_un.b_addr & 0x3fffffff) >> PGSHIFT) != ! 817: ((((long)bp->b_un.b_addr & 0x3fffffff) + bp->b_bcount) >> PGSHIFT)) ! 818: bp->b_bcount = NBPG - (((long)bp->b_un.b_addr) & PGOFSET); ! 819: dra->dr_flags |= DR_ACTV; /* Mark active (use in intr handler) */ ! 820: s = SPL_UP(); ! 821: drstart(rsaddr,dra,bp); ! 822: splx(s); ! 823: ok = drwait(rsaddr,dra); ! 824: #ifdef DR_DEBUG ! 825: if (DR11 & 0x40) { ! 826: caddr = (char *)dra->dr_oba; ! 827: if (dra->dr_op == DR_READ) ! 828: printf("\nAfter read: (%lx)(%lx)", ! 829: caddr[0]&0xff, caddr[1]&0xff); ! 830: } ! 831: #endif ! 832: dra->dr_flags &= ~DR_ACTV; /* Clear active flag */ ! 833: bp->b_un.b_addr = dra->dr_oba; /* Restore original addr, count */ ! 834: bp->b_bcount = dra->dr_obc; ! 835: if (!ok) ! 836: bp->b_flags |= B_ERROR; ! 837: /* Mark buffer B_DONE,so physstrat() in ml/machdep.c won't sleep */ ! 838: iodone(bp); ! 839: wakeup((caddr_t)&dra->dr_flags); ! 840: /* ! 841: * Return to the calling program (physio()). Physio() will sleep ! 842: * until awaken by a call to iodone() in the interupt handler -- ! 843: * which will be called by the dispatcher when it receives dma ! 844: * end-of-range interrupt. ! 845: */ ! 846: } ! 847: ! 848: drwait(rs, dr) ! 849: register struct rsdevice *rs; ! 850: register struct dr_aux *dr; ! 851: { ! 852: int s; ! 853: ! 854: s = SPL_UP(); ! 855: while (dr->dr_flags & DR_ACTV) ! 856: (void) tsleep((caddr_t)dr, DRPRI, devio, 0); ! 857: splx(s); ! 858: if (dr->dr_flags & DR_TMDM) { /* DMA timed out */ ! 859: dr->dr_flags &= ~DR_TMDM; ! 860: return (0); ! 861: } ! 862: if (rs->dr_cstat & (PERR|BERR|TERR)) { ! 863: dr->dr_actf->b_flags |= B_ERROR; ! 864: return (0); ! 865: } ! 866: dr->dr_flags &= ~DR_DMAX; ! 867: return (1); ! 868: } ! 869: ! 870: /* ! 871: * ! 872: * The lower 8-bit of tinfo is the minor device number, the ! 873: * remaining higher 8-bit is the current timout number ! 874: */ ! 875: drrwtimo(tinfo) ! 876: register u_long tinfo; ! 877: { ! 878: register long unit = tinfo & 0xff; ! 879: register struct dr_aux *dr = &dr_aux[unit]; ! 880: register struct rsdevice *rs = dr->dr_addr; ! 881: ! 882: /* ! 883: * If this is not the timeout that drwrite/drread is waiting ! 884: * for then we should just go away ! 885: */ ! 886: if ((tinfo &~ 0xff) != (dr->currenttimo << 8)) ! 887: return; ! 888: /* Mark the device timed out */ ! 889: dr->dr_flags |= DR_TMDM; ! 890: dr->dr_flags &= ~DR_ACTV; ! 891: rs->dr_pulse = RMSK; /* Inihibit interrupt */ ! 892: rs->dr_pulse = (RPER|RDMA|RATN|IENB); /* Clear DMA logic */ ! 893: /* ! 894: * Some applications will not issue a master after dma timeout, ! 895: * since doing so sends an INIT H pulse to the external device, ! 896: * which may produce undesirable side-effects. ! 897: */ ! 898: /* Wake up process waiting in drwait() and flag the error */ ! 899: dr->dr_actf->b_flags |= B_ERROR; ! 900: wakeup((caddr_t)dr->dr_cmd); ! 901: } ! 902: ! 903: /* ! 904: * Kick the driver every second ! 905: */ ! 906: drtimo(dev) ! 907: dev_t dev; ! 908: { ! 909: register int unit = RSUNIT(dev); ! 910: register struct dr_aux *dr; ! 911: ! 912: dr = &dr_aux[unit]; ! 913: if (dr->dr_flags & DR_OPEN) ! 914: timeout(drtimo, (caddr_t)dev, hz); ! 915: wakeup((caddr_t)dr); /* Wakeup any process waiting for interrupt */ ! 916: } ! 917: ! 918: #ifdef DR_DEBUG ! 919: drva(dra, p, va, bcnt) ! 920: struct dr_aux *dra; ! 921: struct proc *p; ! 922: char *va; ! 923: long bcnt; ! 924: { ! 925: register long first, last , np; ! 926: ! 927: if (DR11 & 0x20) { ! 928: first = ((long)(vtoph(p, (unsigned)va))) >> 10; ! 929: last = ((long)(vtoph(p, (unsigned)va+bcnt))) >> 10; ! 930: np = bcnt / 0x3ff; ! 931: printf("\ndrva: (op:%ld)(first:%ld)(last:%ld)(np:%ld)(cnt:%ld)", ! 932: dra->dr_op,first,last,np,bcnt); ! 933: } ! 934: } ! 935: #endif ! 936: ! 937: drstart(rsaddr, dra, bp) ! 938: register struct rsdevice *rsaddr; ! 939: register struct dr_aux *dra; ! 940: register struct buf *bp; ! 941: { ! 942: register long addr; ! 943: u_short go; ! 944: ! 945: #ifdef DR_DEBUG ! 946: if (dra->dr_op == DR_READ && (DR11 & 8)) { ! 947: char *caddr = (char *)bp->b_un.b_addr; ! 948: printf("\ndrstart: READ, bcnt:%ld",bp->b_bcount); ! 949: printf(",(%lx)(%lx)",caddr[0]&0xff,caddr[1]&0xff); ! 950: } ! 951: #endif ! 952: /* we are doing raw IO, bp->b_un.b_addr is user's address */ ! 953: addr = (long)vtoph(bp->b_proc, (unsigned)bp->b_un.b_addr); ! 954: /* ! 955: * Set DMA address into DR11 interace registers: DR11 requires that ! 956: * the address be right shifted 1 bit position before it is written ! 957: * to the board (The board will left shift it one bit position before ! 958: * it places the address on the bus ! 959: */ ! 960: rsaddr->dr_walo = (addr >> 1) & 0xffff; ! 961: rsaddr->dr_wahi = (addr >> 17) & 0x7fff; ! 962: /* Set DMA range count: (number of words - 1) */ ! 963: rsaddr->dr_range = (bp->b_bcount >> 1) - 1; ! 964: /* Set address modifier code to be used for DMA access to memory */ ! 965: rsaddr->dr_addmod = DRADDMOD; ! 966: /* ! 967: * Now determine whether this is a read or a write. ***** This is ! 968: * probably only usefull for link mode operation, since dr11 doesnot ! 969: * controll the direction of data transfer. The C1 control input ! 970: * controls whether the hardware is doing a read or a write. In link ! 971: * mode this is controlled by function 1 latch (looped back by the ! 972: * cable) and could be set the program. In the general case, the dr11 ! 973: * doesnot know in advance what the direction of transfer is - although ! 974: * the program and protocol logic probably is ! 975: */ ! 976: #ifdef DR_DEBUG ! 977: if (DR11 & 1) ! 978: printf( ! 979: "\ndrstrat: about to GO..,dr_cmd:%lx,drstat:%lx,drcnt:%ld,cdata:%lx,OP:%ld", ! 980: dra->dr_cmd, rsaddr->dr_cstat, rsaddr->dr_range, ! 981: rsaddr->dr_data, dra->dr_op); ! 982: #endif ! 983: /* ! 984: * Update function latches may have been done already by drioctl() if ! 985: * request from drioctl() ! 986: */ ! 987: if (dra->dr_cmd & DR_DFCN) { /* deferred function write */ ! 988: dra->dr_cmd &= ~DR_DFCN; /* Clear request */ ! 989: go = dra->dr_cmd & DR_FMSK; /* mask out fcn bits */ ! 990: rsaddr->dr_cstat = go; /* Write it to the board */ ! 991: } ! 992: /* Clear dmaf and attf to assure a clean dma start */ ! 993: rsaddr->dr_pulse = RATN|RDMA|RPER; ! 994: rsaddr->dr_cstat = IENB|GO|CYCL|dra->dr_op; /* GO...... */ ! 995: /* ! 996: * Now check for software cycle request -- usually ! 997: * by transmitter in link mode. ! 998: */ ! 999: if (dra->dr_cmd & DR_PCYL) { ! 1000: dra->dr_cmd &= ~DR_PCYL; /* Clear request */ ! 1001: rsaddr->dr_pulse = CYCL; /* Use pulse register again */ ! 1002: } ! 1003: /* ! 1004: * Now check for deferred ACLO FCNT2 pulse request -- usually to tell ! 1005: * the transmitter (via its attention) that we have enabled dma. ! 1006: */ ! 1007: if (dra->dr_cmd & DR_DACL) { ! 1008: dra->dr_cmd &= ~DR_DACL; /* Clear request */ ! 1009: rsaddr->dr_pulse = FCN2; /* Use pulse register again */ ! 1010: } ! 1011: } ! 1012: #endif NDR
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.