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