Research V7 development
[unix-history] / .ref-Research-V6 / usr / sys / dmr / dp.c
CommitLineData
9893f627
DR
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 */
21struct {
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 */
31struct {
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 */
68dpopen(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
89dpclose()
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 */
108dpread()
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 */
135dpwrite()
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 */
156dpwait()
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 */
177dpstart()
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 */
197dptimeout()
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 */
212dprint()
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 */
231dpxint()
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 */
246dpturnaround()
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}