home *** CD-ROM | disk | FTP | other *** search
- /*
- * DU-11 Synchronous interface driver
- */
-
- #include "../h/param.h"
- #include "../h/systm.h"
- #include "../h/dir.h"
- #include "../h/user.h"
- #include "../h/buf.h"
-
- /* device registers */
- struct dureg {
- int rxcsr, rxdbuf;
- #define parcsr rxdbuf
- int txcsr, txdbuf;
- };
-
- struct du {
- struct dureg *du_addr;
- int du_state;
- struct proc *du_proc;
- struct buf *du_buf;
- caddr_t du_bufb;
- caddr_t du_bufp;
- int du_nxmit;
- int du_timer;
- } du[] = {
- { (struct dureg *) 0160110 },
- };
-
- #define NDU (sizeof(du)/sizeof(du[0]))
-
- #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 (PZERO+1)
-
- duopen(dev)
- register dev;
- {
- int dutimeout();
- register struct du *dp;
- register struct dureg *lp;
-
- dev = minor(dev);
- if (dev >= NDU ||
- ((dp = &du[dev])->du_proc!=NULL && dp->du_proc!=u.u_procp)) {
- u.u_error = ENXIO;
- return;
- }
- dp->du_proc = u.u_procp;
- lp = dp->du_addr;
- if (dp->du_buf==NULL) {
- dp->du_buf = geteblk();
- dp->du_bufb = dp->du_buf->b_un.b_addr;
- dp->du_state = WRITE;
- lp->txcsr = MR;
- lp->parcsr = 035026; /* Sync Int, 7 bits, even parity, sync=026 */
- timeout(dutimeout, (caddr_t)dp, HZ);
- duturn(dp);
- }
- }
-
- duclose(dev)
- {
- register struct du *dp;
- register struct dureg *lp;
-
- dp = &du[minor(dev)];
- lp = dp->du_addr;
- lp->rxcsr = 0;
- lp->txcsr = 0;
- dp->du_timer = 0;
- dp->du_proc = 0;
- if (dp->du_buf != NULL) {
- brelse(dp->du_buf);
- dp->du_buf = NULL;
- }
- }
-
- duread(dev)
- {
- register char *bp;
- register struct du *dp;
-
- dp = &du[minor(dev)];
- bp = dp->du_bufb;
- for(;;) {
- if(duwait(dev))
- return;
- if (dp->du_bufp > bp)
- break;
- spl6();
- if (dp->du_timer <= 1) {
- spl0();
- return;
- }
- sleep((caddr_t)dp, DUPRI);
- spl0();
- }
- u.u_offset = 0;
- iomove(dp->du_bufb, (int)min(u.u_count, (unsigned)(dp->du_bufp-bp)), B_READ);
- }
-
- duwrite(dev)
- {
- register struct du *dp;
- register struct dureg *lp;
-
- dev = minor(dev);
- dp = &du[dev];
- if (u.u_count==0 || duwait(dev))
- return;
- dp->du_bufp = dp->du_bufb;
- dp->du_state = PWRIT;
- dp->du_addr->rxcsr &= ~SCH;
- dp->du_addr->rxcsr = SIE|RTS|DTR;
- if (u.u_count > BSIZE)
- u.u_count = BSIZE;
- dp->du_nxmit = u.u_count;
- u.u_offset = 0;
- iomove(dp->du_bufb, (int)u.u_count, B_WRITE);
- lp = dp->du_addr;
- dp->du_timer = 10;
- spl6();
- while((lp->rxcsr&CTS)==0)
- sleep((caddr_t)dp, DUPRI);
- if (dp->du_state != WRITE) {
- dp->du_state = WRITE;
- lp->txcsr = IE|SIE|SEND|HALF;
- dustart(dev);
- }
- spl0();
- }
-
- duwait(dev)
- {
- register struct du *dp;
- register struct dureg *lp;
-
- dp = &du[minor(dev)];
- lp = dp->du_addr;
- for(;;) {
- if ((lp->rxcsr&DSR)==0 || dp->du_buf==0) {
- u.u_error = EIO;
- return(1);
- }
- spl6();
- if (dp->du_state==READ &&
- ((lp->rxcsr&RCVACT)==0)) {
- spl0();
- return(0);
- }
- sleep((caddr_t)dp, DUPRI);
- spl0();
- }
- }
-
- dustart(dev)
- {
- register struct du *dp;
- register struct dureg *lp;
-
- dp = &du[minor(dev)];
- lp = dp->du_addr;
- dp->du_timer = 10;
- if (dp->du_nxmit > 0) {
- dp->du_nxmit--;
- lp->txdbuf = *dp->du_bufp++;
- } else {
- duturn(dp);
- }
- }
-
- durint(dev)
- {
- register struct du *dp;
- register c, s;
- int dustat;
-
- dp = &du[minor(dev)];
- dustat = dp->du_addr->rxcsr;
- if(dustat<0) {
- if((dustat&CARRIER)==0 && dp->du_state==READ)
- duturn(dp);
- else
- wakeup((caddr_t)dp);
- } else
- if(dustat&DONE) {
- dp->du_addr->rxcsr = IE|SIE|SCH|DTR;
- c = s = dp->du_addr->rxdbuf;
- c &= 0177;
- if(s<0)
- c |= 0200;
- if (dp->du_bufp < dp->du_bufb+BSIZE)
- *dp->du_bufp++ = c;
- }
- }
-
- duxint(dev)
- {
- register struct du *dp;
- register struct dureg *lp;
- register int dustat;
-
- dp = &du[minor(dev)];
- lp = dp->du_addr;
- dustat = lp->txcsr;
- if(dustat<0)
- duturn(dp);
- else if(dustat&DONE)
- dustart(dev);
- }
-
- duturn(dp)
- register struct du *dp;
- {
- register struct dureg *lp;
-
- lp = dp->du_addr;
- if (dp->du_state!=READ) {
- dp->du_state = READ;
- dp->du_timer = 10;
- dp->du_bufp = dp->du_bufb;
- }
- lp->txcsr = HALF;
- lp->rxcsr &= ~SCH;
- lp->rxcsr = STRIP|IE|SIE|SCH|DTR;
- wakeup((caddr_t)dp);
- }
-
- dutimeout(dp)
- register struct du *dp;
- {
- if (dp->du_timer == 0)
- return;
- if (--dp->du_timer == 0) {
- duturn(dp);
- dp->du_timer = 1;
- }
- timeout(dutimeout, (caddr_t)dp, HZ);
- }
-