|
|
1.1 root 1: /* D.L.Buck and Associates, Inc. - 9/4/84
2: *
3: * COPYRIGHT NOTICE:
4: * Copyright c 9/4/84 - An unpublished work by
5: * D.L.Buck and Associates, Inc.
6: *
7: * PROPRIETARY RIGHTS NOTICE:
8: * All rights reserved. This document and program contains
9: * proprietary information of D.L.Buck and Associates,Inc.
10: * of San Jose, California, U.S.A., embodying confidential
11: * information, ideas, and expressions, no part of which
12: * may be reproduced, or transmitted in any form or by any
13: * means, electronic, mechanical, or otherwise, without
14: * the written permission of D.L.Buck and Associates, Inc.
15: *
16: * NAME
17: * bsc - bisync device driver
18: *
19: * DESCRIPTION
20: * This file contains the Unix system interface routines, prepared for
21: * UNIX Version 7, System III, System V, or BSD 4.2.
22: * The entry points are bscopen, bscclose, bscread, bscwrite, and
23: * bscioctl. These routines are meant to be hardware-independent.
24: */
25:
26: #ifndef lint
27: static char bsc_c[] = "@(#)bsc.c 1.15 REL";
28: #endif
29:
30: #include "../bsc/local.h"
31: #include "../bsc/bscio.h"
32: #include "../bsc/bsc.h"
33:
34: #if defined v7 || defined BSD42
35: #define delay(x) sleep((caddr_t)&lbolt, BSCPRI)
36: extern int lbolt;
37: #endif
38:
39: #if defined BSD42
40: #define ERRRET(x) return x
41: #define UCOUNT uio->uio_resid
42: #else
43: #define ERRRET(x) u.u_error = x; return
44: #define UCOUNT u.u_count
45: #endif
46:
47: struct bsc bsc[NVBSC*4]; /* device-specific information */
48: extern struct state states[]; /* state table in bscpsm.c */
49:
50: /*
51: * bscopen -- prepare for BISYNC communications
52: * 0) check and lock device
53: * 1) set up defaults for IOCTL-provided parameters
54: * 2) set up counters and fields returned via IOCTL
55: * 3) set up everything else related to bsc driver
56: * 4) do hardware-specific programming and checking
57: * 5) wait for DSR from modem
58: */
59: /*VARARGS1*/
60: bscopen (dev) /* prepare for BISYNC communication */
61: register dev_t dev;
62: {
63: register struct bsc *bp; /* ptr to dev's bsc entry */
64: int errcode;
65:
66: /* 0. Check and lock device. */
67: dev = minor(dev);
68: /* if (dev >= NBSC) { */
69: if (dev >= MX_NBSC) {
70: ERRRET(ENXIO); /* No such device */
71: }
72: bp = &bsc[dev];
73: if (bp->b_lock) { /* Is port locked? */
74: ERRRET(EBUSY); /* Error - port busy */
75: }
76: bp->b_lock = SSLOCK; /* Special single station lock */
77:
78: /* 1. Set up defaults for ioctl-provided params */
79: bp->b_iocin.b_blks = BSCMBLK; /* Max block size */
80: bp->b_hlflgs = BSCPRIM; /* Flags: we are primary */
81: bp->b_iocin.b_termid[0] = '\0'; /* No terminal id */
82: bp->b_iocin.b_hostid[0] = '\0'; /* No host id */
83: bp->b_iocin.b_nbid = /* Max # bids */
84: bp->b_iocin.b_nnak = /* Max # naks we will give */
85: bp->b_iocin.b_nretry = 15; /* Max # receive t/o's and naks */
86: /* we will accept */
87: bp->b_iocin.b_nttd = /* Max # ttds we will accept */
88: bp->b_iocin.b_nwack = 100; /* Max # wacks we will accept */
89: bp->b_iocin.b_nor = 30; /* Max seconds to wait on initial rd */
90:
91: /* 2. Set up counters and fields returned via ioctl */
92: bp->b_iocout.b_blks = 0; /* # blocks sent/received */
93: bp->b_iocout.b_flags = 0; /* Flags: see definition */
94: bp->b_iocout.b_termid[0] = '\0';/* No terminal id */
95: bp->b_iocout.b_hostid[0] = '\0';/* No host id */
96: bp->b_iocout.b_nbid = 0; /* No bids so far */
97: bp->b_iocout.b_nnak = 0; /* No naks so far */
98: bp->b_iocout.b_nretry = 0; /* No retry so far */
99: bp->b_iocout.b_nttd = 0; /* No ttds so far */
100: bp->b_iocout.b_nwack = 0; /* No wacks so far */
101: bp->b_iocout.b_nor = 0; /* No overruns so far */
102:
103: /* 3. Set up miscellaneous fields for driver */
104: bp->b_state = 0; /* Set initial psm state */
105: bp->b_mode = BSC_INIT; /* Initial mode indicates */
106: /* haven't done any i/o yet */
107: bp->b_rxst0 = 0; /* Reset l/l driver state */
108: bp->b_tmperr = 0; /* No temp. errors yet */
109: bp->b_sema = BSC_DDONE; /* Neither psm nor */
110: /* driver busy - both done */
111:
112: /* 4. Initialize I/O port */
113: if (errcode = bsclopn(dev, bp)) {/* device-specific open */
114: bp->b_lock = 0;
115: ERRRET(errcode);
116: }
117:
118: /* 5. wait till DSR shows */
119: while (bsckdsr(dev,bp), !(bp->b_hlflgs & BSC_DSR) && !u.u_error)
120: delay(PSMTICK);
121: if (bp->b_trace)
122: wakeup(&bp->b_trace);
123: if (u.u_error) {
124: bp->b_lock = 0;
125: bsclcls(dev, bp);
126: }
127: #if defined BSD42
128: return 0;
129: #endif
130: }
131:
132: /*
133: * bscclose -- 1) send disconnect message, if we're up and running
134: * 2) turn off DTR, RTS and disable the channel
135: */
136: bscclose(dev)
137: register dev_t dev;
138: {
139: register struct bsc *bp;
140:
141: dev = minor(dev);
142: bp = &bsc[dev];
143:
144: /*debug*/printf("bscclose");
145: /* 1. Terminate PSM processing, kill receive and tracing */
146: if ( (bp->b_hlflgs & (BSCMPT|BSC_DSR)) != BSC_DSR ||
147: bp->b_mode == BSC_INIT)
148: bp->b_mode = BSC_CLOSED; /* Leave quietly */
149: else { /* Point-to-point ... */
150: bp->b_mode = BSC_CL1; /* Send Disconnect */
151: while (bp->b_mode != BSC_CLOSED &&
152: (bp->b_hlflgs & BSC_DSR)) /* Wait */
153: delay(PSMTICK);
154: }
155: bp->b_rclptr = (char *)0; /* terminate receive */
156: bstclose(dev); /* terminate tracing */
157:
158: /* 2. Unlock the port */
159: /*debug*/printf("close:unlock");
160: bp->b_lock = 0;
161:
162: /* 3. Turn off DTR */
163: bsclcls (dev, bp);
164: #if defined BSD42
165: return 0;
166: #endif
167: }
168:
169: /*
170: * bscread -- read next data block.
171: * 0) If error latch set or no DSR, EIO!
172: * 1) if mode = write, EINVAL!
173: * 2) if mode = init, initialize bsc, mode <- idle
174: * 3) if mode = idle, sync with psm, set b_nor timeout,
175: * mode <- read
176: * 4) while buffer empty and no errs and not eof, sleep
177: * 5) Check termination condition:
178: * a) If err, set mode<-idle, reset hlflgs, set EIO error.
179: * b) If signal caused termination, force rxto & reread.
180: * c) If EOF, set mode<-IDLE, reset hlflgs and sema, return.
181: * d) Otherwise, full buffer.
182: * If size not zero, copy it out and mark it empty.
183: */
184: #if defined BSD42
185: bscread(dev,uio)
186: register dev_t dev;
187: struct uio *uio;
188: #else
189: bscread(dev)
190: register dev_t dev;
191: #endif
192: {
193: register struct bsc *bp; /* ptr to bsc device info. */
194: register int l; /* length info. */
195: int x; /* prty save area */
196: int errcode = 0; /* Error code upon exit */
197:
198: dev = minor(dev);
199: bp = &bsc[dev];
200:
201: /* 0. Check error latch and DSR */
202: if (!(bp->b_hlflgs & BSC_DSR) || /* No DSR! */
203: (bp->b_hlflgs & BSC_ERR)) { /* Error logged */
204: if (!(bp->b_hlflgs & BSC_ERR)) {/* Ensure latched err */
205: bp->b_hlflgs |= BSC_ERR;
206: bp->b_iocout.b_flags = BSCNDSR;
207: }
208: bp->b_mode = BSC_IDLE;
209: ERRRET(EIO);
210: }
211:
212: switch (bp->b_mode) {
213: case BSC_WRITE: /* Error! */
214: ERRRET(EINVAL);
215:
216: case BSC_INIT: /* First read or write action */
217: bscsetup(dev); /* Start by initializing */
218: bp->b_mode = BSC_IDLE;
219:
220: case BSC_IDLE: /* Moving from Idle to Write */
221: while (!(bp->b_sema & BSC_PDONE) &&
222: !(bp->b_hlflgs & BSC_ERR))
223: delay(PSMTICK); /* Synchronize */
224: if (bp->b_hlflgs & BSC_ERR) {
225: bp->b_mode = BSC_IDLE;
226: ERRRET(EIO);
227: }
228: /* Set Read Timeout in Ticks */
229: bp->b_rdflag = bp->b_iocin.b_nor*PSMTPS;
230: bp->b_mode = BSC_READ; /* Now we're in read state */
231: x = spl8(); /* *** protect flags *** */
232: bp->b_sema |= BSC_DBUSY;/* Driver now busy */
233: bp->b_sema &= ~BSC_DDONE;
234: splx(x); /* End protection */
235:
236: case BSC_READ: /* Not first read */
237: forceread:
238: x = spl8();
239: /* Test for no-delay mode and not ready */
240: if (bp->b_sema & BSC_SEENBUF) {
241: bp->b_hlflgs &= ~BSC_FULL;
242: bp->b_sema &= ~BSC_SEENBUF;
243: if (states[bp->b_state].s_type == 'd' &&
244: bp->b_alenb) { /* Decision wait? */
245: bp->b_alenb = 0;/* Disable pto */
246: splx(x);
247: bscpsm(dev); /* Wake up PTO */
248: }
249: }
250: if ((bp->b_sema & BSC_NDLY) &&
251: !(bp->b_hlflgs & (BSC_FULL|BSC_ERR|BSC_XLAST))) {
252: splx(x);
253: ERRRET(EAGAIN); /* NO DELAY */
254: }
255: while (!(bp->b_hlflgs & (BSC_FULL|BSC_ERR|BSC_XLAST)))
256: sleep (bp->b_buffer, BSCPRI); /* Take a nap */
257: splx(x);
258:
259: bp->b_rdflag = 0; /* Cancel read timeout */
260:
261: if (bp->b_hlflgs & BSC_XLAST) {
262: x = spl8(); /* Protect flags */
263: bp->b_mode = BSC_IDLE;
264: bp->b_hlflgs &= ~(BSC_XLAST|BSC_XTRN);
265: bp->b_sema |= BSC_DDONE;
266: bp->b_sema &= ~BSC_DBUSY;
267: splx(x);
268: goto readexit; /* EOF! */
269: }
270:
271: if (bp->b_hlflgs & BSC_ERR) { /* Error way out */
272: bp->b_hlflgs &= ~(BSC_XLAST|BSC_XTRN);
273: bp->b_hlflgs &= ~BSC_FULL;
274: bp->b_sema &= ~BSC_SEENBUF;
275: bp->b_mode = BSC_IDLE;
276: ERRRET(EIO);
277: } else { /* No errors - copy buffer out */
278: l = bp->b_bsize;/* Size of data in buffer */
279: if (l > UCOUNT)
280: l = UCOUNT;
281: if (l) /* transfer data */
282: #if defined BSD42
283: errcode = uiomove(bp->b_buffer,l,UIO_READ,uio);
284: #else
285: if (iomove (bp->b_buffer, l, B_READ))
286: errcode = EFAULT;
287: #endif
288: }
289:
290: /* If FAST-ACKNOWLEDGE mode in effect, ACK on next read */
291: if (bp->b_sema & BSC_FACK) {
292: bp->b_sema |= BSC_SEENBUF;
293: goto readret;
294: } else
295: bp->b_hlflgs &= ~BSC_FULL; /* Mark empty */
296: readexit: x = spl8();
297: if (states[bp->b_state].s_type == 'd' &&
298: bp->b_alenb) { /* Decision wait? */
299: bp->b_alenb = 0; /* Disable PTO */
300: splx(x);
301: bscpsm(dev); /* Awaken PSM */
302: }
303: else splx(x);
304: }
305: readret:
306: #if defined BSD42
307: return errcode;
308: #else
309: if (errcode)
310: u.u_error = errcode;
311: #endif
312: }
313:
314: /*
315: * bscwrite -- 0) if no DSR or error latch set, EIO
316: * 1) if length to write zero or > max, EINVAL
317: * 2) if mode = read, EINVAL!
318: * 3) if mode = init, prime the driver
319: * 4) if mode = idle, init, or write,
320: * a) set mode to write,
321: * b) wait till buffer empty,
322: * c) fill the buffer,
323: * d) set flag to show buffer full.
324: */
325: #if defined BSD42
326: bscwrite(dev,uio)
327: register dev_t dev;
328: struct uio *uio;
329: #else
330: bscwrite(dev)
331: register dev_t dev;
332: #endif
333: {
334: register int l; /* length given us */
335: register struct bsc *bp; /* ptr to bsc dev info */
336: int x; /* priority save area */
337: int errcode = 0; /* Error code to be returned */
338:
339: bp = &bsc[dev = minor(dev)];
340:
341: /* 0. Check error latch and DSR */
342: if (bp->b_hlflgs & BSC_ERR && bp->b_iocout.b_flags == BSCRXTO) {
343: bp->b_hlflgs &= ~BSC_ERR;
344: bp->b_iocout.b_flags = 0;
345: bp->b_mode = BSC_IDLE;
346: }
347: if (!(bp->b_hlflgs & BSC_DSR) || (bp->b_hlflgs & BSC_ERR)) {
348: if (!(bp->b_hlflgs & BSC_ERR)) {/* ensure latched err */
349: bp->b_hlflgs |= BSC_ERR;
350: bp->b_iocout.b_flags = BSCNDSR;
351: }
352: bp->b_mode = BSC_IDLE;
353: ERRRET(EIO);
354: }
355:
356: /* 1. Check length and other errors */
357: if ( (l = UCOUNT) == 0 || l > bp->b_iocin.b_blks) { /* bad length */
358: ERRRET(EINVAL);
359: }
360:
361: /* 2. process according to mode */
362: switch (bp->b_mode)
363: {
364: case BSC_READ:
365: if ((bp->b_sema & BSC_FACK) && (bp->b_sema & BSC_SEENBUF)) {
366: bp->b_hlflgs &= ~BSC_FULL;
367: bp->b_sema &= ~BSC_SEENBUF;
368: bp->b_mode = BSC_WRITE;
369: goto casewrite;
370: }
371: if (bp->b_rdflag == 0) {
372: ERRRET(EINVAL); /* oops - can't read now! */
373: } else {
374: bp->b_rdflag = 1; /* kill read timeout */
375: x = spl8(); /* *** protect flags *** */
376: bp->b_sema &= ~BSC_DBUSY;
377: bp->b_sema |= BSC_DDONE;
378: splx(x); /* end protection */
379: /* wait till timeout */
380: while (bp->b_mode == BSC_READ &&
381: !(bp->b_hlflgs & BSC_ERR))
382: delay(PSMTICK);
383: }
384:
385: case BSC_INIT:
386: bscsetup(dev); /* set up device */
387: bp->b_mode = BSC_IDLE;
388:
389: case BSC_IDLE:
390: if (bp->b_hlflgs & BSC_FULL) {
391: ERRRET(EINVAL); /* caller needs to read */
392: }
393: while (!(bp->b_sema & BSC_PDONE) &&
394: !(bp->b_hlflgs & BSC_ERR))
395: delay(PSMTICK); /* Synchronize */
396: if (bp->b_hlflgs & BSC_ERR) {
397: bp->b_mode = BSC_IDLE;
398: ERRRET(EIO);
399: }
400:
401: bp->b_mode = BSC_WRITE; /* set new mode */
402: x = spl8(); /* *** protect flags *** */
403: bp->b_hlflgs &= ~BSC_ERR; /* reset possible err */
404: bp->b_sema |= BSC_DBUSY;/* driver now busy */
405: bp->b_sema &= ~BSC_DDONE;
406: splx(x); /* *** end protection *** */
407:
408: casewrite:
409: case BSC_WRITE:
410: x = spl8();
411: while ((bp->b_hlflgs & BSC_FULL) && /* wait til empty */
412: !(bp->b_hlflgs & BSC_ERR)) /* and no error */
413: sleep (bp->b_buffer, BSCPRI); /* take a nap */
414: splx(x);
415:
416: if (bp->b_hlflgs & BSC_ERR){ /* if error, EIO */
417: bp->b_hlflgs &= ~(BSC_XLAST|BSC_FULL|BSC_XTRN);
418: bp->b_mode = BSC_IDLE;
419: errcode = EIO;
420: break;
421: }
422: /* copy data to buffer */
423: #if defined BSD42
424: errcode = uiomove(bp->b_buffer, l, UIO_WRITE, uio);
425: #else
426: if (iomove (bp->b_buffer, l, B_WRITE))
427: errcode = EFAULT;
428: #endif
429: bp->b_bsize = l; /* save size */
430: x = spl8();
431: bp->b_hlflgs |= BSC_FULL; /* bufr now full */
432: if (states[bp->b_state].s_type == 'd' &&
433: bp->b_alenb) { /* decision wait? */
434: bp->b_alenb = 0; /* disable pto */
435: splx(x);
436: bscpsm(dev); /* wake 'em up */
437: } else splx(x);
438:
439: if (bp->b_hlflgs & BSC_XLAST) { /* if last block, wait*/
440: x = spl8();
441: while ((bp->b_hlflgs & BSC_FULL) && /* wait til empty */
442: !(bp->b_hlflgs & BSC_ERR)) /* and no error */
443: sleep (bp->b_buffer, BSCPRI);/* take a nap */
444: splx(x);
445: if (bp->b_hlflgs & BSC_ERR) /* if error, EIO */
446: errcode = EIO;
447: else {
448: x = spl8(); /* *** protect flags *** */
449: bp->b_sema |= BSC_DDONE;
450: bp->b_sema &= ~BSC_DBUSY;
451: splx(x); /* *** end protection *** */
452: }
453: bp->b_mode = BSC_IDLE;
454: x = spl8(); /* *** protect flags *** */
455: bp->b_hlflgs &= ~(BSC_XLAST|BSC_FULL|BSC_XTRN);
456: splx(x); /* end protection */
457: }
458: }
459: #if defined BSD42
460: return errcode;
461: #else
462: if (errcode)
463: u.u_error = errcode;
464: #endif
465: }
466:
467: /* bscioctl -- set options or get counter values
468: * Depending on cmd:
469: * BSCGET - copy b_iocout to user's area
470: * BSCSET - copy user's values to b_iocin (set stuff)
471: * BSCTRNSP - set transparent mode flag
472: * BSCNTRNS - reset transparent mode flag
473: * BSCSOH - set send SOH flag
474: * BSCNSOH - turn off SOH flag
475: * BSCLAST - set send last flag
476: * BSCNDLY - set NO DELAY flag
477: */
478: /*VARARGS3*/
479: bscioctl(dev, cmd, arg)
480: register dev_t dev;
481: struct bscio *arg;
482: {
483: register struct bsc *bp; /* ptr to dev info */
484: struct bscio tmp; /* temp struct for chk'g user params*/
485: register int x;
486: int y, errcode = 0;
487:
488: bp = &bsc[dev = minor(dev)];
489: if (cmd != BSCGET && cmd != BSCSET) { /* if write op, wait on buf */
490: x = spl8();
491: while (bp->b_mode == BSC_WRITE && bp->b_hlflgs & BSC_FULL)
492: sleep (bp->b_buffer, BSCPRI);
493: splx(x);
494: }
495: switch (cmd) {
496: case BSCGET:
497: x = spl8();
498: #if defined BSD42
499: bcopy(&bp->b_iocout, arg, sizeof bp->b_iocout);
500: #else
501: if (copyout(&bp->b_iocout, arg, sizeof bp->b_iocout))
502: errcode = EFAULT;
503: #endif
504: bp->b_iocout.b_flags = 0;
505: if (bp->b_hlflgs & BSC_ERR) { /* error latch set? */
506: bp->b_hlflgs &= ~(BSC_ERR|BSC_XLAST|BSC_FULL|BSC_XTRN);
507: bp->b_sema &= ~BSC_DBUSY;
508: bp->b_sema |= BSC_DDONE;
509: }
510: splx(x);
511: break;
512:
513: case BSCSET:
514: if (bp->b_mode == BSC_READ || bp->b_mode == BSC_WRITE) {
515: ERRRET(EINVAL);
516: }
517: #if defined BSD42
518: bcopy(arg, &tmp, sizeof tmp);
519: #else
520: if (copyin (arg, &tmp, sizeof tmp)) {
521: errcode = EFAULT;
522: break;
523: }
524: #endif
525: if (tmp.b_blks > BSCMBLK) { /* block size too big? */
526: ERRRET(EINVAL);
527: }
528: bcopy (/*from*/&tmp, /*to*/&bp->b_iocin, sizeof tmp);
529: x = spl8(); /* *** protect hlflgs */
530: bp->b_hlflgs &= ~BSC_UFLAGS; /* throw out old user flags */
531: bp->b_hlflgs |= (tmp.b_flags & BSC_UFLAGS);
532: splx(x); /* *** end protection */
533: bscparam(dev); /* redo parameters */
534: break;
535:
536: case BSCTRNSP:
537: x = spl8(); /* *** protect hlflgs */
538: bp->b_hlflgs |= BSC_XTRN; /* set transparent mode */
539: splx(x); /* *** end protection */
540: break;
541:
542: case BSCNTRNS:
543: x = spl8(); /* *** protect hlflgs */
544: bp->b_hlflgs &= ~BSC_XTRN; /* reset transp. mode */
545: splx(x); /* *** end protection */
546: break;
547:
548: case BSCSOH:
549: x = spl8(); /* *** protect hlflgs */
550: bp->b_hlflgs |= BSC_XSOH; /* set send SOH flag */
551: splx(x); /* *** end protection */
552: break;
553:
554: case BSCNSOH:
555: x = spl8(); /* *** protect hlflgs */
556: bp->b_hlflgs &= ~BSC_XSOH; /* clear send SOH flag*/
557: splx(x); /* *** end protection */
558: break;
559:
560: case BSCLAST:
561: x = spl8(); /* *** protect hlflgs */
562: bp->b_hlflgs |= BSC_XLAST; /* set send last blk flag */
563: splx(x); /* *** end protection */
564: break;
565:
566: case BSCID:
567: y = (bp->b_iocin.b_flags & BSCASCII)? 0x20 : 0x40;
568: #if defined BSD42
569: bcopy(&y,arg,sizeof y);
570: #else
571: copyout(&y,(int *)arg,sizeof y);
572: #endif
573: break;
574:
575: case BSCNDLY:
576: x = spl8(); /* *** protect flags */
577: bp->b_sema |= BSC_NDLY; /* Set NO DELAY flag */
578: splx(x); /* *** end protection */
579: break;
580:
581: case BSCFACK:
582: x = spl8(); /* *** protect flags */
583: bp->b_sema |= BSC_FACK; /* Set FAST ACKNOWLEDGE */
584: splx(x); /* *** end protection */
585: break;
586:
587: default:
588: ERRRET(EINVAL);
589: }
590: #if defined BSD42
591: return errcode;
592: #else
593: if (errcode)
594: u.u_error = errcode;
595: #endif
596: }
597:
598: /*
599: * bscsetup -- start the psm (protocol state machine)
600: * 1) if state > 0, already started
601: * 2) invoke the psm
602: * 3) set timeout for 1 tick for psm
603: */
604: bscsetup(dev)
605: register dev_t dev;
606: {
607: void bscpto();
608:
609: if (bsc[dev].b_state || bsc[dev].b_mode != BSC_INIT)
610: return;
611: bscpsm(dev);
612: timeout (bscpto, (caddr_t)dev, PSMTICK);
613: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.