# /* * Copyright 1973 Bell Telephone Laboratories Inc */ /* * DP-11 Synchronous interface driver */ #include "../param.h" #include "../conf.h" #include "../user.h" #include "../buf.h" /* control info */ struct { char *dp_buf; char *dp_bufp; int dp_nxmit; char dp_state; char dp_timer; int dp_proc; } dp11; /* device registers */ struct { int dprcsr; char dprbuf; char dpsyn0; int dptcsr; char dptbuf; char dpsyn1; }; /* bits */ #define ODDPAR 010000 #define IENABLE 0100 #define HDUPLX 02 #define CTRANS 0100000 #define RORUN 040000 #define RING 020000 #define DSRDY 010000 #define CARRIER 04000 #define DONE 0200 #define IENABLE 0100 #define SIENABL 040 #define WRITE 1 #define READ 0 #define DTRDY 01 #define RCVACT 04000 #define DPADDR 0174770 #define DPPRI 5 dpopen(dev, flag) { int dptimeout(); if (dp11.dp_proc!=0 && dp11.dp_proc!=u.u_procp) { u.u_error = ENXIO; return; } dp11.dp_proc = u.u_procp; dp11.dp_state = READ; if (dp11.dp_buf==0) { dp11.dp_buf = getblk(NODEV); dp11.dp_bufp = dp11.dp_buf->b_addr; dp11.dp_timer = 60; timeout(dptimeout, 0, 60); } DPADDR->dpsyn0 = 026; DPADDR->dprcsr = HDUPLX|IENABLE; DPADDR->dptcsr = IENABLE|SIENABL|DTRDY; } dpclose() { DPADDR->dprcsr = 0; DPADDR->dptcsr = 0; dp11.dp_timer = 0; dp11.dp_proc = 0; if (dp11.dp_buf != 0) { brelse(dp11.dp_buf); dp11.dp_buf = 0; } } dpread() { register char *bp, **epp; bp = dp11.dp_buf->b_addr; epp = &dp11.dp_bufp; for(;;) { if(dpwait()) return; if (*epp > bp) break; spl6(); if (dp11.dp_timer <= 1) { spl0(); return; } sleep(&dp11, DPPRI); spl0(); } iomove(dp11.dp_buf, 0, min(u.u_count, *epp-bp), B_READ); } dpwrite() { register char *bp; if (u.u_count==0 ||dpwait()) return; dp11.dp_state = WRITE; bp = dp11.dp_buf->b_addr; dp11.dp_bufp = bp; if (u.u_count>512) u.u_count = 512; dp11.dp_nxmit = u.u_count; iomove(dp11.dp_buf, 0, u.u_count, B_WRITE); dpstart(); } dpwait() { for(;;) { if ((DPADDR->dptcsr&DSRDY)==0 || dp11.dp_buf==0) { u.u_error = EIO; return(1); } spl6(); if (dp11.dp_state==READ && (DPADDR->dptcsr&CARRIER)==0) { spl0(); return(0); } sleep(&dp11, DPPRI); spl0(); } } dpstart() { register int c; extern char partab[]; dp11.dp_timer = 5; if (--dp11.dp_nxmit >= 0) { c = (*dp11.dp_bufp++) & 0177; DPADDR->dptbuf = c | ~partab[c]&0200; } else { dp11.dp_bufp = dp11.dp_buf->b_addr; dp11.dp_state = READ; } } dptimeout() { if (dp11.dp_timer==0) return; if (--dp11.dp_timer==0) { dpturnaround(); dp11.dp_timer = 1; } timeout(dptimeout, 0, 60); } dprint() { register int c; c = DPADDR->dprbuf & 0177; if (dp11.dp_state==READ) { if ((DPADDR->dprcsr&ODDPAR) == 0) c =| 0200; if (dp11.dp_bufp < dp11.dp_buf->b_addr+512) *dp11.dp_bufp++ = c; } } dpxint() { register int dpstat; dpstat = DPADDR->dptcsr; DPADDR->dptcsr =& ~(CTRANS|RORUN|RING|DONE); if (dpstat & (CTRANS|RORUN)) dpturnaround(); else if (dpstat&DONE && dp11.dp_state==WRITE) dpstart(); } dpturnaround() { DPADDR->dprcsr =& ~RCVACT; if (dp11.dp_state==WRITE) { dp11.dp_timer = 5; dp11.dp_state = READ; dp11.dp_bufp = dp11.dp_buf->b_addr; } wakeup(&dp11); }