home *** CD-ROM | disk | FTP | other *** search
/ minnie.tuhs.org / unixen.tar / unixen / PDP-11 / Trees / V6 / usr / sys / dmr / dp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1975-07-17  |  4.6 KB  |  256 lines

  1. #
  2. /*
  3.  */
  4.  
  5. /*
  6.  * DP-11 Synchronous interface driver
  7.  * This driver is rather insensitive to the remote
  8.  * device it talks to, which is to say most of the protocol
  9.  * must be supplied by the calling program.
  10.  * Exceptions: parity is even; 7 data bits per character;
  11.  * max. of 512 characters per record; 10 second timeout
  12.  * on waiting to receive; half-duplex transmission.
  13.  */
  14.  
  15. #include "../param.h"
  16. #include "../conf.h"
  17. #include "../user.h"
  18. #include "../buf.h"
  19.  
  20. /* control info */
  21. struct {
  22.     char    *dp_buf;
  23.     char    *dp_bufp;
  24.     int    dp_nxmit;
  25.     char    dp_state;
  26.     char    dp_timer;
  27.     int    dp_proc;
  28. } dp11;
  29.  
  30. /* device registers */
  31. struct {
  32.     int    dprcsr;
  33.     char    dprbuf;
  34.     char    dpsyn0;
  35.     int    dptcsr;
  36.     char    dptbuf;
  37.     char    dpsyn1;
  38. };
  39.  
  40. /* bits */
  41. #define    ODDPAR    010000
  42. #define    IENABLE    0100
  43. #define    HDUPLX    02
  44.  
  45. #define    CTRANS    0100000
  46. #define    RORUN    040000
  47. #define    RING    020000
  48. #define    DSRDY    010000
  49. #define    CARRIER    04000
  50. #define    DONE    0200
  51. #define    IENABLE    0100
  52. #define    SIENABL    040
  53.  
  54. #define    WRITE    1
  55. #define    READ    0
  56.  
  57. #define    DTRDY    01
  58. #define    RCVACT    04000
  59.  
  60. #define    DPADDR    0174770
  61. #define    DPPRI    5
  62. #define    SYN    026        /* (receive) sync character */
  63.  
  64. /*
  65.  * The open fails unless the device is not open or
  66.  * the opening process is the one that has it open already.
  67.  */
  68. dpopen(dev, flag)
  69. {
  70.     int dptimeout();
  71.  
  72.     if (dp11.dp_proc!=0 && dp11.dp_proc!=u.u_procp) {
  73.         u.u_error = ENXIO;
  74.         return;
  75.     }
  76.     dp11.dp_proc = u.u_procp;
  77.     dp11.dp_state = READ;
  78.     if (dp11.dp_buf==0) {
  79.         dp11.dp_buf = getblk(NODEV);
  80.         dp11.dp_bufp = dp11.dp_buf->b_addr;
  81.         dp11.dp_timer = HZ;
  82.         timeout(dptimeout, 0, HZ);
  83.     }
  84.     DPADDR->dpsyn0 = SYN;
  85.     DPADDR->dprcsr = HDUPLX|IENABLE;
  86.     DPADDR->dptcsr = IENABLE|SIENABL|DTRDY;
  87. }
  88.  
  89. dpclose()
  90. {
  91.     DPADDR->dprcsr = 0;
  92.     DPADDR->dptcsr = 0;
  93.     dp11.dp_timer = 0;
  94.     dp11.dp_proc = 0;
  95.     if (dp11.dp_buf != 0) {
  96.         brelse(dp11.dp_buf);
  97.         dp11.dp_buf = 0;
  98.     }
  99. }
  100.  
  101. /*
  102.  * Read waits until:
  103.  *  there is loss of "data set ready", or
  104.  *  a timeout occurs, or
  105.  *  a full record has been received.
  106.  * The former two result in an error.
  107.  */
  108. dpread()
  109. {
  110.     register char *bp, **epp;
  111.  
  112.     bp = dp11.dp_buf->b_addr;
  113.     epp = &dp11.dp_bufp;
  114.     for(;;) {
  115.         if(dpwait())
  116.             return;
  117.         if (*epp > bp)
  118.             break;
  119.         spl6();
  120.         if (dp11.dp_timer <= 1) {
  121.             spl0();
  122.             return;
  123.         }
  124.         sleep(&dp11, DPPRI);
  125.         spl0();
  126.     }
  127.     iomove(dp11.dp_buf, 0, min(u.u_count, *epp-bp), B_READ);
  128. }
  129.  
  130. /*
  131.  * write checks to make sure that the data set is not reading,
  132.  * and that it is ready.  Then the record is copied
  133.  * and transmission started.
  134.  */
  135. dpwrite()
  136. {
  137.     register char *bp;
  138.  
  139.     if (u.u_count==0 || dpwait())
  140.         return;
  141.     dp11.dp_state = WRITE;
  142.     bp = dp11.dp_buf->b_addr;
  143.     dp11.dp_bufp = bp;
  144.     if (u.u_count>512)
  145.         u.u_count = 512;
  146.     dp11.dp_nxmit = u.u_count;
  147.     iomove(dp11.dp_buf, 0, u.u_count, B_WRITE);
  148.     dpstart();
  149. }
  150.  
  151. /*
  152.  * If "data set ready" is down return an error; otherwise
  153.  * wait until the dataset is in read state with no carrier,
  154.  * which means a record has just been received.
  155.  */
  156. dpwait()
  157. {
  158.     for(;;) {
  159.         if ((DPADDR->dptcsr&DSRDY)==0 || dp11.dp_buf==0) {
  160.             u.u_error = EIO;
  161.             return(1);
  162.         }
  163.         spl6();
  164.         if (dp11.dp_state==READ && (DPADDR->dptcsr&CARRIER)==0) {
  165.             spl0();
  166.             return(0);
  167.         }
  168.         sleep(&dp11, DPPRI);
  169.         spl0();
  170.     }
  171. }
  172.  
  173. /*
  174.  * Start off the next character to be transmitted;
  175.  * when the record is done, drop back into read state.
  176.  */
  177. dpstart()
  178. {
  179.     register int c;
  180.     extern char partab[];
  181.  
  182.     dp11.dp_timer = 10;
  183.     if (--dp11.dp_nxmit >= 0) {
  184.         c = (*dp11.dp_bufp++) & 0177;
  185.         DPADDR->dptbuf = c | ~partab[c]&0200;
  186.     } else {
  187.         dp11.dp_bufp = dp11.dp_buf->b_addr;
  188.         dp11.dp_state = READ;
  189.     }
  190. }
  191.  
  192. /*
  193.  * Count down the DP timer (once per second)
  194.  * If it runs out, it presumably means the other station
  195.  * won't speak.
  196.  */
  197. dptimeout()
  198. {
  199.     if (dp11.dp_timer==0)
  200.         return;
  201.     if (--dp11.dp_timer==0) {
  202.         dpturnaround();
  203.         dp11.dp_timer = 1;
  204.     }
  205.     timeout(dptimeout, 0, HZ);
  206. }
  207.  
  208. /*
  209.  * Receiver interrupt: if reading, stash character
  210.  * unless there is an overrun.
  211.  */
  212. dprint()
  213. {
  214.     register int c;
  215.  
  216.     c = DPADDR->dprbuf & 0177;
  217.     if (dp11.dp_state==READ) {
  218.         if ((DPADDR->dprcsr&ODDPAR) == 0)
  219.             c =| 0200;
  220.         if (dp11.dp_bufp < dp11.dp_buf->b_addr+512)
  221.             *dp11.dp_bufp++ = c;
  222.     }
  223. }
  224.  
  225. /*
  226.  * Transmitter interrupt:
  227.  * Knock down hardware bits.
  228.  * If carrier has dropped, the record is done, so turn the line around;
  229.  * otherwise start another character.
  230.  */
  231. dpxint()
  232. {
  233.     register int dpstat;
  234.  
  235.     dpstat = DPADDR->dptcsr;
  236.     DPADDR->dptcsr =& ~(CTRANS|RORUN|RING|DONE);
  237.     if (dpstat & (CTRANS|RORUN))
  238.         dpturnaround();
  239.     else if (dpstat&DONE && dp11.dp_state==WRITE)
  240.         dpstart();
  241. }
  242.  
  243. /*
  244.  * Change the state from writing to reading at the end of a record.
  245.  */
  246. dpturnaround()
  247. {
  248.     DPADDR->dprcsr =& ~RCVACT;
  249.     if (dp11.dp_state==WRITE) {
  250.         dp11.dp_timer = 10;
  251.         dp11.dp_state = READ;
  252.         dp11.dp_bufp = dp11.dp_buf->b_addr;
  253.     }
  254.     wakeup(&dp11);
  255. }
  256.