|
|
1.1 ! root 1: #include "u.h" ! 2: #include "../port/lib.h" ! 3: #include "mem.h" ! 4: #include "dat.h" ! 5: #include "fns.h" ! 6: #include "io.h" ! 7: #include "ureg.h" ! 8: #include "../port/error.h" ! 9: ! 10: #include "devtab.h" ! 11: ! 12: int duartacr; ! 13: int duartimr; ! 14: void (*kprofp)(ulong); ! 15: ! 16: /* ! 17: * Register set for half the duart. There are really two sets. ! 18: */ ! 19: struct Duart{ ! 20: uchar mr1_2; /* Mode Register Channels 1 & 2 */ ! 21: uchar sr_csr; /* Status Register/Clock Select Register */ ! 22: uchar cmnd; /* Command Register */ ! 23: uchar data; /* RX Holding / TX Holding Register */ ! 24: uchar ipc_acr; /* Input Port Change/Aux. Control Register */ ! 25: #define ivr ivr /* Interrupt Vector Register */ ! 26: uchar is_imr; /* Interrupt Status/Interrupt Mask Register */ ! 27: #define ip_opcr is_imr /* Input Port/Output Port Configuration Register */ ! 28: uchar ctur; /* Counter/Timer Upper Register */ ! 29: #define scc_sopbc ctur /* Start Counter Command/Set Output Port Bits Command */ ! 30: uchar ctlr; /* Counter/Timer Lower Register */ ! 31: #define scc_ropbc ctlr /* Stop Counter Command/Reset Output Port Bits Command */ ! 32: }; ! 33: ! 34: enum{ ! 35: CHAR_ERR =0x00, /* MR1x - Mode Register 1 */ ! 36: PAR_ENB =0x00, ! 37: EVEN_PAR =0x00, ! 38: ODD_PAR =0x04, ! 39: NO_PAR =0x10, ! 40: CBITS8 =0x03, ! 41: CBITS7 =0x02, ! 42: CBITS6 =0x01, ! 43: CBITS5 =0x00, ! 44: NORM_OP =0x00, /* MR2x - Mode Register 2 */ ! 45: TWOSTOPB =0x0F, ! 46: ONESTOPB =0x07, ! 47: ENB_RX =0x01, /* CRx - Command Register */ ! 48: DIS_RX =0x02, ! 49: ENB_TX =0x04, ! 50: DIS_TX =0x08, ! 51: RESET_MR =0x10, ! 52: RESET_RCV =0x20, ! 53: RESET_TRANS =0x30, ! 54: RESET_ERR =0x40, ! 55: RESET_BCH =0x50, ! 56: STRT_BRK =0x60, ! 57: STOP_BRK =0x70, ! 58: RCV_RDY =0x01, /* SRx - Channel Status Register */ ! 59: FIFOFULL =0x02, ! 60: XMT_RDY =0x04, ! 61: XMT_EMT =0x08, ! 62: OVR_ERR =0x10, ! 63: PAR_ERR =0x20, ! 64: FRM_ERR =0x40, ! 65: RCVD_BRK =0x80, ! 66: BD38400 =0xCC|0x0000, ! 67: BD19200 =0xCC|0x0100, ! 68: BD9600 =0xBB|0x0000, ! 69: BD4800 =0x99|0x0000, ! 70: BD2400 =0x88|0x0000, ! 71: BD1200 =0x66|0x0000, ! 72: BD300 =0x44|0x0000, ! 73: IM_IPC =0x80, /* IMRx/ISRx - Interrupt Mask/Interrupt Status */ ! 74: IM_DBB =0x40, ! 75: IM_RRDYB =0x20, ! 76: IM_XRDYB =0x10, ! 77: IM_CRDY =0x08, ! 78: IM_DBA =0x04, ! 79: IM_RRDYA =0x02, ! 80: IM_XRDYA =0x01, ! 81: }; ! 82: ! 83: /* ! 84: * software info for a serial duart interface ! 85: */ ! 86: typedef struct Duartport Duartport; ! 87: struct Duartport ! 88: { ! 89: QLock; ! 90: int printing; /* true if printing */ ! 91: ! 92: /* console interface */ ! 93: int nostream; /* can't use the stream interface */ ! 94: IOQ *iq; /* input character queue */ ! 95: IOQ *oq; /* output character queue */ ! 96: ! 97: /* stream interface */ ! 98: Queue *wq; /* write queue */ ! 99: Rendez r; /* kproc waiting for input */ ! 100: int kstarted; /* kproc started */ ! 101: }; ! 102: Duartport duartport[1]; ! 103: ! 104: uchar keymap[]={ ! 105: /*80*/ 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, ! 106: 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x8e, 0x58, ! 107: /*90*/ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, ! 108: 0x98, 0x99, 0x9a, 0x9b, 0x58, 0x58, 0x58, 0x58, ! 109: /*A0*/ 0x58, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, ! 110: 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0xae, 0xaf, ! 111: /*B0*/ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, ! 112: 0xb8, 0xb9, 0x00, 0xbb, 0x1e, 0xbd, 0x60, 0x1f, ! 113: /*C0*/ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0x58, 0xc6, 0x0a, ! 114: 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, ! 115: /*D0*/ 0x09, 0x08, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, ! 116: 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x7f, 0x58, ! 117: /*E0*/ 0x58, 0x58, 0xe2, 0x1b, 0x0d, 0xe5, 0x58, 0x0a, ! 118: 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, ! 119: /*F0*/ 0x09, 0x08, 0xb2, 0x1b, 0x0d, 0xf5, 0x81, 0x58, ! 120: 0x58, 0x58, 0x58, 0x58, 0x58, 0x58, 0x7f, 0x80, ! 121: }; ! 122: ! 123: void ! 124: duartinit(void) ! 125: { ! 126: Duart *duart; ! 127: static int already; ! 128: ! 129: if(already) ! 130: return; ! 131: already = 1; ! 132: ! 133: duart = DUARTREG; ! 134: ! 135: /* ! 136: * Keyboard ! 137: */ ! 138: duart[0].cmnd = RESET_RCV|DIS_TX|DIS_RX; ! 139: duart[0].cmnd = RESET_TRANS; ! 140: duart[0].cmnd = RESET_ERR; ! 141: duart[0].cmnd = RESET_MR; ! 142: duart[0].mr1_2 = CHAR_ERR|PAR_ENB|EVEN_PAR|CBITS8; ! 143: duart[0].mr1_2 = NORM_OP|ONESTOPB; ! 144: duart[0].sr_csr = BD4800; ! 145: ! 146: /* ! 147: * RS232 ! 148: */ ! 149: duart[1].cmnd = RESET_RCV|DIS_TX|DIS_RX; ! 150: duart[1].cmnd = RESET_TRANS; ! 151: duart[1].cmnd = RESET_ERR; ! 152: duart[1].cmnd = RESET_MR; ! 153: duart[1].mr1_2 = CHAR_ERR|NO_PAR|CBITS8; ! 154: duart[1].mr1_2 = NORM_OP|ONESTOPB; ! 155: duart[1].sr_csr = BD9600; ! 156: ! 157: /* ! 158: * Output port ! 159: */ ! 160: duart[0].ipc_acr = duartacr = 0xB7; /* allow change of state interrupt */ ! 161: duart[1].ip_opcr = 0x00; ! 162: duart[1].scc_ropbc = 0xFF; /* make sure the port is reset first */ ! 163: duart[1].scc_sopbc = 0x04; /* dtr = 1, pp = 01 */ ! 164: duart[0].is_imr = duartimr = IM_IPC|IM_RRDYB|IM_XRDYB|IM_RRDYA|IM_XRDYA; ! 165: duart[0].cmnd = ENB_TX|ENB_RX; /* enable TX and RX last */ ! 166: duart[1].cmnd = ENB_TX|ENB_RX; ! 167: ! 168: /* ! 169: * Initialize keyboard ! 170: */ ! 171: while (!(duart[0].sr_csr & (XMT_EMT|XMT_RDY))) ! 172: ; ! 173: duart[0].data = 0x02; ! 174: } ! 175: ! 176: ! 177: void ! 178: duartbaud(int b) ! 179: { ! 180: int x = 0; ! 181: Duart *duart = DUARTREG; ! 182: ! 183: switch(b){ ! 184: case 38400: ! 185: x = BD38400; ! 186: break; ! 187: case 19200: ! 188: x = BD19200; ! 189: break; ! 190: case 9600: ! 191: x = BD9600; ! 192: break; ! 193: case 4800: ! 194: x = BD4800; ! 195: break; ! 196: case 2400: ! 197: x = BD2400; ! 198: break; ! 199: case 1200: ! 200: x = BD1200; ! 201: break; ! 202: case 300: ! 203: x = BD300; ! 204: break; ! 205: default: ! 206: error(Ebadarg); ! 207: } ! 208: if(x & 0x0100) ! 209: duart[0].ipc_acr = duartacr |= 0x80; ! 210: else ! 211: duart[0].ipc_acr = duartacr &= ~0x80; ! 212: duart[1].sr_csr = x; ! 213: } ! 214: ! 215: void ! 216: duartdtr(int val) ! 217: { ! 218: Duart *duart = DUARTREG; ! 219: if (val) ! 220: duart[1].scc_ropbc=0x01; ! 221: else ! 222: duart[1].scc_sopbc=0x01; ! 223: } ! 224: ! 225: void ! 226: duartbreak(int ms) ! 227: { ! 228: static QLock brk; ! 229: Duart *duart = DUARTREG; ! 230: if (ms<=0 || ms >20000) ! 231: error(Ebadarg); ! 232: qlock(&brk); ! 233: duart[0].is_imr = duartimr &= ~IM_XRDYB; ! 234: duart[1].cmnd = STRT_BRK|ENB_TX; ! 235: tsleep(&u->p->sleep, return0, 0, ms); ! 236: duart[1].cmnd = STOP_BRK|ENB_TX; ! 237: duart[0].is_imr = duartimr |= IM_XRDYB; ! 238: qunlock(&brk); ! 239: } ! 240: ! 241: enum{ ! 242: Kptime=200 ! 243: }; ! 244: void ! 245: duartstarttimer(void) ! 246: { ! 247: Duart *duart; ! 248: char x; ! 249: ! 250: duart = DUARTREG; ! 251: duart[0].ctur = (Kptime)>>8; ! 252: duart[0].ctlr = (Kptime)&255; ! 253: duart[0].is_imr = duartimr |= IM_CRDY; ! 254: x = duart[1].scc_sopbc; ! 255: USED(x); ! 256: } ! 257: ! 258: void ! 259: duartstoptimer(void) ! 260: { ! 261: Duart *duart; ! 262: char x; ! 263: ! 264: duart = DUARTREG; ! 265: x = duart[1].scc_ropbc; ! 266: USED(x); ! 267: duart[0].is_imr = duartimr &= ~IM_CRDY; ! 268: } ! 269: ! 270: ! 271: /* ! 272: * a serial line input interrupt ! 273: */ ! 274: void ! 275: duartrintr(char ch) ! 276: { ! 277: IOQ *cq; ! 278: Duartport *dp = duartport; ! 279: ! 280: cq = dp->iq; ! 281: if(cq->putc) ! 282: (*cq->putc)(cq, ch); ! 283: else { ! 284: putc(cq, ch); ! 285: } ! 286: } ! 287: void ! 288: duartclock(void) ! 289: { ! 290: Duartport *dp = duartport; ! 291: IOQ *cq; ! 292: ! 293: cq = dp->iq; ! 294: if(cangetc(cq)) ! 295: wakeup(&cq->r); ! 296: } ! 297: ! 298: /* ! 299: * a serial line output interrupt ! 300: */ ! 301: void ! 302: duartxintr(void) ! 303: { ! 304: int ch; ! 305: IOQ *cq; ! 306: Duartport *dp = duartport; ! 307: Duart *duart; ! 308: ! 309: cq = dp->oq; ! 310: lock(cq); ! 311: ch = getc(cq); ! 312: duart = DUARTREG; ! 313: if(ch < 0){ ! 314: dp->printing = 0; ! 315: wakeup(&cq->r); ! 316: duart[1].cmnd = DIS_TX; ! 317: } else ! 318: duart[1].data = ch; ! 319: unlock(cq); ! 320: } ! 321: ! 322: ! 323: void ! 324: duartintr(Ureg *ur) ! 325: { ! 326: int cause, status, ch, c, i; ! 327: Duart *duart; ! 328: static int collecting, nk; ! 329: static uchar kc[5]; ! 330: ! 331: duart = DUARTREG; ! 332: cause = duart->is_imr; ! 333: /* ! 334: * I can guess your interrupt. ! 335: */ ! 336: /* ! 337: * Is it 0? ! 338: */ ! 339: if(cause & IM_CRDY){ ! 340: if(kprofp) ! 341: (*kprofp)(ur->pc); ! 342: ch = duart[1].scc_ropbc; ! 343: USED(ch); ! 344: duart[0].ctur = (Kptime)>>8; ! 345: duart[0].ctlr = (Kptime)&255; ! 346: ch = duart[1].scc_sopbc; ! 347: USED(ch); ! 348: return; ! 349: } ! 350: /* ! 351: * Is it 1? ! 352: */ ! 353: if(cause & IM_RRDYA){ /* keyboard input */ ! 354: status = duart->sr_csr; ! 355: ch = duart->data; ! 356: if(status & (FRM_ERR|OVR_ERR|PAR_ERR)) ! 357: duart->cmnd = RESET_ERR; ! 358: if(status & PAR_ERR) /* control word: caps lock (0x4) or repeat (0x10) */ ! 359: kbdrepeat((ch&0x10) == 0); ! 360: else{ ! 361: if(ch == 0x7F) /* VIEW key (bizarre) */ ! 362: ch = 0xFF; ! 363: if(ch == 0xB6) /* NUM PAD */ ! 364: collecting = 1; ! 365: else{ ! 366: if(ch & 0x80) ! 367: ch = keymap[ch&0x7F]; ! 368: if(!collecting) ! 369: kbdputc(&kbdq, ch); ! 370: else{ ! 371: kc[nk++] = ch; ! 372: c = latin1(kc, nk); ! 373: if(c >= -1){ /* otherwise need more keystrokes */ ! 374: if(c != -1) /* valid sequence */ ! 375: kbdputc(&kbdq, c); ! 376: else /* dump characters */ ! 377: for(i=0; i<nk; i++) ! 378: kbdputc(&kbdq, kc[i]); ! 379: nk = 0; ! 380: collecting = 0; ! 381: } ! 382: } ! 383: } ! 384: } ! 385: } ! 386: /* ! 387: * Is it 2? ! 388: */ ! 389: while(cause & IM_RRDYB){ /* duart input */ ! 390: status = duart[1].sr_csr; ! 391: ch = duart[1].data; ! 392: if(status & (FRM_ERR|OVR_ERR|PAR_ERR)) ! 393: duart[1].cmnd = RESET_ERR; ! 394: else ! 395: duartrintr(ch); ! 396: cause = duart->is_imr; ! 397: } ! 398: /* ! 399: * Is it 3? ! 400: */ ! 401: if(cause & IM_XRDYB) /* duart output */ ! 402: duartxintr(); ! 403: /* ! 404: * Is it 4? ! 405: */ ! 406: if(cause & IM_XRDYA) ! 407: duart[0].cmnd = DIS_TX; ! 408: /* ! 409: * Is it 5? ! 410: */ ! 411: if(cause & IM_IPC) ! 412: mousetrack((~duart[0].ipc_acr) & 7, 0, 0); ! 413: } ! 414: ! 415: ! 416: /* ! 417: * Queue n characters for output; if queue is full, we lose characters. ! 418: * Get the output going if it isn't already. ! 419: */ ! 420: void ! 421: duartputs(IOQ *cq, char *s, int n) ! 422: { ! 423: int ch, x; ! 424: Duartport *dp = duartport; ! 425: Duart *duart; ! 426: ! 427: x = splduart(); ! 428: lock(cq); ! 429: puts(cq, s, n); ! 430: if(dp->printing == 0){ ! 431: ch = getc(cq); ! 432: if(ch >= 0){ ! 433: dp->printing = 1; ! 434: duart = DUARTREG; ! 435: duart[1].cmnd = ENB_TX; ! 436: while(!(duart[1].sr_csr & (XMT_RDY|XMT_EMT))) ! 437: ; ! 438: duart[1].data = ch; ! 439: } ! 440: } ! 441: unlock(cq); ! 442: splx(x); ! 443: } ! 444: ! 445: void ! 446: duartenable(Duartport *dp) ! 447: { ! 448: /* ! 449: * set up i/o routines ! 450: */ ! 451: if(dp->oq){ ! 452: dp->oq->puts = duartputs; ! 453: dp->oq->ptr = dp; ! 454: } ! 455: if(dp->iq) ! 456: dp->iq->ptr = dp; ! 457: } ! 458: ! 459: /* ! 460: * set up an duart port as something other than a stream ! 461: */ ! 462: void ! 463: duartspecial(int port, IOQ *oq, IOQ *iq, int baud) ! 464: { ! 465: Duartport *dp = &duartport[port]; ! 466: ! 467: dp->nostream = 1; ! 468: dp->oq = oq; ! 469: dp->iq = iq; ! 470: duartenable(dp); ! 471: duartbaud(baud); ! 472: } ! 473: ! 474: static int duartputc(IOQ *, int); ! 475: static void duartstopen(Queue*, Stream*); ! 476: static void duartstclose(Queue*); ! 477: static void duartoput(Queue*, Block*); ! 478: static void duartkproc(void *); ! 479: Qinfo duartinfo = ! 480: { ! 481: nullput, ! 482: duartoput, ! 483: duartstopen, ! 484: duartstclose, ! 485: "duart" ! 486: }; ! 487: ! 488: static void ! 489: duartstopen(Queue *q, Stream *s) ! 490: { ! 491: Duartport *dp; ! 492: char name[NAMELEN]; ! 493: ! 494: if(s->id > 0) ! 495: panic("duartstopen"); ! 496: dp = &duartport[s->id]; ! 497: ! 498: qlock(dp); ! 499: dp->wq = WR(q); ! 500: WR(q)->ptr = dp; ! 501: RD(q)->ptr = dp; ! 502: qunlock(dp); ! 503: ! 504: if(dp->kstarted == 0){ ! 505: dp->kstarted = 1; ! 506: sprint(name, "duart%d", s->id); ! 507: kproc(name, duartkproc, dp); ! 508: } ! 509: } ! 510: ! 511: static void ! 512: duartstclose(Queue *q) ! 513: { ! 514: Duartport *dp = q->ptr; ! 515: ! 516: qlock(dp); ! 517: dp->wq = 0; ! 518: dp->iq->putc = 0; ! 519: WR(q)->ptr = 0; ! 520: RD(q)->ptr = 0; ! 521: qunlock(dp); ! 522: } ! 523: ! 524: static void ! 525: duartoput(Queue *q, Block *bp) ! 526: { ! 527: Duartport *dp = q->ptr; ! 528: IOQ *cq; ! 529: int n, m; ! 530: ! 531: if(dp == 0){ ! 532: freeb(bp); ! 533: return; ! 534: } ! 535: cq = dp->oq; ! 536: if(waserror()){ ! 537: freeb(bp); ! 538: nexterror(); ! 539: } ! 540: if(bp->type == M_CTL){ ! 541: while (cangetc(cq)) /* let output drain */ ! 542: sleep(&cq->r, cangetc, cq); ! 543: n = strtoul((char *)(bp->rptr+1), 0, 0); ! 544: switch(*bp->rptr){ ! 545: case 'B': ! 546: case 'b': ! 547: duartbaud(n); ! 548: break; ! 549: case 'D': ! 550: case 'd': ! 551: duartdtr(n); ! 552: break; ! 553: case 'K': ! 554: case 'k': ! 555: duartbreak(n); ! 556: break; ! 557: case 'R': ! 558: case 'r': ! 559: /* can't control? */ ! 560: break; ! 561: case 'W': ! 562: case 'w': ! 563: /* obsolete */ ! 564: break; ! 565: } ! 566: }else while((m = BLEN(bp)) > 0){ ! 567: while ((n = canputc(cq)) == 0){ ! 568: kprint(" duartoput: sleeping\n"); ! 569: sleep(&cq->r, canputc, cq); ! 570: } ! 571: if(n > m) ! 572: n = m; ! 573: (*cq->puts)(cq, bp->rptr, n); ! 574: bp->rptr += n; ! 575: } ! 576: poperror(); ! 577: freeb(bp); ! 578: } ! 579: ! 580: /* ! 581: * process to send bytes upstream for a port ! 582: */ ! 583: static void ! 584: duartkproc(void *a) ! 585: { ! 586: Duartport *dp = a; ! 587: IOQ *cq = dp->iq; ! 588: Block *bp; ! 589: int n; ! 590: ! 591: loop: ! 592: while ((n = cangetc(cq)) == 0) ! 593: sleep(&cq->r, cangetc, cq); ! 594: qlock(dp); ! 595: if(dp->wq == 0){ ! 596: cq->out = cq->in; ! 597: }else{ ! 598: bp = allocb(n); ! 599: bp->flags |= S_DELIM; ! 600: bp->wptr += gets(cq, bp->wptr, n); ! 601: PUTNEXT(RD(dp->wq), bp); ! 602: } ! 603: qunlock(dp); ! 604: goto loop; ! 605: } ! 606: ! 607: enum{ ! 608: Qdir= 0, ! 609: Qeia0= STREAMQID(0, Sdataqid), ! 610: Qeia0ctl= STREAMQID(0, Sctlqid), ! 611: }; ! 612: ! 613: Dirtab duartdir[]={ ! 614: "eia0", {Qeia0}, 0, 0666, ! 615: "eia0ctl", {Qeia0ctl}, 0, 0666, ! 616: }; ! 617: ! 618: #define NDuartport (sizeof duartdir/sizeof(Dirtab)) ! 619: ! 620: /* ! 621: * allocate the queues if no one else has ! 622: */ ! 623: void ! 624: duartreset(void) ! 625: { ! 626: Duartport *dp = duartport; ! 627: ! 628: if(dp->nostream) ! 629: return; ! 630: dp->iq = xalloc(sizeof(IOQ)); ! 631: initq(dp->iq); ! 632: dp->oq = xalloc(sizeof(IOQ)); ! 633: initq(dp->oq); ! 634: duartenable(dp); ! 635: } ! 636: ! 637: Chan* ! 638: duartattach(char *spec) ! 639: { ! 640: return devattach('t', spec); ! 641: } ! 642: ! 643: Chan* ! 644: duartclone(Chan *c, Chan *nc) ! 645: { ! 646: return devclone(c, nc); ! 647: } ! 648: ! 649: int ! 650: duartwalk(Chan *c, char *name) ! 651: { ! 652: return devwalk(c, name, duartdir, NDuartport, devgen); ! 653: } ! 654: ! 655: void ! 656: duartstat(Chan *c, char *dp) ! 657: { ! 658: switch(c->qid.path){ ! 659: case Qeia0: ! 660: streamstat(c, dp, duartdir[0].name, duartdir[0].perm); ! 661: break; ! 662: default: ! 663: devstat(c, dp, duartdir, NDuartport, devgen); ! 664: break; ! 665: } ! 666: } ! 667: ! 668: Chan* ! 669: duartopen(Chan *c, int omode) ! 670: { ! 671: Duartport *dp; ! 672: ! 673: switch(c->qid.path){ ! 674: case Qeia0: ! 675: case Qeia0ctl: ! 676: dp = &duartport[0]; ! 677: break; ! 678: default: ! 679: dp = 0; ! 680: break; ! 681: } ! 682: ! 683: if(dp && dp->nostream) ! 684: error(Einuse); ! 685: ! 686: if((c->qid.path & CHDIR) == 0) ! 687: streamopen(c, &duartinfo); ! 688: return devopen(c, omode, duartdir, NDuartport, devgen); ! 689: } ! 690: ! 691: void ! 692: duartcreate(Chan *c, char *name, int omode, ulong perm) ! 693: { ! 694: USED(c, name, omode, perm); ! 695: error(Eperm); ! 696: } ! 697: ! 698: void ! 699: duartclose(Chan *c) ! 700: { ! 701: if(c->stream) ! 702: streamclose(c); ! 703: } ! 704: ! 705: long ! 706: duartread(Chan *c, void *buf, long n, ulong offset) ! 707: { ! 708: int s; ! 709: Duart *duart = DUARTREG; ! 710: ! 711: switch(c->qid.path&~CHDIR){ ! 712: case Qdir: ! 713: return devdirread(c, buf, n, duartdir, NDuartport, devgen); ! 714: case Qeia0ctl: ! 715: if(offset) ! 716: return 0; ! 717: s = splhi(); ! 718: *(uchar *)buf = duart[1].ip_opcr; ! 719: splx(s); ! 720: return 1; ! 721: } ! 722: return streamread(c, buf, n); ! 723: } ! 724: ! 725: long ! 726: duartwrite(Chan *c, void *va, long n, ulong offset) ! 727: { ! 728: USED(offset); ! 729: return streamwrite(c, va, n, 0); ! 730: } ! 731: ! 732: void ! 733: duartremove(Chan *c) ! 734: { ! 735: USED(c); ! 736: error(Eperm); ! 737: } ! 738: ! 739: void ! 740: duartwstat(Chan *c, char *dp) ! 741: { ! 742: USED(c, dp); ! 743: error(Eperm); ! 744: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.