|
|
1.1 ! root 1: /* Jupiter driver -- both 8 bit programmed i/o and 16 bit dma i/o */ ! 2: ! 3: #include "ju.h" ! 4: #if NJU>0 ! 5: #include "../h/param.h" ! 6: #include "../h/dir.h" ! 7: #include "../h/user.h" ! 8: #include "../h/buf.h" ! 9: #include "../h/pte.h" ! 10: #include "../h/ubavar.h" ! 11: #include "../h/ubareg.h" ! 12: #include "../h/systm.h" ! 13: ! 14: #define JUPRI PZERO+10 ! 15: #define JULOWAT 50 ! 16: ! 17: struct judevice { ! 18: unsigned short jucsr, /* interface card csr */ ! 19: jutc, /* transfer count */ ! 20: juba, /* bus address */ ! 21: juxba, /* extended bus address */ ! 22: judcsr, /* device csr */ ! 23: judcw, /* device command word */ ! 24: judsw, /* device status word */ ! 25: juvec; /* interrupt vector */ ! 26: }; ! 27: ! 28: #define JBUFSIZ 512 ! 29: #define JUSIZ (2*JBUFSIZ) ! 30: ! 31: #define JNTRIES 2000 ! 32: #define MAXSAME 60 ! 33: struct ju { ! 34: unsigned char jucbuf[JUSIZ]; /* one buffer */ ! 35: unsigned char *jur, *juw; /* two chasing pointers */ ! 36: int jucc; /* char count to dismbiguate */ ! 37: unsigned short flag; /* the case of jur == juw */ ! 38: unsigned int writes, lastwrite; ! 39: unsigned short samewrite; ! 40: int waitcount; ! 41: } jutab[NJU]; ! 42: ! 43: int jutimeout; ! 44: int waitpoke, timerpoke; ! 45: /* FLAG BITS */ ! 46: #define OPEN 010 ! 47: #define DIWAIT 020 ! 48: #define DEBUG 040 ! 49: #define ASLP 0100 ! 50: #define ESLP 0200 ! 51: #define DMA 0400 ! 52: #define TIWAIT 01000 ! 53: ! 54: /* I/O LOCATIONS */ ! 55: #define DA 0777320 ! 56: #define CSR DA+0 ! 57: #define TC DA+02 ! 58: #define BA DA+04 ! 59: #define XBA DA+06 ! 60: #define DCSR DA+010 ! 61: #define DCW DA+012 ! 62: #define DSW DA+014 ! 63: #define VEC DA+016 ! 64: /* ! 65: DA device base address ! 66: CSR csr for interface card ! 67: TC transfer count ! 68: BA bus address ! 69: XBA extended bus address ! 70: DCSR csr for device ! 71: DCW command word to device ! 72: DSW status word from device ! 73: VEC interrupt vector ! 74: */ ! 75: ! 76: /* BIT DEFINITIONS: */ ! 77: ! 78: /* interface csr register */ ! 79: #define C_GO 1 ! 80: #define C_DFD 2 ! 81: #define C_BY 020 ! 82: #define C_DIR 040 ! 83: #define C_TIE 0100 ! 84: #define C_DON 0200 ! 85: #define C_FIFO 01400 ! 86: #define C_WDF 02000 ! 87: #define C_PGE 010000 ! 88: #define C_VE 020000 ! 89: #define C_MTO 040000 ! 90: #define C_ERR 0100000 ! 91: /* ! 92: C_GO dma go bit ! 93: C_DFD data flag done ! 94: C_BY byte mode ! 95: C_DIR xfer direction (1 for read from device) ! 96: C_TIE enable transfer complete interrupt ! 97: C_DON transfer done ! 98: C_FIFO fifo level ! 99: C_WDF waiting for data flag ! 100: C_PGE program error ! 101: C_VE vector error ! 102: C_MTO memory timeout ! 103: C_ERR any error ! 104: */ ! 105: ! 106: /* device csr register */ ! 107: #define D_RST 1 ! 108: #define D_SNS 2 ! 109: #define D_DIE 0100 ! 110: #define D_DIR 0200 ! 111: /* ! 112: D_RST reset terminal ! 113: D_SNS sense line ! 114: D_DIE enable devive interrupt ! 115: D_DIR device interrupt request ! 116: */ ! 117: ! 118: /* device command word */ ! 119: #define DC_SI 01000 ! 120: #define DC_RST 0400 ! 121: /* ! 122: DC_SI suppress interrupt from terminal ! 123: DC_RST reset terminal ! 124: */ ! 125: /* device status word */ ! 126: #define DS_BSY 0100000 ! 127: #define DS_PBR 040000 ! 128: #define DS_KSR 020000 ! 129: /* ! 130: DS_BSY device busy ! 131: DS_PBR parallel byte ready ! 132: DS_KSR keystroke ready ! 133: */ ! 134: ! 135: int juattach(), juprobe(), judgo(), judintr(), jutintr(); ! 136: int justrategy(), justart(); ! 137: ! 138: struct uba_ctlr *jucinfo[NJU]; ! 139: struct uba_ctlr juctlr[NJU]; /* juattach() sets jucinfo to point to this */ ! 140: struct uba_device *judinfo[NJU]; ! 141: u_short justd[] = { 0 }; ! 142: struct uba_driver judriver = ! 143: { juprobe, 0, juattach, judgo, justd, "ju", judinfo ,"ju", jucinfo }; ! 144: ! 145: #define ui_open ui_type ! 146: struct buf jubuf[NJU]; ! 147: struct buf judtab[NJU]; ! 148: juprobe(reg) ! 149: caddr_t reg; ! 150: { ! 151: register int br, cvec; ! 152: register struct judevice *juaddr = (struct judevice *)reg; ! 153: ! 154: juaddr->juvec = 0500; /* set interrupt vector xxx ? */ ! 155: /* ! 156: juaddr->judcsr &= ~D_DIR; |* clear interrupt request bit *| ! 157: juaddr->judcsr |= D_DIE; |* enable interrupt, the one that *| ! 158: |* happens when terminal is ready *| ! 159: juaddr->judcsr |= D_DIR; |*cause an interrupt *| ! 160: DELAY(10000); ! 161: */ ! 162: br = 0x14; /* BR Level 14 = UNIBUS 4 */ ! 163: cvec = 0500; ! 164: return(1); ! 165: } ! 166: ! 167: juattach(ui) /* initialization on system boot */ ! 168: register struct uba_device *ui; ! 169: { ! 170: register struct uba_ctlr *um; ! 171: register int unit; ! 172: ! 173: unit = ui->ui_unit; ! 174: ! 175: um = &juctlr[unit]; ! 176: jucinfo[unit] = um; ! 177: ui->ui_ctlr = unit; ! 178: ui->ui_mi = um; ! 179: um->um_driver = ui->ui_driver; ! 180: um->um_ctlr = unit; ! 181: um->um_ubanum = ui->ui_ubanum; ! 182: um->um_alive = 1; ! 183: um->um_intr = ui->ui_intr; ! 184: um->um_addr = ui->ui_addr; ! 185: um->um_hd = ui->ui_hd; ! 186: } ! 187: ! 188: static int jerror, ! 189: entries,direntries,breturns,oreturns, ! 190: impossible, jutotali, jubytes; ! 191: static int jwrites, jwaits, jwritepokes, jfullpokes, jreads; ! 192: juopen(dev, flag) ! 193: dev_t dev; ! 194: { ! 195: register int s; ! 196: register unit, d; ! 197: int jutimer(); ! 198: register struct ju *ju; ! 199: register struct uba_device *ui; ! 200: ! 201: d = minor(dev); ! 202: unit = d&07; ! 203: ju = &jutab[unit]; ! 204: ui = judinfo[unit]; ! 205: if(unit >= NJU || ui->ui_alive == 0 || (ju->flag & OPEN)) { ! 206: u.u_error = ENXIO; ! 207: return; ! 208: } ! 209: jerror=waitpoke=timerpoke=0; ! 210: entries=direntries=breturns=oreturns=0; ! 211: jwrites=jwaits=jwritepokes=jfullpokes=jreads=0; ! 212: jubytes=jutotali=impossible=0; ! 213: ju->flag = (d&077)|OPEN; ! 214: ju->juw = ju->jur = ju->jucbuf; ! 215: ju->jucc = 0; ! 216: ! 217: ui->ui_open++; ! 218: while(((struct judevice *)ui->ui_addr)->judsw&DS_BSY) ! 219: sleep((caddr_t)&lbolt,JUPRI); ! 220: if(jutimeout == 0) { /* i.e. there is not a timer already going */ ! 221: jutimeout++; ! 222: timeout(jutimer, (caddr_t)0, 60); ! 223: } ! 224: ! 225: } ! 226: ! 227: jutimer() ! 228: { ! 229: register struct ju *ju; ! 230: register unit, flag, ps; ! 231: register struct judevice *juaddr; ! 232: ! 233: for (unit=flag=0; unit < NJU; unit++) { ! 234: ju = &jutab[unit]; ! 235: if (ju->flag&OPEN==0) { ! 236: continue; ! 237: } ! 238: juaddr = (struct judevice *)(judinfo[unit]->ui_addr); ! 239: flag++; /* unit is active */ ! 240: ps = spl4(); ! 241: if (ju->flag & TIWAIT) { ! 242: if (ju->writes == ju->lastwrite) { ! 243: if (++(ju->samewrite) > MAXSAME) { ! 244: if(ju->flag & DEBUG)printf("timer TIWAIT\n"); ! 245: juaddr->jucsr &= ~C_GO; ! 246: jutintr(unit); ! 247: } ! 248: } else ! 249: ju->lastwrite = ju->writes; ! 250: } ! 251: if (ju->flag&DIWAIT) { ! 252: /* judintr thinks it has work to do, */ ! 253: /* is waiting for a device interrupt */ ! 254: if ((juaddr->judsw & DS_BSY) == 0) { ! 255: /* device is not busy! */ ! 256: timerpoke++; ! 257: judintr(unit); ! 258: } ! 259: } ! 260: splx(ps); ! 261: } ! 262: if(flag) { /* keep timer going */ ! 263: timeout(jutimer, (caddr_t)0, 60); ! 264: } else { /* no active devices, shut down timer */ ! 265: jutimeout = 0; ! 266: } ! 267: } ! 268: #define DEBUGON (('J'<<8)|1) ! 269: #define DEBUGOFF (('J'<<8)|2) ! 270: #define DMAON (('J'<<8)|3) ! 271: #define DMAOFF (('J'<<8)|4) ! 272: #define READREGS (('J'<<8)|6) ! 273: ! 274: struct juregs { ! 275: unsigned short jucsr, ! 276: judcsr, ! 277: judsw; ! 278: }; ! 279: ! 280: juioctl(dev, cmd, addr) ! 281: register dev_t dev; ! 282: register struct juregs *addr; ! 283: register cmd; ! 284: { ! 285: int unit; ! 286: struct ju *ju; ! 287: struct judevice *juaddr; ! 288: ! 289: unit = minor(dev)&07; ! 290: ju = &jutab[unit]; ! 291: juaddr = (struct judevice *)judinfo[unit]->ui_addr; ! 292: ! 293: switch(cmd){ ! 294: case DMAON: ! 295: if(ju->jucc > 0)juwait(ju,0); /* flush pg buffer */ ! 296: ju->flag |= DMA; ! 297: if(ju->flag & DEBUG)printf("ju: DMAON\n"); ! 298: break; ! 299: case DMAOFF: ! 300: ju->flag &= ~DMA; ! 301: break; ! 302: case READREGS: ! 303: addr->jucsr = juaddr->jucsr; ! 304: addr->judcsr = juaddr->judcsr; ! 305: addr->judsw = juaddr->judsw; ! 306: break; ! 307: case DEBUGON: ! 308: ju->flag |= DEBUG; ! 309: printf("ju: DEBUGON\n"); ! 310: break; ! 311: case DEBUGOFF: ! 312: ju->flag &= ~DEBUG; ! 313: break; ! 314: default: ! 315: u.u_error = EFAULT; ! 316: } ! 317: } ! 318: juclose(dev) ! 319: register dev_t dev; ! 320: { ! 321: register unit; ! 322: register struct ju *ju; ! 323: ! 324: unit = minor(dev)&07; ! 325: ju = &jutab[unit]; ! 326: ! 327: ju->flag &= ~OPEN; /* to shut off timer */ ! 328: juwait(ju,0); ! 329: ((struct judevice *)judinfo[unit]->ui_addr)->jucsr = 0; ! 330: ((struct judevice *)judinfo[unit]->ui_addr)->judcsr = 0; ! 331: ! 332: judinfo[unit]->ui_open = 0; ! 333: if(ju->flag&DEBUG) { ! 334: printf("juclose: errors %d waitpokes %d timerpokes %d\n", ! 335: jerror,waitpoke,timerpoke); ! 336: printf(" judintr: %d entries, of which %d had D_DIR set\n", ! 337: entries, direntries); ! 338: printf(" %d returns on busy, %d out bottom\n", ! 339: breturns, oreturns); ! 340: printf("%d writes, %d reads, %d writepokes, %d fullpokes, %d waits\n", ! 341: jwrites,jreads,jwritepokes,jfullpokes,jwaits); ! 342: if(jubytes) ! 343: printf("totali %d on %d bytes sent, %d average\n",jutotali,jubytes, ! 344: jutotali/jubytes); ! 345: } ! 346: ju->flag = 0; ! 347: } ! 348: ! 349: juwait(ju, count) ! 350: register struct ju *ju; ! 351: register count; ! 352: { ! 353: register int s, times; ! 354: register r; ! 355: ! 356: jwaits++; ! 357: times = 60; ! 358: ju->waitcount = count; ! 359: while(ju->jucc > count){ ! 360: ju->flag |= ASLP; ! 361: r = tsleep((caddr_t)ju, JUPRI, 1); ! 362: if(r == TS_TIME) { /* timed out */ ! 363: if ((ju->flag&DIWAIT) == 0) { ! 364: /* oddly enough judintr doesn't think it has */ ! 365: /* any work to do */ ! 366: s = spl4(); ! 367: waitpoke++; ! 368: judintr(ju-jutab); ! 369: splx(s); ! 370: } ! 371: times--; ! 372: if(times==0) { ! 373: printf("jupiter timeout, buffer flushed\n"); ! 374: goto flush; ! 375: } ! 376: } ! 377: if (r==TS_SIG) { ! 378: flush: ! 379: ju->jur = ju->juw = ju->jucbuf; ! 380: ju->jucc = 0; ! 381: } ! 382: } ! 383: } ! 384: ! 385: unsigned short jcheck(addr,bitmask,value) ! 386: register unsigned short *addr; ! 387: register unsigned int bitmask, value; ! 388: { ! 389: register int times; ! 390: unsigned short data; ! 391: ! 392: times = 0; ! 393: while (((data = *addr) & bitmask) != value) ! 394: if (times++ >= JNTRIES) { ! 395: times = 0; ! 396: if (tsleep((caddr_t)addr, JUPRI, 1) == TS_SIG) ! 397: return 0; ! 398: } ! 399: ! 400: return data; ! 401: } ! 402: ! 403: juread(dev) ! 404: { ! 405: register struct judevice *addr; ! 406: register struct ju *ju; ! 407: register int unit, count; ! 408: register unsigned char *bptr; ! 409: ! 410: unit = dev & 07; ! 411: ju = &jutab[unit]; ! 412: addr = (struct judevice *)judinfo[unit]->ui_addr; ! 413: jreads++; ! 414: ! 415: if (ju->jucc) ! 416: juwait(ju, 0); ! 417: if(ju->flag&DMA) { ! 418: if(ju->flag&DEBUG) ! 419: printf("attempting dma read to ju\n"); ! 420: ju->flag |= TIWAIT; ! 421: physio(justrategy,&jubuf[unit],dev,B_READ,minphys); ! 422: return; ! 423: } ! 424: count = u.u_count; ! 425: bptr = ju->jucbuf; ! 426: ! 427: addr->judcsr &= ~D_DIR; ! 428: if(ju->flag&DEBUG)printf("DSW address %o\n",&(addr->judsw)); ! 429: while (count--) { ! 430: *bptr++ = (unsigned char)(jcheck(&(addr->judsw),DS_PBR, DS_PBR) ! 431: &0xFF) ; ! 432: if(ju->flag&DEBUG)printf("DSW is %x\n",(unsigned int)addr->judsw); ! 433: jcheck(&(addr->judsw), DS_PBR, 0); ! 434: /* send PBA command */ ! 435: jcheck(&(addr->judsw), DS_BSY, 0); ! 436: addr->judcw = 033; ! 437: if(ju->flag & DEBUG)printf("end of read loop, data %x\n", ! 438: (int)(*(bptr-1))); ! 439: } ! 440: ! 441: iomove(ju->jucbuf, u.u_count, B_READ); ! 442: } ! 443: ! 444: juwrite(dev) ! 445: { ! 446: register struct ju *ju; ! 447: register unsigned char *p; ! 448: register c, cc; ! 449: register s; ! 450: register unsigned char *jur; ! 451: register int unit; ! 452: ! 453: unit = minor(dev) & 07; ! 454: ju = &jutab[unit]; ! 455: ju->writes++; ! 456: jwrites++; ! 457: ! 458: if(ju->flag&DMA) { ! 459: if(ju->flag&DEBUG) ! 460: printf("attempting dma write to ju\n"); ! 461: ju->flag |= TIWAIT; ! 462: physio(justrategy,&jubuf[unit],dev,B_WRITE,minphys); ! 463: } ! 464: else { ! 465: while(u.u_count) { ! 466: jur = ju->jur; ! 467: if(jur > ju->juw) ! 468: cc = jur - ju->juw; ! 469: else if (jur == ju->juw && ju->jucc != 0) ! 470: cc = 0; /* buffer full */ ! 471: else /* from juw to end of buffer */ ! 472: cc = ju->jucbuf + JUSIZ - ju->juw; ! 473: if(u.u_count < cc) ! 474: cc = u.u_count; ! 475: if(cc == 0) { /* the buffer must be full */ ! 476: s = spl4(); /* correct priority?xxx */ ! 477: if ((ju->flag&DIWAIT) == 0) { ! 478: jfullpokes++; ! 479: judintr(unit); ! 480: } ! 481: splx(s); ! 482: juwait(ju,JULOWAT); ! 483: } ! 484: else { /* queue up some characters */ ! 485: iomove(ju->juw, cc, B_WRITE); ! 486: if((ju->juw += cc) >= ju->jucbuf + JUSIZ) ! 487: ju->juw = ju->jucbuf; ! 488: s = spl4(); ! 489: ju->jucc += cc; ! 490: if (( ju->flag&DIWAIT) == 0) { ! 491: jwritepokes++; ! 492: judintr(unit); ! 493: } ! 494: splx(s); ! 495: } ! 496: } ! 497: } ! 498: } ! 499: ! 500: /* Since justrategy is currently called only by juwrite ! 501: via physio, there will be only one transaction in each ! 502: DMA-U's queue at a given time. So we tack the given buffer ! 503: header pointer on at the end of the queue, and call justart ! 504: */ ! 505: justrategy(bp) ! 506: register struct buf *bp; ! 507: { ! 508: register struct uba_device *ui; ! 509: register struct uba_ctlr *um; ! 510: register struct buf *dp; ! 511: register judvma; ! 512: dev_t unit; ! 513: int ps; ! 514: ! 515: ps = spl4(); ! 516: unit = minor(bp->b_dev); ! 517: ui = judinfo[unit]; ! 518: um = ui->ui_mi; /* ctlr pointer */ ! 519: dp = &judtab[unit]; ! 520: dp->b_actf = bp; ! 521: dp->b_actl = bp; ! 522: bp->av_forw = NULL; ! 523: um->um_tab.b_actf = dp; ! 524: um->um_tab.b_actl = dp; ! 525: um->um_cmd = C_TIE | C_GO; ! 526: if (bp->b_flags & B_READ) ! 527: um->um_cmd |= C_DIR; ! 528: ! 529: justart(um); ! 530: splx(ps); ! 531: } ! 532: ! 533: justart(um) ! 534: register struct uba_ctlr *um; ! 535: { ! 536: register struct buf *bp, *dp; ! 537: register struct judevice *juaddr; ! 538: ! 539: dp = um->um_tab.b_actf; ! 540: bp = dp->b_actf; ! 541: um->um_tab.b_active++; ! 542: juaddr = (struct judevice *)um->um_addr; ! 543: jcheck(&(juaddr->judsw), DS_BSY, 0); ! 544: juaddr->jutc = -bp->b_bcount / sizeof(short); ! 545: juaddr->judcsr = juaddr->jucsr = 0; ! 546: (void) ubago(judinfo[minor(bp->b_dev)]); ! 547: } ! 548: ! 549: judgo(um) ! 550: register struct uba_ctlr *um; ! 551: { ! 552: register struct judevice *juaddr = (struct judevice *)um->um_addr; ! 553: ! 554: juaddr->juba = um->um_ubinfo; ! 555: juaddr->juxba = (um->um_ubinfo>>16) & 3; ! 556: juaddr->jucsr = um->um_cmd; ! 557: } ! 558: jutintr(dev) ! 559: register dev_t dev; ! 560: { ! 561: register struct buf *bp, *dp; ! 562: register struct judevice *juaddr; ! 563: register struct uba_ctlr *um; ! 564: register unit; ! 565: register struct ju *ju; ! 566: ! 567: unit = minor(dev) & 07; ! 568: um = jucinfo[unit]; ! 569: ! 570: ju = &jutab[unit]; ! 571: ju->flag &= ~TIWAIT; ! 572: ju->samewrite = 0; ! 573: juaddr = (struct judevice *)um->um_addr; ! 574: juaddr->jucsr = 0; ! 575: if(um->um_tab.b_active == 0) ! 576: return; ! 577: ! 578: dp = um->um_tab.b_actf; ! 579: bp = dp->b_actf; ! 580: ! 581: /* should check for errors? */ ! 582: ! 583: um->um_tab.b_active = 0; ! 584: um->um_tab.b_errcnt = 0; ! 585: um->um_tab.b_actf = dp->b_forw; ! 586: dp->b_errcnt = 0; ! 587: dp->b_active = 0; ! 588: bp->b_resid = (-juaddr->jutc * sizeof(short)); ! 589: ubadone(um); ! 590: iodone(bp); ! 591: } ! 592: ! 593: static int jcount; ! 594: judintr(dev) ! 595: register dev_t dev; ! 596: { ! 597: register struct ju *ju; ! 598: register struct judevice *addr; ! 599: register c, cc, unit; ! 600: ! 601: unit = minor(dev) & 07; ! 602: ju = &jutab[unit]; ! 603: ju->flag &= ~DIWAIT; ! 604: addr = (struct judevice *)judinfo[unit]->ui_addr; ! 605: ! 606: entries++; if(addr->judcsr&D_DIR)direntries++; ! 607: ! 608: if (addr->jucsr&C_ERR) { ! 609: printf("error: ju %d %x\n",dev,(int)addr->jucsr); ! 610: addr->jucsr &= ~C_ERR; ! 611: ju->flag &= ~DIWAIT; ! 612: ju->flag |= ESLP; ! 613: jerror++; ! 614: return; ! 615: } ! 616: ! 617: cc = 0; ! 618: while (ju->jucc > 0) { ! 619: addr->judcsr &= ~D_DIR; /* clear interrupt request bit */ ! 620: for(jcount=0;jcount<JNTRIES;jcount++) ! 621: if( (addr->judsw&DS_BSY) == 0 )goto putout; ! 622: /* busy too long -- sleep */ ! 623: addr->judcsr |= D_DIE; ! 624: ju->flag |= DIWAIT; ! 625: if(ju->flag&ASLP && ju->jucc <= ju->waitcount){ ! 626: ju->flag &= ~ASLP; ! 627: wakeup((caddr_t)ju); ! 628: } ! 629: breturns++; ! 630: return; ! 631: putout: /* not busy: output a byte */ ! 632: addr->judcw = *(ju->jur)++; ! 633: if (ju->jur == ju->jucbuf + JUSIZ) ! 634: ju->jur = ju->jucbuf; ! 635: ju->jucc--; ! 636: cc++; ! 637: jutotali += jcount; ! 638: jubytes++; ! 639: } ! 640: ! 641: ! 642: out: if(cc && ju->flag&ASLP && ju->jucc <= ju->waitcount) { ! 643: ju->flag &= ~ASLP; ! 644: wakeup ((caddr_t)ju); ! 645: } ! 646: oreturns++; ! 647: } ! 648: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.