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