1: /*
2: * SCCS id @(#)du.c 2.1 (Berkeley) 8/5/83
3: */
4:
5: /*
6: * DU-11 and DUP-11 synchronous line interface driver
7: */
8:
9:
10: #include "du.h"
11: #if NDU > 0
12: #include "param.h"
13: #include <sys/conf.h>
14: #include <sys/buf.h>
15: #include <sys/proc.h>
16: #include <sys/dir.h>
17: #include <sys/user.h>
18: #include <sys/systm.h>
19: #include <sys/dureg.h>
20:
21: extern struct dudevice *DUADDR;
22:
23: /*
24: * receiver interrupt code state definitions
25: */
26: #define RIDLE 0 /* idle, waiting for a message */
27: #define RRUN 1 /* running, message in progress */
28: #define RQUIT1 2 /* quit, trashing all until carrier drop */
29: #define RQUIT2 3 /* same as above, but return error */
30:
31: /*
32: * transmitter interrupt code state definitions
33: */
34: #define TIDLE 0 /* idle, waiting for a message */
35: #define TRUN 1 /* running, message in progress */
36: #define TLAST 2 /* sending last character */
37: #define TCARDRP 3 /* waiting for carrier hold-down delay */
38:
39: /*
40: * miscellaneous defintions
41: */
42: #define SYN 026 /* sync character */
43: #define MSGN 5 /* number of message buffers each direction */
44: #define MSGLEN 102 /* length of each message buffer */
45: #define TIMEOUT 3 /* number of seconds before receive timeout */
46: #define TDELAY 2 /* number ticks to hold down xmit carrier */
47: #define DUPRI 5 /* du11 sleep priority */
48:
49: /*
50: * message buffer descriptor
51: */
52: struct msgbuf {
53: caddr_t msgbufp; /* pointer to message buffer */
54: char msgbc; /* message byte count */
55: char msgerr; /* nonzero if error in message */
56: };
57:
58: /*
59: * du11 control info
60: */
61: struct {
62: struct proc *duproc; /* process adr of caller, 0 if closed */
63: /*
64: * Transmit info
65: */
66: struct buf *dutbufp; /* pointer to transmit buffer */
67: struct msgbuf dutbuff[MSGN]; /* message buffer descriptors */
68: struct msgbuf *dutbufi; /* in pointer */
69: struct msgbuf *dutbufo; /* out pointer */
70: short dutbufn; /* number of message buffers that are full */
71: short dutstate; /* state of transmitter interrupt code */
72: caddr_t dutbufc; /* char ptr for message in progress */
73: short dutbc; /* byte count of message in progress */
74: short dutdna; /* number of times data not available */
75: /*
76: * Receive info
77: */
78: #ifndef UCB_NKB
79: struct buf *durbufp; /* pointer to receive buffer */
80: #endif
81: struct msgbuf durbuff[MSGN]; /* message buffer descriptors */
82: struct msgbuf *durbufi; /* in pointer */
83: struct msgbuf *durbufo; /* out pointer */
84: short durbufn; /* number of message buffers that are full */
85: short durstate; /* state of receiver interrupt code */
86: caddr_t durbufc; /* char ptr for message in progress */
87: short durbc; /* byte count of message in progress */
88: short durtimer; /* seconds left until timeout */
89: short durover; /* number of receiver data overruns */
90: short durfull; /* number of times receive buffer full */
91: short durlong; /* number of messages > 255 bytes */
92: } du11;
93:
94: #define MAINTDEV 1 /* minor device for maintenance mode */
95: int maint; /* nonzero if open for maintenance */
96:
97: /*ARGSUSED*/
98: duopen(dev, flag)
99: dev_t dev;
100: {
101: register struct dudevice *duaddr = DUADDR;
102: register n;
103: extern durtimeout();
104:
105: if (du11.duproc == u.u_procp)
106: return;
107: if (du11.duproc) {
108: u.u_error = ENXIO;
109: return;
110: }
111:
112: /*
113: * Check whether opening for maintenance mode
114: */
115: if (minor(dev) == MAINTDEV)
116: maint = 1;
117: else
118: maint = 0;
119:
120: /*
121: * reset device
122: */
123: duaddr->dutcsr = DUTCSR_MR;
124:
125: /*
126: * Allocate transmit buffer
127: */
128: du11.dutbufp = geteblk();
129: du11.dutbufi = du11.dutbufo = du11.dutbuff;
130: du11.dutbufn = 0;
131: for(n = 0; n < MSGN; n++)
132: du11.dutbuff[n].msgbufp = du11.dutbufp->b_un.b_addr + MSGLEN*n;
133: du11.dutstate = TIDLE;
134:
135: /*
136: * Allocate receive buffer
137: */
138: #ifndef UCB_NKB
139: du11.durbufp = geteblk();
140: for(n = 0; n < MSGN; n++)
141: du11.durbuff[n].msgbufp = du11.durbufp->b_un.b_addr+(MSGLEN*n);
142: #else
143: #if UCB_NKB >= 1
144: for(n = 0; n < MSGN; n++)
145: du11.durbuff[n].msgbufp = (du11.dutbufp->b_un.b_addr+(BSIZE/2))
146: + (MSGLEN * n);
147: #else
148: THIS IS AN ERROR!;
149: #endif
150: #endif
151: du11.durbufi = du11.durbufo = du11.durbuff;
152: du11.durbufn = 0;
153: du11.durstate = RIDLE;
154:
155: /*
156: * Start 1 second receiver timeout clock
157: */
158: du11.durtimer = 0;
159: timeout(durtimeout, 0, hz);
160: du11.duproc = u.u_procp;
161:
162: /*
163: * Set parameters according to whether du11 or dup11
164: */
165: #ifdef DU11
166: duaddr->durdbuf = DUPARCSR_8BITS | DUPARCSR_ISYNC | SYN;
167: #else
168: duaddr->durdbuf = DUPARCSR_DEC | DUPARCSR_CRCINH | SYN;
169: if (maint)
170: duaddr->dutcsr = DUTCSR_MPSYSTST;
171: #endif
172: /*
173: * Start receiver
174: */
175: duaddr->durcsr = DU_STSYNC | DU_DTR | DU_SSYNC;
176: }
177:
178: duclose()
179: {
180: register struct dudevice *duaddr = DUADDR;
181:
182: /*
183: * Stop device and disable interrupts
184: */
185: duaddr->durcsr = 0;
186: duaddr->dutcsr = 0;
187:
188: /*
189: * Stop timer
190: */
191: du11.durtimer = -1;
192: while (du11.durtimer)
193: sleep(&du11.durstate, DUPRI);
194:
195: /*
196: * Stop interrupt code for sure
197: */
198: du11.duproc = 0;
199:
200: /*
201: * Release buffers
202: */
203: #ifdef UCB_BUFOUT
204: #define brelse abrelse
205: #endif
206: brelse(du11.dutbufp);
207: #ifndef UCB_NKB
208: brelse(du11.durbufp);
209: #endif
210:
211: /*
212: * clear maintenance mode flag
213: */
214: maint = 0;
215: }
216:
217: duread()
218: {
219: register nbytes;
220:
221: /*
222: * wait for a message to appear in the receive buffer or for TIMEOUT
223: * seconds to elapse
224: */
225: du11.durtimer = TIMEOUT;
226: (void) _spl6();
227: while (du11.durbufn == 0) {
228: if (du11.durtimer == 0) {
229: (void) _spl0();
230: return;
231: }
232: sleep(&du11.durstate, DUPRI);
233: }
234: (void) _spl0();
235: du11.durtimer = 0;
236:
237: /*
238: * if an error was detected on this message, throw it away and return
239: * an error to the caller
240: */
241: if (du11.durbufo->msgerr) {
242: if (++du11.durbufo == du11.durbuff + MSGN)
243: du11.durbufo = du11.durbuff;
244: du11.durbufn--;
245: u.u_error = EIO;
246: return;
247: }
248:
249: /*
250: * Copy the message to the caller's buffer
251: */
252: nbytes = min(u.u_count, du11.durbufo->msgbc);
253: iomove(du11.durbufo->msgbufp, nbytes, B_READ);
254: if (++du11.durbufo == du11.durbuff + MSGN)
255: du11.durbufo = du11.durbuff;
256: du11.durbufn--;
257: }
258:
259: duwrite()
260: {
261: register nbytes;
262:
263: /*
264: * Wait for there to be room for the message in the buffer
265: */
266: while (du11.dutbufn == MSGN)
267: sleep(&du11.dutstate, DUPRI);
268:
269: /*
270: * Transfer the message from the caller's buffer to ours
271: */
272: nbytes = min(u.u_count, MSGLEN);
273: du11.dutbufi->msgbc = nbytes;
274: iomove(du11.dutbufi->msgbufp, nbytes, B_WRITE);
275: if (++du11.dutbufi == du11.dutbuff + MSGN)
276: du11.dutbufi = du11.dutbuff;
277: du11.dutbufn++;
278:
279: /*
280: * If the interrupt code is not running, start it up
281: */
282: if (du11.dutstate == TIDLE)
283: duxstart();
284: }
285:
286: durint()
287: {
288: register c, dustat;
289: register struct dudevice *duaddr = DUADDR;
290:
291: dustat = duaddr->durcsr;
292: if (du11.duproc == 0) {
293: duaddr->dutcsr = DUTCSR_MR;
294: if (maint)
295: #ifdef DU11
296: duaddr->dutcsr |= DUTCSR_MSYSTST;
297: #ifdef UCB_DEVERR
298: printf("durint: er=%b\n", dustat, DU_BITS);
299: #else
300: printf("durint err %o\n", dustat);
301: #endif
302: #else
303: duaddr->dutcsr |= DUTCSR_MPSYSTST;
304: #ifdef UCB_DEVERR
305: printf("durint: er=%b\n", dustat, DU_PBITS);
306: #else
307: printf("durint err %o\n", dustat);
308: #endif
309: #endif DU11
310: return;
311: }
312: switch(du11.durstate) {
313:
314: /*
315: * Wait for the first char to be rcvd, ignoring carrier changes
316: */
317: case RIDLE:
318: if ((dustat & DU_RDONE) == 0)
319: return;
320: if (du11.durbufn == MSGN)
321: goto rfull;
322: du11.durbufc = du11.durbufi->msgbufp; /* set up char ptr */
323: du11.durbufi->msgerr = 0; /* set no error in msg */
324: du11.durbc = 0; /* set byte count */
325: du11.durstate = RRUN; /* set message in progress */
326:
327: /*
328: * A message is in progress
329: */
330: case RRUN:
331: if (dustat & DU_RDONE) { /* a character has arrived */
332: c = duaddr->durdbuf;
333:
334: /*
335: * End message if lost character or message too long
336: */
337: if (c & DURDBUF_OVERRUN) {
338: du11.durover++;
339: goto rerror;
340: }
341: if (du11.durbc++ == MSGLEN) {
342: du11.durlong++;
343: goto rerror;
344: }
345: *du11.durbufc++ = c;
346: }
347: if ((dustat & DU_CAR) == 0) /* carrier drop means */
348: break; /* end of message */
349: return;
350:
351: /*
352: * We have used up all the message buffers. Throw the
353: * message away.
354: */
355: rfull:
356: du11.durfull++;
357: du11.durstate = RQUIT1;
358: case RQUIT1:
359: if ((dustat & DU_CAR) == 0) {
360: du11.durstate = RIDLE;
361: duaddr->durcsr &= ~DU_SSYNC; /* desync receiver */
362: duaddr->durcsr |= DU_SSYNC;
363: }
364: c = duaddr->durdbuf;
365: return;
366:
367: /*
368: * Flag the message no good and junk the rest of it
369: */
370: rerror:
371: du11.durbufi->msgerr++;
372: du11.durstate = RQUIT2;
373:
374: case RQUIT2:
375: c = duaddr->durdbuf;
376: if (dustat & DU_CAR)
377: return;
378: }
379:
380: /*
381: * The message is finished. Set up the byte count and advance
382: * the in pointer to pass the message to the upper-level code.
383: */
384: du11.durbufi->msgbc = du11.durbc;
385: if (++du11.durbufi == du11.durbuff + MSGN)
386: du11.durbufi = du11.durbuff;
387: du11.durbufn++;
388: du11.durstate = RIDLE;
389: duaddr->durcsr &= ~DU_SSYNC; /* desync receiver */
390: duaddr->durcsr |= DU_SSYNC;
391: c = duaddr->durdbuf;
392: wakeup(&du11.durstate);
393: }
394:
395: duxint()
396: {
397: register dustat;
398: register struct dudevice *duaddr = DUADDR;
399: extern duxfin();
400:
401: dustat = duaddr->dutcsr;
402: if (du11.duproc == 0) {
403: duaddr->dutcsr = DUTCSR_MR;
404: if (maint)
405: #ifdef DU11
406: duaddr->dutcsr |= DUTCSR_MSYSTST;
407: #ifdef UCB_DEVERR
408: printf("duxint: er=%b\n", dustat, DUTCSR_BITS);
409: #else
410: printf("duxint err %o\n", dustat);
411: #endif
412: #else
413: duaddr->dutcsr |= DUTCSR_MPSYSTST;
414: #ifdef UCB_DEVERR
415: printf("duxint: er=%b\n", dustat, DUTCSR_PBITS);
416: #else
417: printf("duxint err %o\n", dustat);
418: #endif
419: #endif
420: return;
421: }
422: switch(du11.dutstate) {
423:
424: /*
425: * A message is in progress
426: */
427: case TRUN:
428: /*
429: * Count number of times data not available
430: */
431: if (dustat & DUTCSR_NODATA)
432: du11.dutdna++;
433: if (dustat & DUTCSR_TDONE) {
434: if (--du11.dutbc) { /* if there are more chars */
435: duaddr->dutdbuf = *du11.dutbufc++ & 0377;
436: #ifndef DU11
437: if (du11.dutbc == 1) {
438: duaddr->dutdbuf = DURDBUF_REOM;
439: duaddr->dutcsr &= ~DUTCSR_SEND;
440: du11.dutstate = TLAST;
441: }
442: #endif
443: }
444: #ifdef DU11
445: else /* wait for the last one */
446: {
447: duaddr->dutcsr = DUTCSR_SEND | DUTCSR_DNAIE;
448: if (maint)
449: duaddr->dutcsr |= DUTCSR_MSYSTST;
450: du11.dutstate = TLAST;
451: }
452: #endif
453: }
454: return;
455:
456: /*
457: * Wait for the data not available flag, signifying that the
458: * last char has been completely sent
459: */
460: case TLAST:
461: #ifdef DU11
462: if (dustat & DUTCSR_NODATA)
463: #endif
464: {
465: du11.dutstate = TCARDRP;
466: duaddr->dutcsr = 0; /* drop carrier */
467: if (maint)
468: #ifdef DU11
469: duaddr->dutcsr |= DUTCSR_MSYSTST;
470: #else
471: duaddr->dutcsr |= DUTCSR_MPSYSTST;
472: #endif
473: duaddr->durcsr &= ~DU_RTS;
474: timeout(duxfin, 0, TDELAY);
475: }
476: }
477: }
478:
479: /*
480: * Carrier hold-down delay completed
481: */
482: duxfin()
483: {
484: if (++du11.dutbufo == du11.dutbuff + MSGN)
485: du11.dutbufo = du11.dutbuff;
486: du11.dutbufn--;
487: du11.dutstate = TIDLE;
488:
489: /*
490: * If there is another message in the buffer, start sending it
491: */
492: if (du11.dutbufi != du11.dutbufo)
493: duxstart();
494: wakeup(&du11.dutstate);
495: }
496:
497: /*
498: * Start transmitting a new message
499: */
500: duxstart()
501: {
502: register struct dudevice *duaddr = DUADDR;
503:
504: du11.dutbc = du11.dutbufo->msgbc;
505: du11.dutbufc = du11.dutbufo->msgbufp;
506: du11.dutstate = TRUN;
507: duaddr->durcsr |= DU_RTS;
508:
509: duaddr->dutcsr = DUTCSR_SEND;
510: if (maint)
511: #ifdef DU11
512: duaddr->dutcsr |= DUTCSR_MSYSTST;
513: #else
514: duaddr->dutcsr |= DUTCSR_MPSYSTST;
515: #endif
516: duaddr->dutdbuf = DURDBUF_RSOM | (*du11.dutbufc++ & 0377);
517:
518: /*
519: * Turn on interrupts
520: */
521: duaddr->durcsr |= DU_RIE;
522: duaddr->dutcsr |= DUTCSR_TIE;
523: }
524:
525: /*
526: * Exit if being closed
527: */
528: durtimeout()
529: {
530: if (du11.durtimer < 0) {
531: du11.durtimer = 0;
532: wakeup(&du11.durstate);
533: return;
534: }
535:
536: /*
537: * If duread is sleeping, decrement timer and wakeup if time's up
538: */
539: if (du11.durtimer > 0)
540: if (--du11.durtimer == 0)
541: wakeup(&du11.durstate);
542: timeout(durtimeout, 0, hz);
543: }
544: #endif NDU
Defined functions
Defined variables
maint
defined in line
95; used 9 times
Defined struct's
msgbuf
defined in line
52; used 12 times
Defined macros
DUPRI
defined in line
47; used 3 times
MSGN
defined in line
43; used 12 times
- in line 67,
81,
131,
140-144(2),
242,
254,
266,
275,
320,
385,
484
RIDLE
defined in line
26; used 3 times
RRUN
defined in line
27; used 1 times
SYN
defined in line
42; used 2 times
TIDLE
defined in line
34; used 3 times
TLAST
defined in line
36; used 2 times
TRUN
defined in line
35; used 1 times