# /* * DU-11 Synchronous interface driver */ #include "../hd/param.h" #include "../hd/user.h" #include "../hd/buf.h" #include "../hd/peri.h" /* device registers */ struct { int rxcsr, rxdbuf; int txcsr, txdbuf; }; extern du_addr[], du_cnt; #define DONE 0200 #define IE 0100 #define SIE 040 #define CTS 020000 #define CARRIER 010000 #define RCVACT 04000 #define DSR 01000 #define STRIP 0400 #define SCH 020 #define RTS 04 #define DTR 02 #define MR 0400 #define SEND 020 #define HALF 010 #define READ 0 #define WRITE 1 #define PWRIT 2 #define DUPRI 5 duopen(dev) { register struct du *dp; register *lp; if (dev >= du_cnt || ((dp = &du_du[dev])->du_proc!=0 && dp->du_proc!=u.u_procp)) { u.u_error = ENXIO; return; } dp->du_proc = u.u_procp; lp = du_addr[dev]; lp->txcsr = MR; lp->rxdbuf = 035026; if (dp->du_buf==0) { dp->du_buf = getblk(NODEV); dp->du_bufb = dp->du_buf->b_addr; dp->du_bufe = dp->du_bufb+512; dp->du_state = WRITE; duturn(dev); } } duclose(dev) { register struct du *dp; register *lp; dp = &du_du[dev]; lp = du_addr[dev]; lp->rxcsr = 0; lp->txcsr = 0; dp->du_proc = 0; if (dp->du_buf != 0) { brelse(dp->du_buf); dp->du_buf = 0; } } duread(dev) { register char *bp; register struct du *dp; register n; int flag; dp = &du_du[dev]; bp = dp->du_bufb; flag = 0; for(;;) { if(duwait(dev)) return; spl5(); if (n = dp->du_nleft) { dp->du_nleft = 0; spl0(); flag++; while (n--) { if (passc(*bp++)<0) break; if (bp == dp->du_bufe) bp = dp->du_bufb; } } else { if ( flag) { spl0(); break; } sleep(dp, DUPRI); spl0(); } } dp->du_bufp = dp->du_bufb; } duwrite(dev) { register struct du *dp; register char *bp,*ep; int n, *lp; dp = &du_du[dev]; lp = du_addr[dev]; if (u.u_count==0 ||duwait(dev)) return; dp->du_bufp = ep = bp = dp->du_bufb; dp->du_state = PWRIT; lp->rxcsr =& ~SCH; lp->rxcsr = SIE|RTS|DTR; n = 0; while (u.u_count!=0) { *bp++ = cpass(); n++; if (bp==dp->du_bufe) bp = dp->du_bufb; if (bp==ep) { duset(dev, n); if (u.u_count!=0) { spl5(); sleep(dp,DUPRI); spl0(); } else return; ep = dp->du_bufp; n = 0; } } duset(dev, n); } duwait(dev) { register struct du *dp; register *lp; dp = &du_du[dev]; lp = du_addr[dev]; for(;;) { if ((lp->rxcsr&DSR)==0 || dp->du_buf==0) { u.u_error = EIO; return(1); } spl5(); if (dp->du_state==READ && ((lp->rxcsr&RCVACT)==0 || dp->du_nleft)) { spl0(); return(0); } sleep(dp, DUPRI); spl0(); } } dustart(dev) { register struct du *dp; register *lp dp = &du_du[dev]; lp = du_addr[dev]; if (dp->du_nleft > 0) { if (--dp->du_nleft==200) wakeup(dp); lp->txdbuf = *dp->du_bufp++; if (dp->du_bufp==dp->du_bufe) dp->du_bufp = dp->du_bufb; } else { duturn(dev); } } duset(dev, an) { register struct du *dp; register *lp; dp = &du_du[dev]; lp = du_addr[dev]; spl5(); while((lp->rxcsr&CTS)==0) sleep(dp,DUPRI); dp->du_nleft =+ an; if (dp->du_state != WRITE) { dp->du_state = WRITE; lp->txcsr = IE|SIE|SEND|HALF; dustart(dev); } spl0(); } durint(dev) { register struct du *dp; register c, s; int dustat, *lp; dp = &du_du[dev]; lp = du_addr[dev]; dustat = lp->rxcsr; if(dustat<0) { if((dustat&CARRIER)==0 && dp->du_state==READ) duturn(dev); else wakeup(dp); } else if(dustat&DONE) { lp->rxcsr = IE|SIE|SCH|DTR; c = s = lp->rxdbuf; c =& 0177; if(s<0) c =| 0200; if (++dp->du_nleft==384) wakeup(dp); if (dp->du_bufp == dp->du_bufe) dp->du_bufp = dp->du_bufb; *dp->du_bufp++ = c; if (c == 0377) duturn(dev); } } duxint(dev) { register struct du *dp; register *lp; register int dustat; dp = &du_du[dev]; lp = du_addr[dev]; dustat = lp->txcsr; if(dustat<0) duturn(dev); else if(dustat&DONE) dustart(dev); } duturn(dev) { register struct du *dp; register *lp; dp = &du_du[dev]; lp = du_addr[dev]; if (dp->du_state!=READ) { dp->du_state = READ; dp->du_bufp = dp->du_bufb; dp->du_nleft = 0; } lp->txcsr = HALF; lp->rxcsr =& ~SCH; lp->rxcsr = STRIP|IE|SIE|SCH|DTR; wakeup(dp); }