|
|
1.1 ! root 1: /* 5-29-84 dsrelease checks for zombie state or even death */ ! 2: /* dsclose() shuts down device */ ! 3: /* DSWAIT added */ ! 4: /* 5-25-84 process pointer saved in dsopen for dsintr() */ ! 5: /* vsunlock must then be duplicated using correct process structure */ ! 6: /* the interrelation of dsstart-sleeping, dsintr, and dscleanup ! 7: needs to be cleaned up ! 8: Probably dscleanup should not call wakeup */ ! 9: ! 10: ! 11: #include "ds.h" ! 12: # if NDS > 0 ! 13: ! 14: /* ! 15: * DSC System 200 driver ! 16: * via DSC dma11. ! 17: * vax 4.1bsd version ! 18: */ ! 19: ! 20: #include "../h/param.h" ! 21: #include "../h/systm.h" ! 22: #include "../h/mount.h" ! 23: #include "../h/dir.h" ! 24: #include "../h/user.h" ! 25: #include "../h/pte.h" ! 26: #include "../h/map.h" ! 27: #include "../h/buf.h" ! 28: #include "../h/ubareg.h" ! 29: #include "../h/ubavar.h" ! 30: #include "../h/conf.h" ! 31: #include "../h/proc.h" ! 32: #include "../h/file.h" ! 33: #include "../h/vmmac.h" ! 34: ! 35: #include "../h/dsreg.h" ! 36: #include "../h/dsc.h" ! 37: ! 38: /* ! 39: * THESE ARE SITE-SPECIFIC ! 40: * ! 41: * starting base for the ! 42: * d/a and a/d converters, ! 43: * for setting up sequence ram. ! 44: */ ! 45: ! 46: /* ! 47: * reset device ! 48: */ ! 49: # define RESETDEV bit(4) ! 50: # define dsseq(sc, reg, conv, dir) \ ! 51: (sc->c_ascseq[reg] = conv | ((dir & 01) << 6)) ! 52: ! 53: /* ! 54: * ds flags ! 55: */ ! 56: # define DS_CLOSED 0 ! 57: # define DS_OPEN bit(0) ! 58: # define DS_IDLE bit(1) ! 59: # define DS_NDSK bit(2) ! 60: # define DS_MON bit(3) ! 61: # define DS_BRD bit(4) ! 62: # define DS_READ bit(5) ! 63: # define DS_WRITE bit(6) ! 64: ! 65: ! 66: # define DSPRI (PZERO+1) ! 67: /* ! 68: * Redundant book-keeping ! 69: * to help avoid page-wise overlap of buffers ! 70: * remember that this device is both asynchronous and ! 71: * uses user-supplied buffers ! 72: */ ! 73: struct dspageinfo { ! 74: int firstunit, ! 75: lastunit; /* in units of CLSIZE*NBPG, i.e. 1024 */ ! 76: }; ! 77: /* ! 78: * relevant information ! 79: * about the dma and asc ! 80: */ ! 81: struct ds_softc { ! 82: short c_dmacsr; /* copy of dma csr */ ! 83: short c_asccsr; /* copy of asc csr */ ! 84: short c_ascflags; /* initial asc flags */ ! 85: short c_ascsrt; /* sampling rate */ ! 86: short c_ascseq[8]; ! 87: int c_flags; /* internal flags */ ! 88: int c_errs; /* errors, returned via ioctl */ ! 89: int c_bufno; /* dsubinfo/buffer */ ! 90: int c_outbufno; ! 91: int c_uid; /* user id */ ! 92: short c_pid; /* process id */ ! 93: struct proc *c_procp; /* process structure pointer */ ! 94: int c_ubinfo[NDSB]; /* uba info */ ! 95: struct dspageinfo c_pageinfo[NDSB]; ! 96: struct buf c_dsb[NDSB]; /* buffer list */ ! 97: struct buf *c_ibp, *c_obp; /* buffer list pointers */ ! 98: int c_nbytes; /* total # of bytes xferred since reset */ ! 99: int c_to_idle; /* total # times idle flag set */ ! 100: int c_to_active; /* total # times idle flag cleared */ ! 101: } ds_softc[NDS]; ! 102: ! 103: int dsprobe(), dsattach(), dsintr(); ! 104: ! 105: struct uba_device *dsdinfo[NDS]; ! 106: struct uba_ctlr dsctlr[NDS], *dscinfo[NDS]; /* dsattach() sets dscinfo to point to this */ ! 107: ! 108: u_short dsstd[] = { ! 109: 0165400, 0 ! 110: }; ! 111: ! 112: struct uba_driver dsdriver = { ! 113: dsprobe, 0, dsattach, 0, dsstd, "ds", dsdinfo, "ds", dscinfo ! 114: }; ! 115: int dsdebug; ! 116: ! 117: /* ! 118: * all this just to generate ! 119: * an interrupt; rather ! 120: * involved isn't it? ! 121: */ ! 122: dsprobe(reg) ! 123: caddr_t reg; ! 124: { ! 125: register int br, cvec; /* value-result */ ! 126: register struct dsdevice *dsaddr; ! 127: int dummy; ! 128: ! 129: # ifdef lint ! 130: br = 0; cvec = br; br = cvec; ! 131: # endif lint ! 132: ! 133: dsaddr = (struct dsdevice *) reg; ! 134: ! 135: dsaddr->dmacsr = 0; ! 136: dsaddr->dmacls = 0; ! 137: dsaddr->ascseq[0] = DABASE+0 | ((DA & 01) << 6); ! 138: dsaddr->ascseq[0] |= LAST_SEQ; /* last sequence register */ ! 139: dsaddr->ascsrt = 0100; ! 140: dsaddr->dmacsr = DMA_IE; ! 141: dsaddr->asccsr = ASC_RUN | ASC_IE; ! 142: ! 143: DELAY(40000); ! 144: /* ! 145: * now shut everything down. ! 146: * too bad we have to duplicate ! 147: * the code from dsinit but to ! 148: * call dsinit we need to give ! 149: * it a unit. ! 150: */ ! 151: ! 152: dsaddr->dmacls = 0; ! 153: dummy = dsaddr->dmasar; /* clears sar flag */ ! 154: dsaddr->dmaclr = 0; ! 155: ! 156: dummy = dsaddr->ascrst; ! 157: dsaddr->ascrst = 0; ! 158: ! 159: return(1); ! 160: } ! 161: ! 162: dsattach(ui) ! 163: struct uba_device *ui; ! 164: { ! 165: register struct uba_ctlr *um; ! 166: register int unit; ! 167: register int i; ! 168: ! 169: unit = ui->ui_unit; ! 170: ! 171: um = &dsctlr[unit]; ! 172: dscinfo[unit] = um; ! 173: ui->ui_ctlr = unit; ! 174: ui->ui_mi = um; ! 175: um->um_driver = ui->ui_driver; ! 176: um->um_ctlr = unit; ! 177: um->um_ubanum = ui->ui_ubanum; ! 178: um->um_alive = 1; ! 179: um->um_intr = ui->ui_intr; ! 180: um->um_addr = ui->ui_addr; ! 181: um->um_hd = ui->ui_hd; ! 182: ds_softc[unit].c_flags = DS_IDLE; ! 183: for(i=0;i<NDSB;i++) ! 184: ds_softc[unit].c_dsb[i].b_flags &= ~B_BUSY; ! 185: } ! 186: ! 187: /* ARGSUSED */ ! 188: dsopen(dev, flag) ! 189: dev_t dev; ! 190: { ! 191: register struct dsdevice *dsaddr; ! 192: register struct uba_device *ui; ! 193: register struct ds_softc *sc; ! 194: register int unit, i; ! 195: register struct buf *bp; ! 196: int dummy; ! 197: ! 198: if ((unit = (minor(dev) & ~RESETDEV)) >= NDS) ! 199: goto bad; ! 200: ! 201: if ((ui = dsdinfo[unit]) == NULL) ! 202: goto bad; ! 203: ! 204: if (ui->ui_alive == 0) ! 205: goto bad; ! 206: ! 207: sc = &ds_softc[ui->ui_unit]; ! 208: dsaddr = (struct dsdevice *)ui->ui_addr; ! 209: ! 210: if(dsdebug)printf("dsopen: unit %d, flag %x\n",unit,flag); ! 211: if (dsaddr->dmacsr & DMA_OFL) { ! 212: u.u_error = ENXIO; ! 213: return; ! 214: } ! 215: ! 216: /* ! 217: * if this is the reset device ! 218: * then just do a reset and return. ! 219: */ ! 220: if (minor(dev) & RESETDEV) { ! 221: /* ! 222: * if the converters are in use then ! 223: * only the current user or root can ! 224: * do a reset. ! 225: */ ! 226: if (sc->c_flags & DS_OPEN) { ! 227: if ((sc->c_uid != u.u_ruid) && (u.u_uid != 0)) { ! 228: u.u_error = ENXIO; ! 229: return; ! 230: } ! 231: } ! 232: ds_softc[unit].c_flags = DS_CLOSED | DS_IDLE; ! 233: dscleanup(unit); ! 234: printf("ds%d: reset\n",unit); ! 235: return; ! 236: } ! 237: ! 238: /* ! 239: * only one person can use it at a time ! 240: * and it can't be opened for both reading and writing ! 241: */ ! 242: if (sc->c_flags & DS_OPEN || (flag & (FREAD|FWRITE)) == (FREAD|FWRITE)) { ! 243: bad: u.u_error = ENXIO; ! 244: return; ! 245: } ! 246: ! 247: /* ! 248: * initialize ! 249: */ ! 250: ! 251: ! 252: /* set defaults and initial conditions in ds_softc */ ! 253: sc->c_flags = DS_IDLE; ! 254: sc->c_errs = 0; ! 255: ! 256: sc->c_nbytes = sc->c_to_idle = sc->c_to_active = 0; ! 257: ! 258: sc->c_ascflags = (flag & FWRITE ? ASC_PLAY : ASC_RECORD) | ASC_HZ04; ! 259: sc->c_ascseq[0] = ( ! 260: (flag & FWRITE) ? ! 261: (DABASE+0 | (DA << 6)) : (ADBASE+0 | (AD << 6)) ! 262: ) | LAST_SEQ; ! 263: sc->c_ascsrt = 399; ! 264: ! 265: ! 266: sc->c_uid = u.u_ruid; ! 267: sc->c_pid = u.u_procp->p_pid; ! 268: sc->c_procp = u.u_procp; ! 269: if(dsdebug)printf("pid %d %d, flag %x stat %x\n", ! 270: sc->c_pid,sc->c_procp->p_pid,sc->c_procp->p_stat); ! 271: sc->c_flags |= DS_OPEN | (flag & FREAD ? DS_READ : DS_WRITE); ! 272: u.u_procp->p_flag |= SPHYSIO; ! 273: dsaddr->dmacsr = 0; ! 274: dummy = dsaddr->dmasar; ! 275: } ! 276: ! 277: /* ARGSUSED */ ! 278: dsclose(dev, flag) { ! 279: register int unit; ! 280: register struct dsdevice *dsaddr; ! 281: register struct uba_device *ui; ! 282: register struct ds_softc *sc; ! 283: ! 284: unit = minor(dev) & ~RESETDEV; ! 285: sc = &ds_softc[unit]; ! 286: ui = dsdinfo[unit]; ! 287: dsaddr = (struct dsdevice *)ui->ui_addr; ! 288: if(dsdebug)printf("X"); ! 289: if (sc->c_outbufno != sc->c_bufno && ! 290: sc->c_errs == 0 && !(sc->c_flags & DS_IDLE)) ! 291: tsleep((caddr_t)&ds_softc[unit], DSPRI,0); ! 292: dsaddr->asccsr = 0; ! 293: ds_softc[unit].c_flags = DS_CLOSED | DS_IDLE; ! 294: dscleanup(unit); ! 295: u.u_procp->p_flag &= ~ SPHYSIO; ! 296: if(dsdebug){ ! 297: printf("to_active %d, to_idle %d, c_nbytes %d\n", ! 298: sc->c_to_active, ! 299: sc->c_to_idle, ! 300: sc->c_nbytes); ! 301: printf("c_ascseq[0] %x\n",sc->c_ascseq[0]); ! 302: dsdb(dsaddr); ! 303: } ! 304: } ! 305: ! 306: /* ! 307: * ! 308: * Using u.u_count, u.u_base, each buffer header is set up. ! 309: * The converters only need the base address of the buffer and the word ! 310: * count. ! 311: * ! 312: */ ! 313: dsstart(dev, rw) ! 314: register dev_t dev; ! 315: { ! 316: register struct dsdevice *dsaddr; ! 317: register struct uba_device *ui; ! 318: register struct ds_softc *sc; ! 319: register struct buf *bp; ! 320: register int unit, c, bufno, ps; ! 321: int dummy,i, count; ! 322: caddr_t base; ! 323: int bits; ! 324: ! 325: if(dsdebug)printf("S"); ! 326: ! 327: unit = minor(dev) & ~RESETDEV; ! 328: sc = &ds_softc[unit]; ! 329: ui = dsdinfo[unit]; ! 330: dsaddr = (struct dsdevice *)ui->ui_addr; ! 331: ! 332: /* ! 333: * check user access rights to buffer ! 334: */ ! 335: if (useracc(u.u_base, u.u_count, rw==B_READ?B_WRITE:B_READ) == NULL) { ! 336: u.u_error = EFAULT; ! 337: return; ! 338: } ! 339: ! 340: if (sc->c_errs) { ! 341: u.u_error = EIO; ! 342: return; ! 343: } ! 344: ! 345: ! 346: /* ! 347: * Get a buffer for each 64K block ! 348: * point each device buffer somewhere into ! 349: * the user's buffer ! 350: */ ! 351: /* NOTE that in order to get reasonable performance, ! 352: * buffer lengths (initial u.u_count) must be either ! 353: * less than 64K or sufficiently greater than a multiple ! 354: * of 64K. ! 355: */ ! 356: base = u.u_base; ! 357: count = u.u_count; ! 358: while(count > 0) { ! 359: ! 360: if(dsdebug)printf("LT "); ! 361: ! 362: /* ! 363: * no hardware buffers left, sleep till interrupt ! 364: * wakes us up ! 365: */ ! 366: ! 367: ! 368: ps = spl6(); ! 369: if ((sc->c_dmacsr = dsaddr->dmacsr) & DMA_SFL) { ! 370: register ts; ! 371: if(dsdebug)printf("s"); ! 372: ts = tsleep((caddr_t) &ds_softc[unit], DSPRI, 0); ! 373: if(dsdebug)printf("w"); ! 374: switch(ts) { ! 375: case TS_SIG: ! 376: u.u_error = EINTR; ! 377: /* stop dsc, if active */ ! 378: dsaddr->asccsr = dummy = 0; ! 379: dscleanup(unit); ! 380: return; ! 381: case TS_OK: ! 382: if ((sc->c_dmacsr = dsaddr->dmacsr) & DMA_SFL) { ! 383: u.u_error = EIO; ! 384: printf("ds%d still full after tsleep\n",unit); ! 385: dscleanup(unit); ! 386: return; ! 387: } ! 388: /* I don't think this allows for a clean dsclose() ! 389: in all cases */ ! 390: if((sc->c_flags & DS_CLOSED) || ! 391: !(sc->c_flags & DS_OPEN)){ ! 392: if(dsdebug) ! 393: printf("ds: wakeup unopen\n"); ! 394: u.u_error = EIO; ! 395: dscleanup(unit); ! 396: return; ! 397: } ! 398: break; ! 399: default: ! 400: printf("ds: %x from tsleep\n",ts); ! 401: dscleanup(unit); ! 402: u.u_error = EIO; ! 403: return; ! 404: } ! 405: } ! 406: ! 407: splx(ps); ! 408: ! 409: ! 410: ps = spl6(); ! 411: ! 412: /* ! 413: * If device is IDLE (initial read/write, or datalate condition ! 414: * has been detected in dsintr()), (re)initialize dsc ! 415: */ ! 416: ! 417: if (sc->c_flags & DS_IDLE) { ! 418: ! 419: if(dsdebug) ! 420: printf("I1 "); ! 421: dsaddr->asccsr = sc->c_asccsr = sc->c_ascflags; ! 422: dummy = dsaddr->ascrst; ! 423: dsaddr->asccsr = (sc->c_asccsr |= ASC_IE); ! 424: dsaddr->ascsrt = sc->c_ascsrt; ! 425: {register j, i = 0; ! 426: do { ! 427: dsaddr->ascseq[i] = sc->c_ascseq[i]; ! 428: j = i++; ! 429: } while(!(sc->c_ascseq[j] & LAST_SEQ) && i<8); ! 430: } ! 431: dsaddr->dmacsr = sc->c_dmacsr = 0; ! 432: dsaddr->dmacls = 0; ! 433: dummy = dsaddr->dmasar; /* clears sfl flag */ ! 434: dsaddr->dmawc = -1; ! 435: dsaddr->dmacsr = sc->c_dmacsr = (DMA_IE | DMA_CHN ! 436: | (rw == B_READ ? DMA_W2M : 0) ); ! 437: ! 438: sc->c_bufno = sc->c_outbufno = 0; ! 439: sc->c_ibp = sc->c_obp = &sc->c_dsb[0]; /* correct? */ ! 440: ! 441: } ! 442: ! 443: ! 444: /* get next device buffer and set it up */ ! 445: bp = sc->c_ibp++; ! 446: if (sc->c_ibp > &sc->c_dsb[NDSB-1]) ! 447: sc->c_ibp = &sc->c_dsb[0]; ! 448: ! 449: /* hopefully redundant check against going to fast */ ! 450: if(bp->b_flags & B_BUSY){ ! 451: printf("dsstart: about to set up BUSY buffer!\n"); ! 452: u.u_error = EIO; ! 453: return; ! 454: } ! 455: ! 456: ! 457: c = MIN(count, 1024*64); ! 458: bp->b_un.b_addr = base; ! 459: bp->b_error = 0; ! 460: bp->b_proc = u.u_procp; ! 461: bp->b_dev = dev; ! 462: bp->b_blkno = sc->c_bufno; ! 463: bp->b_bcount = c; ! 464: bufno = sc->c_bufno % NDSB; ! 465: ! 466: /* the page computations should be relative to param.h defs */ ! 467: ! 468: sc->c_pageinfo[bufno].firstunit = (int)base >> 10; ! 469: sc->c_pageinfo[bufno].lastunit=(((int)base+c+1023)>>10)-1; ! 470: ! 471: for(i=0;i<NDSB;i++) ! 472: if((sc->c_dsb[i].b_flags & B_BUSY) ! 473: && ! 474: (!(sc->c_pageinfo[bufno].firstunit > ! 475: sc->c_pageinfo[i].lastunit) ! 476: && ! 477: !(sc->c_pageinfo[bufno].lastunit < ! 478: sc->c_pageinfo[i].firstunit))) { ! 479: printf("ds: buf %d overlaps %d\n",i,bufno); ! 480: u.u_error=EIO; ! 481: return; ! 482: } ! 483: ! 484: /* lock the buffer and send it off */ ! 485: ! 486: bp->b_flags = B_BUSY | B_PHYS | rw; ! 487: if(dsdebug)printf("lk%d %x %d ",bufno,base,c); ! 488: dslock(base, (int) c); /* fasten seat belts */ ! 489: ! 490: sc->c_ubinfo[bufno] = ubasetup(ui->ui_ubanum, bp, UBA_WANTBDP); ! 491: ! 492: dsaddr->dmablr = ~ (c >> 1); ! 493: dsaddr->dmasax = (sc->c_ubinfo[bufno] >> 16) & 03; ! 494: dsaddr->dmasar = sc->c_ubinfo[bufno]; ! 495: ! 496: sc->c_bufno++; ! 497: ! 498: /* ! 499: * start the dsc, if necessary ! 500: */ ! 501: if(sc->c_flags & DS_IDLE){ ! 502: if(dsdebug)printf("I2 "); ! 503: sc->c_flags &= ~DS_IDLE; ! 504: ++sc->c_to_active; ! 505: dsaddr->asccsr = (sc->c_asccsr |= ASC_RUN); ! 506: } ! 507: ! 508: splx(ps); ! 509: ! 510: base += c; ! 511: count -= c; ! 512: if(dsdebug)printf("LB%x",u.u_error); ! 513: } ! 514: ! 515: u.u_count = count; ! 516: } ! 517: dsdb(dsaddr) ! 518: register struct dsdevice *dsaddr; ! 519: { ! 520: printf("dmacsr %b\n", dsaddr->dmacsr, DMA_BITS); ! 521: printf("asccsr %b\n", dsaddr->asccsr, ASC_BITS); ! 522: printf("dmawc %o\t", dsaddr->dmawc); ! 523: printf("dmablr %o\n", dsaddr->dmablr); ! 524: printf("dmaac %o\t", dsaddr->dmaac); ! 525: printf("dmasar %o\n", dsaddr->dmasar); ! 526: printf("dmaacx %o\t", dsaddr->dmaacx); ! 527: printf("dmasax %o\n", dsaddr->dmasax); ! 528: printf("ascsrt(decimal) %d\n", dsaddr->ascsrt); ! 529: printf("ascseq[0] %o\n", dsaddr->ascseq[0]); ! 530: } ! 531: /* ! 532: * this is where the real work is done. we copy any device registers that ! 533: * we will be looking at to decrease the amount of traffic on the ds 200 ! 534: * bus. ! 535: * ! 536: */ ! 537: dsintr(dev) ! 538: dev_t dev; ! 539: { ! 540: register struct dsdevice *dsaddr; ! 541: register struct uba_device *ui; ! 542: register struct ds_softc *sc; ! 543: register struct buf *bp; ! 544: register int bufno; ! 545: register int i; ! 546: int unit, dummy; ! 547: ! 548: unit = minor(dev) & ~RESETDEV; ! 549: sc = &ds_softc[unit]; ! 550: ui = dsdinfo[unit]; ! 551: ! 552: dsaddr = (struct dsdevice *) dsdinfo[unit]->ui_addr; ! 553: ! 554: sc->c_dmacsr = dsaddr->dmacsr; ! 555: ! 556: dsaddr->dmacls = 0; ! 557: if(dsdebug)printf("i"); ! 558: if (sc->c_flags & DS_IDLE) { ! 559: printf("ds%d: interrupt while idle\n", unit); ! 560: return; ! 561: } ! 562: ! 563: if (sc->c_dmacsr & DMA_ERR) { ! 564: if(dsdebug)printf("e"); ! 565: sc->c_asccsr = (sc->c_dmacsr & DMA_XIN ? dsaddr->asccsr : 0); ! 566: dsaddr->asccsr = dummy = 0; ! 567: ! 568: dsaddr->dmacsr = (sc->c_dmacsr &= ~DMA_CHN); ! 569: if ((sc->c_dmacsr & (DMA_XER|DMA_UBA|DMA_AMPE|DMA_XBA)) ! 570: || (sc->c_asccsr & (ASC_BA|ASC_DCN|ASC_DNP))) { ! 571: ++sc->c_errs; ! 572: printf("ds%d error: asccsr=%b dmacsr=%b\n", ! 573: unit, sc->c_asccsr, ASC_BITS, ! 574: sc->c_dmacsr, DMA_BITS); ! 575: } else ! 576: sc->c_nbytes += sc->c_obp->b_bcount; ! 577: /* the above may be wrong, since DLT interrupt seems to occur ! 578: * separately from (and later than) DMA completion ! 579: * interrupt */ ! 580: dscleanup(unit); ! 581: return; ! 582: } ! 583: ! 584: /* ! 585: * get current buffer and release it ! 586: */ ! 587: ! 588: bp = sc->c_obp++; ! 589: if (sc->c_obp > &sc->c_dsb[NDSB-1]) ! 590: sc->c_obp = &sc->c_dsb[0]; ! 591: ! 592: sc->c_outbufno++; ! 593: if(dsdebug)printf("b "); ! 594: dsrelease(sc, ui, bp); ! 595: ! 596: /* ! 597: * update byte count. ! 598: */ ! 599: ! 600: sc->c_nbytes += bp->b_bcount; ! 601: ! 602: wakeup((caddr_t) &ds_softc[unit]); ! 603: } ! 604: ! 605: /* ! 606: * release resources, if any, associated with a buffer ! 607: */ ! 608: dsrelease(sc, ui, bp) ! 609: register struct ds_softc *sc; ! 610: struct uba_device *ui; ! 611: register struct buf *bp; ! 612: { ! 613: register int ps; ! 614: register struct pte *pte; ! 615: register int npf; ! 616: int bufno; ! 617: ! 618: bufno = bp->b_blkno % NDSB; ! 619: if(dsdebug)printf("R%d ",bufno); ! 620: /* ! 621: * release uba resources ! 622: * and memory resources if process seems healthy ! 623: */ ! 624: ps = spl6(); ! 625: ! 626: if (bp->b_flags & B_BUSY) { ! 627: if(dsdebug)printf("%x %d ",bp->b_un.b_addr,bp->b_bcount); ! 628: ubarelse(ui->ui_ubanum, &sc->c_ubinfo[bufno]); ! 629: ! 630: /* we can't call vsunlock() because u.u_procp may be ! 631: different */ ! 632: if( !(sc->c_pid == sc->c_procp->p_pid) || ! 633: (sc->c_procp->p_flag & SWEXIT) || ! 634: (sc->c_procp->p_stat == SZOMB)){ ! 635: /* process is dying or dead */ ! 636: /* exit() will release memory (does it unlock???) */ ! 637: /* but will not release uba resources */ ! 638: printf(" REL pid %d %d flag %x stat %x ",sc->c_pid, ! 639: sc->c_procp->p_pid,sc->c_procp->p_flag, ! 640: sc->c_procp->p_stat); ! 641: sc->c_flags |= DS_CLOSED; ! 642: } ! 643: else { ! 644: pte = vtopte(sc->c_procp,btop(bp->b_un.b_addr)); ! 645: npf = btoc(bp->b_bcount + ((int)(bp->b_un.b_addr)&CLOFSET)); ! 646: if(dsdebug)printf("U%x %d ",pte->pg_pfnum,npf); ! 647: while(npf > 0) { ! 648: munlock(pte->pg_pfnum); ! 649: if(sc->c_ascflags & ASC_RECORD) ! 650: pte->pg_m = 1; /* memory written */ ! 651: pte += CLSIZE; ! 652: npf -= CLSIZE; ! 653: } ! 654: } ! 655: ! 656: bp->b_flags = 0; /* better than resetting B_BUSY */ ! 657: } ! 658: ! 659: splx(ps); ! 660: } ! 661: ! 662: /* ! 663: * release all buffers and do general cleanup ! 664: */ ! 665: dscleanup(unit) ! 666: int unit; ! 667: { ! 668: register struct dsdevice *dsaddr; ! 669: register struct uba_device *ui; ! 670: register struct ds_softc *sc; ! 671: register struct buf *bp; ! 672: int dummy; ! 673: ! 674: unit = (unit & ~RESETDEV); ! 675: sc = &ds_softc[unit]; ! 676: ui = dsdinfo[unit]; ! 677: dsaddr = (struct dsdevice *) dsdinfo[unit]->ui_addr; ! 678: ! 679: if(dsdebug)printf("C "); ! 680: if (!(sc->c_flags & DS_IDLE)) ! 681: ++sc->c_to_idle; ! 682: sc->c_flags |= DS_IDLE; ! 683: ! 684: dsaddr->asccsr = dummy = 0; ! 685: dummy = dsaddr->ascrst; ! 686: dsaddr->dmacsr = dummy = 0; ! 687: dummy = dsaddr->dmasar; ! 688: ! 689: for (bp = &(sc->c_dsb[0]); bp < &(sc->c_dsb[NDSB]); ++bp) ! 690: dsrelease(sc, ui, bp); ! 691: ! 692: ! 693: /* if called from dsintr while dsstart is sleeping */ ! 694: ! 695: wakeup((caddr_t) &ds_softc[unit]); ! 696: } ! 697: ! 698: /* ! 699: * a/d conversion ! 700: */ ! 701: dsread(dev) ! 702: dev_t dev; ! 703: { ! 704: dsstart(dev, B_READ); /* writes on disk */ ! 705: } ! 706: ! 707: /* ! 708: * d/a conversion ! 709: */ ! 710: dswrite(dev) ! 711: dev_t dev; ! 712: { ! 713: dsstart(dev, B_WRITE); /* reads from disk */ ! 714: } ! 715: ! 716: /* ARGSUSED */ ! 717: dsioctl(dev, cmd, addr, flag) ! 718: dev_t dev; ! 719: caddr_t addr; ! 720: { ! 721: register struct dsdevice *dsaddr; ! 722: register struct ds_softc *sc; ! 723: register struct ds_seq *dq; ! 724: register struct ds_err *de; ! 725: register struct ds_trans *dt; ! 726: struct uba_device *ui; ! 727: struct ds_seq ds_seq; ! 728: struct ds_err ds_err; ! 729: struct ds_trans ds_trans; ! 730: int unit; ! 731: int flts; ! 732: int i; ! 733: int iarg[2]; ! 734: ! 735: if (minor(dev) & RESETDEV) { ! 736: u.u_error = EINVAL; ! 737: return; ! 738: } ! 739: unit = minor(dev) & ~RESETDEV; ! 740: ! 741: sc = &ds_softc[unit]; ! 742: ui = dsdinfo[unit]; ! 743: dsaddr = (struct dsdevice *) ui->ui_addr; ! 744: ! 745: switch (cmd) { ! 746: /* set sample rate */ ! 747: case DSRATE: ! 748: ! 749: if (copyin(addr, (caddr_t) iarg, (unsigned) sizeof(int))) { ! 750: u.u_error = EFAULT; ! 751: return; ! 752: } ! 753: sc->c_ascsrt = 4000000/iarg[0] - 1; ! 754: break; ! 755: ! 756: case DS08KHZ: ! 757: sc->c_ascflags &= ~ ASC_HZMSK; ! 758: sc->c_ascflags |= ASC_HZ08; /* set 8kHz filter */ ! 759: break; ! 760: ! 761: case DS04KHZ: ! 762: sc->c_ascflags &= ~ ASC_HZMSK; ! 763: sc->c_ascflags |= ASC_HZ04; /* set 4kHz filter */ ! 764: break; ! 765: ! 766: ! 767: ! 768: case DSBYPAS: ! 769: sc->c_ascflags &= ~ ASC_HZMSK; ! 770: sc->c_ascflags |= ASC_BYPASS; /* set bypass */ ! 771: break; ! 772: ! 773: /* fetch errors */ ! 774: case DSERRS: ! 775: de = &ds_err; ! 776: de->dma_csr = sc->c_dmacsr; ! 777: de->asc_csr = sc->c_asccsr; ! 778: de->errors = sc->c_errs; ! 779: if (copyout((caddr_t) de, addr, (unsigned) sizeof(struct ds_err))) { ! 780: u.u_error = EFAULT; ! 781: return; ! 782: } ! 783: break; ! 784: ! 785: /* fetch transition counts */ ! 786: case DSTRANS: ! 787: dt = &ds_trans; ! 788: dt->to_idle = sc->c_to_idle; ! 789: dt->to_active = sc->c_to_active; ! 790: if (copyout((caddr_t) dt, addr, sizeof(struct ds_trans))) { ! 791: u.u_error = EFAULT; ! 792: return; ! 793: } ! 794: break; ! 795: ! 796: /* how many samples actually converted */ ! 797: case DSDONE: ! 798: if (copyout((caddr_t) sc->c_nbytes, addr, (unsigned) sizeof(int))) { ! 799: u.u_error = EFAULT; ! 800: return; ! 801: } ! 802: break; ! 803: ! 804: case DSSTEREO: ! 805: while(!sc->c_flags & DS_IDLE); ! 806: if (sc->c_flags & DS_READ) { ! 807: dsseq(sc, 0, ADBASE, AD); ! 808: dsseq(sc, 1, ADBASE+1 | LAST_SEQ, AD); ! 809: } else { ! 810: dsseq(sc, 0, DABASE, DA); ! 811: dsseq(sc, 1, DABASE+1 | LAST_SEQ, DA); ! 812: } ! 813: break; ! 814: ! 815: case DSMONO: ! 816: while(!sc->c_flags & DS_IDLE); ! 817: if (sc->c_flags & DS_READ) ! 818: dsseq(sc, 0, ADBASE | LAST_SEQ, AD); ! 819: else ! 820: dsseq(sc, 0, DABASE | LAST_SEQ, DA); ! 821: break; ! 822: ! 823: case DSRESET: ! 824: /* not adequate */ ! 825: sc->c_flags = DS_CLOSED | DS_IDLE; ! 826: dscleanup(unit); ! 827: break; ! 828: ! 829: case DSDEBUG: ! 830: dsdebug = 1 - dsdebug; ! 831: break; ! 832: case DSWAIT: ! 833: while(sc->c_outbufno != sc->c_bufno ! 834: && !(sc->c_flags & DS_IDLE)) ! 835: tsleep((caddr_t)&ds_softc[unit],DSPRI,0); ! 836: break; ! 837: ! 838: default: ! 839: u.u_error = ENOTTY; ! 840: break; ! 841: } ! 842: } ! 843: ! 844: ! 845: /* ! 846: * zero uba vector. ! 847: * shut off converters. ! 848: * set error bit. ! 849: */ ! 850: dsreset(uban) { ! 851: register struct uba_device *ui; ! 852: register struct ds_softc *sc; ! 853: register int ds; ! 854: ! 855: for (ds = 0; ds < NDS; ds++) { ! 856: if ((ui = dsdinfo[ds]) == NULL) ! 857: continue; ! 858: if (ui->ui_alive == 0) ! 859: continue; ! 860: if (ui->ui_ubanum != uban) ! 861: continue; ! 862: ! 863: printf(" ds%d", ds); ! 864: ! 865: sc = &ds_softc[ds]; ! 866: ! 867: /* ! 868: * release unibus resources ! 869: */ ! 870: sc->c_flags = DS_CLOSED | DS_IDLE; ! 871: dscleanup(ds); ! 872: } ! 873: } ! 874: /* ! 875: equivalent to vslock() from vmmem.c ! 876: inserted differently here for debugging convenience only. ! 877: */ ! 878: dslock(base, count) ! 879: caddr_t base; ! 880: { ! 881: register unsigned v; ! 882: register int npf; ! 883: register struct pte *pte; ! 884: ! 885: u.u_procp->p_flag |= SDLYU; ! 886: v = btop(base); ! 887: pte = vtopte(u.u_procp, v); ! 888: npf = btoc(count + ((int)base & CLOFSET)); ! 889: if(dsdebug)printf("Lk %x %d ",pte->pg_pfnum,npf); ! 890: while (npf > 0) { ! 891: if (pte->pg_v) ! 892: mlock(pte->pg_pfnum); ! 893: else ! 894: if (fubyte((caddr_t)ctob(v)) < 0) ! 895: panic("vslock"); ! 896: pte += CLSIZE; ! 897: v += CLSIZE; ! 898: npf -= CLSIZE; ! 899: } ! 900: u.u_procp->p_flag &= ~SDLYU; ! 901: } ! 902: # endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.