|
|
1.1 root 1: /* D.L.Buck and Associates, Inc. - 8/27/84
2: *
3: * COPYRIGHT NOTICE:
4: * Copyright c 8/27/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: * bsctr - BISYNC TRACE Driver
18: *
19: * DESCRIPTION
20: * This trace module represents a pseudo-device to Unix. It has
21: * the usual open, close, read, and ioctl routines for a read-only
22: * device. As well, it has a trace event logging routine which is
23: * called from the other portions of the bisync driver to log state
24: * changes, received information, transmitted information, and errors.
25: * Trace events are stored in a trace buffer until read by a user-level
26: * routine.
27: */
28:
29: #ifndef lint
30: static char bsctr_c[] = "@(#)bsctr.c 1.7 REL";
31: #endif
32:
33: #include "../bsc/local.h"
34: #include "../bsc/bscio.h"
35: #include "../bsc/bsc.h"
36: #include "../bsc/bsctr.h"
37:
38: #if defined BSD42
39: #define ERRRET(x) return x
40: #define UCOUNT uio->uio_resid
41: #else
42: #define ERRRET(x) u.u_error = x; return
43: #define UCOUNT u.u_count
44: #endif
45:
46: #define SIZEMASK 0x03ff
47:
48: extern struct bsc bsc[]; /* device information */
49: char bsctbuf[TBUFSIZE]; /* circular trace buffer */
50: char *bsctbin, *bsctbout; /* ptrs to next write, read locations */
51: char *lastpkt; /* pts to len field of last pkt if 'y' */
52: char bscbw; /* someone's waiting on the trace buffer */
53: unsigned char bsclost; /* number of lost trace events */
54: int bsctlock = -1; /* Trace lock */
55: #if defined BSD42
56: extern struct timeval time;
57: #define TRTIME time.tv_sec
58: #else
59: extern long time;
60: #define TRTIME time
61: #endif
62:
63: #define INSERT(x) {*bsctbin = (x);\
64: if (++bsctbin == &bsctbuf[TBUFSIZE]) bsctbin = bsctbuf;}
65: #define ZERO 0 /* dummy insert value for odd byte receive packets */
66:
67: /*
68: * NAME
69: * bsctr - trace an event for Bisync Drivers
70: * SYNOPSIS
71: * bsctr (dev, state, type [, len, dptr])
72: * dev_t dev; Device number
73: * unsigned state; State number (bscpsm) or other info (bscll)
74: * char type; Trace Packet type
75: * short len; (Optional) Length of data section of packet
76: * char *dptr; (Optional) Pointer to data section (kernel space)
77: * ALGORITHM
78: * 1. Check for trace buffer overflow
79: * 2. If we can't insert next trace packet, count
80: * trace buffer overruns. Otherwise, insert
81: * packet into trace buffer.
82: * 3. If the last packet was of type 'y' and this packet is the
83: * same, combine the packets by merging the data from the
84: * second into the first.
85: * 4. If the last packet was type 'y' and the data length was
86: * odd, make it even by adding a dummy data byte.
87: * 5. Add the new data packet by inserting the time (a long),
88: * state, type, and if type 'x' or 'y', the length and
89: * data.
90: * MACHINE DEPENDENCIES
91: * This algorithm assumes a 'normal' byte ordering within a short.
92: * If the length needs to be increased ((3) above), the low-order
93: * byte address is computed and incremented, and any carry
94: * added to the computed high-order address.
95: * On Intel and PDP-11's, for example, this algorithm will need
96: * to be modified.
97: */
98:
99: bsctr(dev,state,type,len,dptr)
100: dev_t dev; /* bsc device minor number */
101: unsigned state; /* current state number, or other info */
102: char type; /* current state's type */
103: register short int len; /* length of data in dptr */
104: register char *dptr; /* data to be logged */
105: {
106: register int avail; /* number of trace buffer bytes available */
107: short int givenlen;
108:
109: /* 1. check for trace buffer overflow */
110: avail = (bsctbin >= bsctbout) ? TBUFSIZE - (bsctbin - bsctbout):
111: bsctbout - bsctbin;
112: --avail; /* don't allow in to catch out */
113:
114: /* 2. if we can't insert next trace packet, count
115: * trace buffer overruns. Otherwise, insert
116: * packet into trace buffer.
117: */
118: givenlen = (type < 'x') ? 0 : (len & SIZEMASK);
119:
120: if (avail < givenlen+8) { /* we will lose data */
121: ++bsclost;
122: return;
123: }
124:
125: /*
126: * 3. If it is a 'y' type (receive) then the characters will be
127: * sent here one at a time. In order to store them similarly to
128: * 'x' types (transmit), each character is added to the end of the
129: * list of received characters and the length is incremented by one
130: * instead of storing each of the characters as an individual packet.
131: * The first receive character is stored just as a transmit packet
132: * with a length of one. The next packet, if a 'y', is stored as
133: * noted above.
134: */
135:
136: if (type == 'y' && lastpkt) {
137: INSERT(*dptr);
138: lastpkt[0]++; /* Incr. length */
139: if (*lastpkt == 0) { /* Overflow? */
140: if (lastpkt == bsctbuf)
141: bsctbuf[TBUFSIZE-1]++;
142: else lastpkt[-1]++;
143: }
144: } else {
145: /*
146: * Check to see if the last character stored was a receive type
147: * and whether the length was odd. If it was, a
148: * dummy character must be added to force an even boundary
149: * as with transmit characters
150: */
151: if (lastpkt && (*lastpkt & 1))
152: INSERT(ZERO);
153: lastpkt = (char *)0;
154:
155: INSERT(TRTIME>>24);
156: INSERT(TRTIME>>16);
157: INSERT(TRTIME>>8);
158: INSERT(TRTIME);
159: INSERT(state);
160: INSERT(type);
161: if (type >= 'x') { /* we will log data */
162: INSERT(givenlen>>8);
163: if (type == 'y')
164: lastpkt = bsctbin;
165: INSERT(givenlen);
166: if (type == 'x' && (givenlen & 1)) ++givenlen;
167: while (--givenlen >= 0)
168: INSERT(*dptr++);
169: }
170: }
171: if (bscbw) { /* someone waiting */
172: bscbw = 0;
173: wakeup (bsctbuf);
174: }
175: }
176:
177: #if defined BSD42
178: bstread(dev,uio) /* user request to read trace buffer */
179: register dev_t dev;
180: struct uio *uio;
181: #else
182: bstread(dev) /* user request to read trace buffer */
183: register dev_t dev;
184: #endif
185: {
186: register int x, diff;
187: int errcode = 0;
188:
189: dev = minor(dev);
190: x = spl8();
191: while (bsctbin == bsctbout) { /* buffer empty */
192: if (bsc[dev].b_mode == BSC_CLOSED){
193: splx(x);
194: #if defined BSD42
195: return 0;
196: #else
197: return;
198: #endif
199: }
200: ++bscbw; /* indicate we'll sleep for trace buf*/
201: sleep(bsctbuf, BSCPRI);/* sleep for it */
202: }
203: if (lastpkt && (*lastpkt & 1))
204: INSERT(ZERO);
205: lastpkt = (char *)0;
206: diff = (bsctbin > bsctbout) ? bsctbin - bsctbout :
207: TBUFSIZE - (bsctbout - bsctbin);
208: splx(x);
209: if (diff > UCOUNT) diff = UCOUNT;
210: if (&bsctbout[diff] >= &bsctbuf[TBUFSIZE]) {
211: x = &bsctbuf[TBUFSIZE] - bsctbout;
212: #if defined BSD42
213: errcode = uiomove(bsctbout, x, UIO_READ, uio);
214: if (!errcode)
215: errcode = uiomove (bsctbuf, diff - x, UIO_READ, uio);
216: #else
217: if (iomove (bsctbout, x, B_READ) ||
218: iomove (bsctbuf, diff - x, B_READ))
219: errcode = EFAULT;
220: #endif
221: bsctbout = &bsctbuf[diff - x];
222: } else {
223: #if defined BSD42
224: errcode = uiomove(bsctbout, diff, UIO_READ, uio);
225: #else
226: if (iomove(bsctbout, diff, B_READ))
227: errcode = EFAULT;
228: #endif
229: bsctbout += diff;
230: }
231: /* ?. If trace events were lost, add loss event to next buffer */
232: if (bsclost) { /* # trace events lost */
233: x = spl8();
234: bsctr(dev, bsclost, 'o'); /* overrun event */
235: bsclost = 0;
236: splx(x);
237: }
238: #ifdef BSD42
239: return errcode;
240: #else
241: if (errcode)
242: u.u_error = errcode;
243: #endif
244: }
245:
246: bstopen(dev, flag)
247: dev_t dev;
248: {
249: if (bsctlock != -1) {
250: ERRRET(EBUSY);
251: }
252: bsctlock = dev = minor(dev);
253: bsc[dev].b_trace = 1; /* indicate tracing activated */
254: bsctbin = bsctbout = bsctbuf; /* initialize in, out pointers */
255: lastpkt = (char *)0;
256: while (bsc[dev].b_mode == BSC_CLOSED) /* wait till open */
257: sleep (&bsc[dev].b_trace, BSCPRI);
258: #ifdef BSD42
259: return 0;
260: #endif
261: }
262:
263: bstclose(dev)
264: dev_t dev;
265: {
266: wakeup(bsctbuf);
267: bsc[minor(dev)].b_trace = 0;
268: bsctlock = -1;
269: #if defined BSD42
270: return 0;
271: #endif
272: }
273:
274: bstioctl(dev,cmd,arg) /* ioctl entry */
275: dev_t dev;
276: {
277: bsc[minor(dev)].b_trace = (cmd&0xf) + 1;
278: #if defined BSD42
279: return 0;
280: #endif
281: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.