home *** CD-ROM | disk | FTP | other *** search
- #
- /*
- */
-
- /*
- * DP-11 Synchronous interface driver
- * This driver is rather insensitive to the remote
- * device it talks to, which is to say most of the protocol
- * must be supplied by the calling program.
- * Exceptions: parity is even; 7 data bits per character;
- * max. of 512 characters per record; 10 second timeout
- * on waiting to receive; half-duplex transmission.
- */
-
- #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
- #define SYN 026 /* (receive) sync character */
-
- /*
- * The open fails unless the device is not open or
- * the opening process is the one that has it open already.
- */
- 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 = HZ;
- timeout(dptimeout, 0, HZ);
- }
- DPADDR->dpsyn0 = SYN;
- 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;
- }
- }
-
- /*
- * Read waits until:
- * there is loss of "data set ready", or
- * a timeout occurs, or
- * a full record has been received.
- * The former two result in an error.
- */
- 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);
- }
-
- /*
- * write checks to make sure that the data set is not reading,
- * and that it is ready. Then the record is copied
- * and transmission started.
- */
- 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();
- }
-
- /*
- * If "data set ready" is down return an error; otherwise
- * wait until the dataset is in read state with no carrier,
- * which means a record has just been received.
- */
- 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();
- }
- }
-
- /*
- * Start off the next character to be transmitted;
- * when the record is done, drop back into read state.
- */
- dpstart()
- {
- register int c;
- extern char partab[];
-
- dp11.dp_timer = 10;
- 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;
- }
- }
-
- /*
- * Count down the DP timer (once per second)
- * If it runs out, it presumably means the other station
- * won't speak.
- */
- dptimeout()
- {
- if (dp11.dp_timer==0)
- return;
- if (--dp11.dp_timer==0) {
- dpturnaround();
- dp11.dp_timer = 1;
- }
- timeout(dptimeout, 0, HZ);
- }
-
- /*
- * Receiver interrupt: if reading, stash character
- * unless there is an overrun.
- */
- 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;
- }
- }
-
- /*
- * Transmitter interrupt:
- * Knock down hardware bits.
- * If carrier has dropped, the record is done, so turn the line around;
- * otherwise start another character.
- */
- 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();
- }
-
- /*
- * Change the state from writing to reading at the end of a record.
- */
- dpturnaround()
- {
- DPADDR->dprcsr =& ~RCVACT;
- if (dp11.dp_state==WRITE) {
- dp11.dp_timer = 10;
- dp11.dp_state = READ;
- dp11.dp_bufp = dp11.dp_buf->b_addr;
- }
- wakeup(&dp11);
- }
-