|
|
1.1 root 1: #include "../bsc/local.h"
2: #include "../bsc/bscio.h"
3: #include "../bsc/bsc.h"
4:
5: /* D.L.Buck and Associates, Inc. - %H%
6: *
7: * COPYRIGHT NOTICE:
8: * Copyright c %H% - An unpublished work by
9: * D.L.Buck and Associates, Inc.
10: *
11: * PROPRIETARY RIGHTS NOTICE:
12: * All rights reserved. This document and program contains
13: * proprietary information of D.L.Buck and Associates,Inc.
14: * of San Jose, California, U.S.A., embodying confidential
15: * information, ideas, and expressions, no part of which
16: * may be reproduced, or transmitted in any form or by any
17: * means, electronic, mechanical, or otherwise, without
18: * the written permission of D.L.Buck and Associates, Inc.
19: *
20: * NAME
21: * bscpsm -- BISYNC Single- or Multi-station Protocol State Machine
22: *
23: * DESCRIPTION
24: * The BISYNC protocol is implemented via a state machine. The state
25: * machine consists of a state table, the state machine algorithm,
26: * and a set of state actions.
27: *
28: * Each state in the state machine is either a 'send', 'receive',
29: * 'decision', 'function', or 'error' state. Each has a particular
30: * action associated with it. Before defining the state table for the
31: * protocol state machine, we introduce the state enumerations for use
32: * in subsequent definitions.
33: */
34:
35: #ifndef lint
36: static char bscpm_c[] = "%W% %Q%";
37: #endif
38:
39: long TWAIT = 2;
40:
41: #define START 0 /* starting state */
42: #define PTPT 1 /* Starting state for point-to-point */
43: #define SNDBID 2 /* pt-pt write; send bid */
44: #define WTBIDA 3 /* wait bid acknowledgement */
45: #define CKHOST 4 /* check host id */
46: #define CKXMIT 5 /* check transmit buffer */
47: #define SNDTXT 6 /* send text block */
48: #define WTTXTA 7 /* wait text acknowledgement */
49: #define RGTACK 8 /* check for correct ack */
50: #define XFLIP 9 /* flip even/odd block indicator */
51: #define SNDTTD 10 /* text buffer empty - send ttd */
52: #define WTTTDA 11 /* wait for ttd acknowledgement */
53: #define PROERR 12 /* error - protocol violation */
54: #define SNDEOT 13 /* send eot */
55: #define RTYERR 14 /* error - # retries exceeded */
56: #define WNGACK 15 /* wrong acknowledgement */
57: #define CKNWAK 16 /* check wack counter */
58: #define WAKERR 17 /* error - too many wack's */
59: #define CKNRTY 18 /* check # retries */
60: #define CHKRVI 19 /* check action on rvi */
61: #define RVIERR 20 /* error - rvi received */
62: #define RTOENQ 21 /* send enq for timeout */
63: #define WTRTOA 22 /* wait for response to timeout enq */
64: #define CKNRT2 23 /* check # retries */
65: #define CORACK 24 /* check for correct acknowledgement */
66: #define BIDEOT 25 /* send eot then rebid */
67: #define CKNBID 26 /* check # bids sent */
68: #define BIDERR 27 /* error - bid count exceeded */
69: #define HSTERR 28 /* error - wrong host id */
70: #define DONE 29 /* transmit complete */
71: #define WTPTPT 30 /* wait for point-to-point enq */
72: #define SETODD 31 /* set odd block count */
73: #define CKRDY 32 /* check rcv buffer availability */
74: #undef DELAY
75: #define DELAY 33 /* send wack */
76: #define WTWAKA 34 /* wait wack acknowledgement */
77: #define SNDLST 35 /* send last acknowledgement */
78: #define WTTEXT 36 /* receive text */
79: #define CKBCC 37 /* check bcc */
80: #define NAKERR 38 /* error - too many nak's */
81: #define SNDNAK 39 /* send nak */
82: #define CKNTTD 40 /* check # ttd's */
83: #define TTDERR 41 /* error - too many ttd's */
84: #define CKABTM 42 /* check for abnormal termination */
85: #define RXEEOF 43 /* error - early eof */
86: #define RDONE 44 /* receive complete */
87: #define SNDDSC 45 /* line closed - send disconnect */
88: #define XTO 46 /* error - transmit timeout */
89: #define NODSR 47 /* error - modem dropped DSR */
90: #define CONTND 48 /* error - line contention on send */
91: #define MPT 49 /* multipoint poll receive */
92: #define CKMPT 50 /* check multipoint address */
93: #define MPTCNT 51 /* mulipoint contention */
94: #define FASTAK 52 /* fast acknowledge */
95: #define POLEOT 53 /* send eot to poll */
96: #define TOOBIG 54 /* Received block was greater than BSCMBLK */
97: #define SETLST 55 /* Set "last sent" to ack0/1 */
98: extern long nvbsc;
99: extern struct bsc bsc[];
100: #ifdef NBSM
101: extern struct bscsub bscsubs[NBSM][NBSSUB];
102: extern char ascdev[],ebcdev[];
103: #endif
104:
105: /*
106: * There are NX different transmission messages, as follows:
107: */
108: #define X_BID 0 /* initial bid request */
109: #define X_TXT 1 /* text message */
110: #define X_TTD 2 /* temporary transmit delay */
111: #define X_EOT 3 /* end of transmission */
112: #define X_ENQ 4 /* repeat last message request */
113: #define X_LST 5 /* send last acknowledgement */
114: #define X_WAK 6 /* acknowledge with wait request */
115: #define X_NAK 7 /* negative acknowledgement */
116: #define X_DSC 8 /* disconnect */
117: #define X_BAK 9 /* bid acknowledgement */
118: #define NX 10 /* number of transmission messages */
119:
120: /* These are the ASCII messages and message components: */
121:
122: typedef struct xlist xl;
123: /* initial bid */
124: xl ascbid[] = { { 0, 0 }, { 1, "\005" }, {0,0} };
125: /* init bid response */
126: xl ascbak[] = { { 0, 0 }, { 2, "\020\060" }, {0,0} };
127: /* text block */
128: xl asctxt[] = { { 1, "" }, /* stx or soh */
129: { 0, "" }, /* data */
130: { 0, "\020" }, /* if transparent, len = 1 */
131: { 0, "" }, /* etb or etx */
132: #ifdef MANCRC
133: { 1, "" }, /* crc */
134: #endif
135: {0,0} }; /* changed! */
136: xl astx = { 1, "\002" }; /* start of text block */
137: xl atstx = { 2, "\020\002" }; /* start of transparent text block */
138: xl asoh = { 1, "\001" }; /* start of header */
139: xl atsoh = { 2, "\020\001" }; /* start of transparent header */
140: xl aetb = { X_CRC|1, "\027" }; /* end intermediate text blk */
141: xl aetx = { X_CRC|1, "\003" }; /* end last text block */
142: xl ascttd[] = { { 2, "\002\005" }, {0,0} }; /* temp. xmit delay */
143: xl asceot[] = { { 1, "\004" }, {0,0} }; /* end of transmission */
144: xl ascenq[] = { { 1, "\005" }, {0,0} }; /* enquiry */
145: xl asclst[] = { { 2, "" }, {0,0} }; /* changed! */
146: xl aack0 = {2, "\020\060" }; /* even acknowledgement */
147: xl aack1 = {2, "\020\061" }; /* odd acknowledgement */
148: xl ascwak[] = { { 2, "\020\073" }, {0,0} }; /* acknowledge with wait */
149: xl ascnak[] = { { 1, "\025" }, {0,0} }; /* negative acknowledgement */
150: xl ascdsc[] = { { 2, "\020\004" }, {0,0} }; /* disconnect sequence */
151: xl *asclist[] = {ascbid, asctxt, ascttd, asceot, ascenq, asclst, ascwak,
152: ascnak, ascdsc, ascbak};
153:
154: /* ebcdic transmit lists */
155: /* initial bid */
156: xl ebcbid[] = { { 0, 0 }, { 1, "\055" }, {0,0} };
157: /* init bid response */
158: xl ebcbak[] = { { 0, 0 }, { 2, "\020\160" }, {0,0} };
159: /* text block */
160: xl ebctxt[] = { { 1, "" }, /* stx or soh */
161: { 0, "" }, /* data */
162: { 0, "\020" }, /* if transparent, len = 1 */
163: { 0, "" }, /* etb or etx */
164: #ifdef MANCRC
165: { 2, "" }, /* crc */
166: #endif
167: {0,0} }; /* changed! */
168: xl estx = { 1, "\002" }; /* start of text block */
169: xl etstx = { 2, "\020\002" }; /* start of transparent text block */
170: xl esoh = { 1, "\001" }; /* start of header */
171: xl etsoh = { 2, "\020\001" }; /* start of transparent header */
172: xl eetb = { X_CRC|1, "\046" }; /* end intermediate text blk */
173: xl eetx = { X_CRC|1, "\003" }; /* end last text block */
174: xl ebcttd[] = { { 2, "\002\055" }, {0,0} }; /* temp. xmit delay */
175: xl ebceot[] = { { 1, "\067" }, {0,0} }; /* end of transmission */
176: xl ebcenq[] = { { 1, "\055" }, {0,0} }; /* enquiry */
177: xl ebclst[] = { { 2, "" }, {0,0} }; /* changed! */
178: xl eack0 = {2, "\020\160" }; /* even acknowledgement */
179: xl eack1 = {2, "\020\141" }; /* odd acknowledgement */
180: xl ebcwak[] = { { 2, "\020\153" }, {0,0} }; /* acknowledge with wait */
181: xl ebcnak[] = { { 1, "\075" }, {0,0} }; /* negative acknowledgement */
182: xl ebcdsc[] = { { 2, "\020\067" }, {0,0} }; /* disconnect sequence */
183: xl *ebclist[] = {ebcbid, ebctxt, ebcttd, ebceot, ebcenq, ebclst, ebcwak,
184: ebcnak, ebcdsc, ebcbak};
185:
186: /* receive lists - both transmission codes
187: *
188: * Each receive list is a string of the different states to which to
189: * transfer based on the level-0 packet classification.
190: * This string indexed by a frame type (see bsc.h) gives the state for the
191: * corresponding packet class.
192: */
193:
194: char rlbida[NC] = {
195: /* - enq - eot - nak - etx - etb - wak - rvi - ak0 - ak1 - ttd */
196: CKNBID,CKNBID,BIDEOT,BIDEOT,BIDEOT,CKNBID,BIDEOT,CKHOST,BIDEOT,BIDEOT};
197: char rltxta[NC] = {
198: /* - enq - eot - nak - etx - etb - wak - rvi - ak0 - ak1 - ttd */
199: PROERR,PROERR,CKNRTY,FASTAK,FASTAK,CKNWAK,CHKRVI,RGTACK,RGTACK,PROERR};
200: char rlttda[NC] = {
201: /* - enq - eot - nak - etx - etb - wak - rvi - ak0 - ak1 - ttd */
202: PROERR,PROERR,CKXMIT,PROERR,PROERR,PROERR,PROERR,PROERR,PROERR,PROERR};
203: char rlrtoa[NC] = {
204: /* - enq - eot - nak - etx - etb - wak - rvi - ak0 - ak1 - ttd */
205: CKNRT2,PROERR,CKNRTY,FASTAK,FASTAK,CKNWAK,CHKRVI,CORACK,CORACK,CKNRT2};
206: char rlptpt[NC] = {
207: /* - enq - eot - nak - etx - etb - wak - rvi - ak0 - ak1 - ttd */
208: SETODD,WTPTPT,WTPTPT,WTPTPT,WTPTPT,WTPTPT,WTPTPT,WTPTPT,WTPTPT,WTPTPT};
209: char rltext[NC] = {
210: /* - enq - eot - nak - etx - etb - wak - rvi - ak0 - ak1 - ttd */
211: SETLST,CKABTM,WTTEXT,CKBCC, CKBCC, WTTEXT,WTTEXT,WTTEXT,WTTEXT,CKNTTD};
212: char rlwaka[NC] = {
213: /* - enq - eot - nak - etx - etb - wak - rvi - ak0 - ak1 - ttd */
214: CKRDY,RXEEOF,WTWAKA,PROERR,PROERR,WTWAKA,WTWAKA,WTWAKA,WTWAKA,PROERR};
215: char rlwtps[NC] = {
216: /* - enq - eot - nak - etx - etb - wak - rvi - ak0 - ak1 - ttd */
217: CKMPT, CKMPT, MPT, MPT, MPT, MPT, MPT, MPT, MPT, MPT };
218:
219: /*
220: * There are NR different receive lists, as shown above; these
221: * are numbered for use in the protocol state entry for a receive
222: * operation. The following constants index 'rlist' to provide a pointer
223: * to the appropriate receive list.
224: */
225: #define R_BIDA 0 /* bid acknowledgement wait */
226: #define R_TXTA 1 /* text acknowledgement wait */
227: #define R_TTDA 2 /* temp. text delay ack. wait */
228: #define R_RTOA 3 /* response time out wait */
229: #define R_PTPT 4 /* point-to-point bid wait */
230: #define R_TEXT 5 /* wait for text */
231: #define R_WAKA 6 /* wait for response to wack message */
232: #define R_POLSEL 7 /* wait for poll/select */
233: #define NR 8 /* number of receive lists */
234:
235: char *rlist[NR] = {rlbida, rltxta, rlttda, rlrtoa, rlptpt, rltext, rlwaka,
236: rlwtps};
237:
238: /*
239: * PSM states may consist of decision functions, which decide for themselves
240: * what the following state will be, and ordinary functions, which have the
241: * next state decided for them in the PSM state table.
242: * Each function is represented by an ordinal in the state table, as follows:
243: */
244: #define D_START 0 /* decide multipoint vs point-to-point */
245: #define D_PTPT 1 /* decide on send vs receive */
246: #define D_CKHOST 2 /* check correctness of host id */
247: #define D_CKXMIT 3 /* check status of xmit buffer */
248: #define D_RGTACK 4 /* check to see if ack is right */
249: #define D_XFLIP 5 /* flip even/odd indicator - block recv'd */
250: #define D_CKNWAK 6 /* check max wacks allowed */
251: #define D_CKNRTY 7 /* check max retries allowed */
252: #define D_CHKRVI 8 /* check rvi action */
253: #define D_CKNRT2 9 /* check max retries allowed */
254: #define D_CORACK 10 /* check current vs previous ack */
255: #define D_CKNBID 11 /* check max bids allowed */
256: #define F_SETODD 12 /* set odd block expected */
257: #define D_CKRDY 13 /* check status of rcv buffer */
258: #define D_CKBCC 14 /* check last block's crc */
259: #define D_CKNTTD 15 /* check max ttd's allowed */
260: #define D_CKABTM 16 /* check for normal transmission termination */
261: #define D_CKMPT 17 /* check poll/select address */
262: #define D_FASTACK 18 /* wait during fast acknowledge */
263: #define F_SETLST 19 /* Set even/odd ackn. message */
264:
265: struct state states[] = {
266: { 'd', 0, D_START }, /* 0 decide on pt-pt vs multipoint */
267: { 'd', 0, D_PTPT }, /* 1 decide on send vs receive */
268: { 's', WTBIDA, X_BID }, /* 2 send ENQ (bid) */
269: { 'r', CKNBID, R_BIDA },/* 3 receive bid acknowledgement */
270: { 'd', 0, D_CKHOST }, /* 4 check to see if right host id */
271: { 'd', 0, D_CKXMIT }, /* 5 check for full transmit buffer */
272: { 's', WTTXTA, X_TXT }, /* 6 send stx, data, et[bx], ... */
273: { 'r', RTOENQ, R_TXTA}, /* 7 wait text acknowledgement */
274: { 'd', 0, D_RGTACK }, /* 8 check for correct acknowledgement */
275: { 'f', CKXMIT, D_XFLIP},/* 9 flip even/odd indicator */
276: { 's', WTTTDA, X_TTD }, /* 10 send temp. text delay */
277: { 'r', CKXMIT, R_TTDA },/* 11 wait proper response (nak) */
278: { 'e', SNDEOT,BSCPROTO},/* 12 protocol error - funny response */
279: { 's', START, X_EOT }, /* 13 send eot */
280: { 'e', SNDEOT,BSCNRETR},/* 14 NRETRY limit exceeded */
281: { 's', WTTXTA, X_ENQ}, /* 15 wrong ack - send enq */
282: { 'd', 0, D_CKNWAK }, /* 16 check # wacks received in a row */
283: { 'e', SNDEOT,BSCNWACK},/* 17 NWACK limit exceeded */
284: { 'd', 0, D_CKNRTY }, /* 18 check # retries */
285: { 'd', 0, D_CHKRVI }, /* 19 check whether we abort or accept RVI */
286: { 'e', SNDEOT, BSCRVI },/* 20 error - RVI received */
287: { 's', WTRTOA, X_ENQ }, /* 21 receive timeout - send ENQ */
288: { 'r', CKNRT2, R_RTOA },/* 22 wait on acknowledgement to ENQ */
289: { 'd', 0, D_CKNRT2 }, /* 23 check # retries */
290: { 'd', 0, D_CORACK }, /* 24 check to see if we resend text */
291: { 's', CKNBID, X_EOT }, /* 25 bad response to bid */
292: { 'd', 0, D_CKNBID }, /* 26 check # bids */
293: { 'e', SNDEOT, BSCNBID},/* 27 error - too many unanswered bids */
294: { 'e', SNDEOT, BSCWHI}, /* 28 error - wrong host */
295: { 'e', SNDEOT, 0 }, /* 29 done! */
296: { 'r', WTPTPT, R_PTPT },/* 30 wait for line bid from other end */
297: { 'f', CKRDY, F_SETODD},/* 31 set odd response indicator */
298: { 'd', 0, D_CKRDY }, /* 32 check receive buffer available */
299: { 's', WTWAKA, X_WAK }, /* 33 buffer unavailable - send wack */
300: { 'r', WTWAKA, R_WAKA}, /* 34 wait wack acknowledgement */
301: { 's', WTTEXT, X_LST }, /* 35 send 'last response' */
302: { 'r', WTTEXT, R_TEXT}, /* 36 wait for text */
303: { 'd', 0, D_CKBCC }, /* 37 check bcc (crc or lrc) */
304: { 'e', SNDEOT, BSCNNAK},/* 38 error - nak limit exceeded */
305: { 's', WTTEXT, X_NAK }, /* 39 send nak (to TTD or bad text block) */
306: { 'd', 0, D_CKNTTD }, /* 40 check TTD limits */
307: { 'e', SNDEOT, BSCNTTD},/* 41 error - TTD limit exceeded */
308: { 'd', 0, D_CKABTM }, /* 42 check for normal eof or early eof */
309: { 'e', 0, BSCEEOF }, /* 43 early end of file */
310: { 'e', 0, 0 }, /* 44 normal end of receive */
311: { 's', START, X_DSC}, /* 45 send disconnect message */
312: { 'e', 0, BSCTXTO }, /* 46 error - xmit timeout */
313: { 'e', 0, BSCNDSR }, /* 47 error - no DSR */
314: { 'e', SNDEOT,BSCONTND},/* 48 error - line contention */
315: { 'r', MPT, R_POLSEL }, /* 49 MPT Wait Poll/Select */
316: { 'd', 0, D_CKMPT }, /* 50 CKMPT Check Poll/select address */
317: { 'e', MPT, BSCONTND }, /* 51 MPTCNT Multipoint contention */
318: { 'd', CKBCC,D_FASTACK},/* 52 FASTAK Wait during fast acknowledge */
319: { 's', MPT, X_EOT }, /* 53 POLEOT Respond negatively to poll */
320: { 'e', SNDEOT, BSC2BIG},/* 54 TOOBIG Rcvd block was too big */
321: { 'f', SNDLST,F_SETLST},/* 55 SETLST Set even/odd last send pointer */
322: };
323:
324:
325: bscpsm(dev) /* protocol state machine */
326: register dev_t dev;
327: {
328: register struct bsc *bp;
329: #ifdef NBSM
330: register struct bscsub *bsp;
331: #endif
332: register struct state *st;
333: int x,xx;
334: register int iflag, dflag;
335:
336: if (dev >= MX_NBSC)
337: panic("bsc: unknown device#");
338: bp = &bsc[dev];
339:
340: x = spl8(); /* Lock the door */
341: if (bp->b_sema & BSC_INPSM) { /* Someone have it locked? */
342: splx(x); /* Yes - leave quietly */
343: return;
344: }
345: bp->b_sema |= BSC_INPSM; /* Make sure no one else enters */
346: splx(x);
347:
348: if (bp->b_mode == BSC_CL1) { /* Need to send disconnect */
349: bp->b_state = SNDDSC; /* New state: send disconnect */
350: bp->b_mode = BSC_CL2; /* New mode: wait for disc complete */
351: }
352:
353: #ifdef NBSM
354: if (bp->b_lock != SSLOCK)
355: if (bp->b_psmbsy == -1)
356: bsp = NULL;
357: else
358: bsp = &bscsubs[dev][bp->b_psmbsy];
359: #endif
360:
361: /* Main loop of Protocol State Machine */
362: while (1) {
363: st = &states[bp->b_state];
364:
365: /* If tracing engaged, trace this state */
366: if (bp->b_trace)
367: bsctr (dev, bp->b_state, st->s_type);
368: switch (st->s_type) {
369: case 'f': /* function */
370: bp->b_state = st->s_next;/* always use table's new st*/
371: case 'd': /* decision */
372: iflag = bp->b_hlflgs; /* temp copy of flag */
373: #ifdef NBSM
374: dflag = (bp->b_lock == SSLOCK) ? iflag :
375: (bsp?bsp->bs_flags:0);
376: /* temp copy of device flags */
377: #else
378: dflag = iflag; /* same as iflag */
379: #endif
380: switch (st->s_ord) { /* do function */
381: case D_START:
382: if (bp->b_mode == BSC_CL2)
383: bp->b_mode = BSC_CLOSED;
384: if (bp->b_mode == BSC_CLOSED)
385: goto closedoor;
386:
387: #ifdef NBSM
388: if (bp->b_lock == SSLOCK)
389: x = bp->b_sema;
390: else x = (bsp)?bsp->bs_sema:BSC_DDONE;
391: #else
392: x = bp->b_sema;
393: #endif
394: if (x & BSC_DBUSY) {
395: x = spl8();
396: bp->b_alarm = PSMTPS;
397: bp->b_alenb = 1;
398: splx(x);
399: goto closedoor;
400: }
401: bp->b_tmperr = 0; /* zero tmperrs */
402: if (iflag & BSCMPT) { /* if multipoint, */
403: bp->b_hlflgs |= BSC_POLLWT;
404: bp->b_state = MPT;
405: } else
406: bp->b_state = PTPT;
407: x = spl8();
408: bp->b_sema |= BSC_PDONE;
409: bp->b_sema &= ~BSC_PBUSY;
410: #ifdef NBSM
411: if (bp->b_lock != SSLOCK && bsp) {
412: bsp->bs_sema |= BSC_PDONE;
413: bsp->bs_sema &= ~BSC_PBUSY;
414: bsp = NULL;
415: bp->b_psmbsy = -1;
416: }
417: #endif
418: splx(x);
419: break;
420:
421: case D_PTPT:
422: /* If we are to write, SNDBID; read, WTPTPT;
423: * otherwise, delay.
424: */
425: /* If ready to write, check initial bid */
426: for (x=0; x<sizeof bp->b_iocin.b_termid &&
427: bp->b_iocin.b_termid[x];
428: ++x);
429: if (bp->b_mode == BSC_WRITE) {
430: bp->b_state = SNDBID;
431: bp->b_sema &= ~BSC_PDONE;
432: bp->b_sema |= BSC_PBUSY;
433: ascbid[0].xnum = x;
434: ebcbid[0].xnum = x;
435: ascbid[0].xptr = bp->b_iocin.b_termid;
436: ebcbid[0].xptr = bp->b_iocin.b_termid;
437: break;
438: }
439: if (bp->b_mode == BSC_READ) {
440: bp->b_state = WTPTPT;
441: bp->b_sema &= ~BSC_PDONE;
442: bp->b_sema |= BSC_PBUSY;
443: ascbak[0].xnum = x;
444: ebcbak[0].xnum = x;
445: ascbak[0].xptr = bp->b_iocin.b_termid;
446: ebcbak[0].xptr = bp->b_iocin.b_termid;
447: break;
448: }
449: /* else */
450: wakeup ((caddr_t)bp->b_buffer);
451: x = spl8();
452: bp->b_alarm = PSMTPS; /* wait 1 sec*/
453: bp->b_alenb = 1;
454: splx(x);
455: goto closedoor;
456:
457: case D_CKHOST:
458: /* 1. Set expected response to odd ackn.
459: * Null our term id field - send once only.
460: * 2. If we are supposed to check host id,
461: * compare received vs. given.
462: * If different, HSTERR.
463: * Normally, CKXMIT.
464: */
465: bp->b_hlflgs |= BSC_ACK; /* set odd */
466: bp->b_iocin.b_termid[0] = '\0';
467: bp->b_state = ((!(iflag & BSCCKHOST))
468: || bp->b_iocin.b_hostid[0] == '\0'
469: || bsccmp(bp->b_iocin.b_hostid,
470: bp->b_iocout.b_hostid)==0) ?
471: CKXMIT : HSTERR;
472: break;
473:
474: case D_CKXMIT:
475: /* Check transmit buffer. If empty,
476: * wait up to 2 seconds; if still
477: * empty, send TTD.
478: */
479: if (!(dflag & BSC_FULL)) { /* buffer empty */
480: if (bp->b_alarm <= -100 &&
481: ++bp->b_bscto >= 2*PSMTPS) {
482: bp->b_bscto = 0;
483: bp->b_state = SNDTTD;
484: break;
485: }
486: x = spl8();
487: bp->b_alarm = 1; /* wait 1 tick */
488: bp->b_alenb = 1; /* enable alarm */
489: splx(x);
490: goto closedoor;
491: }
492: /* buffer full */
493: bp->b_bscto = 0;
494: bp->b_state = SNDTXT; /* send what we got */
495: if (iflag & BSCASCII) { /* set up text list*/
496: asctxt[0] = (dflag&BSC_XTRN)?
497: ((dflag&BSC_XSOH)?atsoh:atstx):
498: ((dflag&BSC_XSOH)?asoh : astx);
499: #ifdef NBSM
500: if (bp->b_lock != SSLOCK) {
501: asctxt[1].xnum =
502: X_CRC|bsp->bs_size;
503: asctxt[1].xptr =
504: bsp->bs_buf;
505: } else {
506: #endif
507: asctxt[1].xnum =
508: X_CRC|bp->b_bsize;
509: asctxt[1].xptr =
510: bp->b_buffer;
511: #ifdef NBSM
512: }
513: #endif
514: asctxt[2].xnum = (dflag&BSC_XTRN)?1:0;
515: asctxt[3] =
516: (dflag&BSC_XLAST)?aetx : aetb;
517: #ifdef MANCRC
518: asctxt[4].xptr = bp->b_crc;
519: #endif
520: } else {
521: ebctxt[0] = (dflag&BSC_XTRN)?
522: ((dflag&BSC_XSOH)?etsoh:etstx):
523: ((dflag&BSC_XSOH)?esoh : estx);
524: #ifdef NBSM
525: if (bp->b_lock != SSLOCK) {
526: ebctxt[1].xnum =
527: X_CRC|bsp->bs_size;
528: ebctxt[1].xptr =
529: bsp->bs_buf;
530: } else {
531: #endif
532: ebctxt[1].xnum =
533: X_CRC|bp->b_bsize;
534: ebctxt[1].xptr =
535: bp->b_buffer;
536: #ifdef NBSM
537: }
538: #endif
539: ebctxt[2].xnum = (dflag&BSC_XTRN)?1:0;
540: ebctxt[3] =
541: (dflag&BSC_XLAST)?eetx : eetb;
542: #ifdef MANCRC
543: ebctxt[4].xptr = bp->b_crc;
544: #endif
545: }
546: break;
547:
548: case D_RGTACK:
549: if (bp->b_class1 == ((iflag&BSC_ACK)?C_AK1:C_AK0))
550: bp->b_state = XFLIP;
551: else
552: bp->b_state =
553: (++bp->b_tmperr >
554: (bp->b_iocin.b_nretry&0xff))
555: ? RTYERR : WNGACK;
556: break;
557:
558: case D_XFLIP:
559: ++bp->b_iocout.b_blks; /* tally # blks sent */
560: bp->b_tmperr = 0; /* zero tmp error ct */
561: bp->b_hlflgs ^= BSC_ACK;
562: #ifdef NBSM
563: if (bp->b_lock != SSLOCK) {
564: bsp->bs_flags &= ~BS_FULL;
565: wakeup ((caddr_t)&bsp->bs_flags);
566: } else {
567: #endif
568: bp->b_hlflgs &= ~BSC_FULL;
569: wakeup ((caddr_t)bp->b_buffer);
570: #ifdef NBSM
571: }
572: #endif
573: bp->b_state = (dflag & BSC_XLAST)? DONE : CKXMIT;
574: break;
575:
576: case D_FASTACK:
577: /* Fast acknowledge (text reply to text).
578: * Wait for write caller to finish
579: * as indicated by LAST flag going
580: * off. Wait up to 5 seconds.
581: * When done, go check bcc on text.
582: */
583: if (bp->b_alarm <= -100) { /* Timeout. */
584: if (dflag & BSC_XLAST /* waiting on*/
585: /* end of wrt*/
586: && ++bp->b_bscto <= 5*PSMTPS) {
587: x = spl8();
588: bp->b_alarm = 1;
589: bp->b_alenb = 1;
590: splx(x);
591: goto closedoor;
592: }
593: bp->b_bscto = 0;
594: bp->b_state = CKBCC; /* done write*/
595: #ifdef NBSM
596: if (bp->b_lock != SSLOCK)
597: bsp->bs_mode = BS_READ;
598: else
599: #endif
600: bp->b_mode = BS_READ;
601: break;
602: }
603: /* 1st time thru -- terminate write */
604: bp->b_tmperr = 0;
605: ++bp->b_iocout.b_blks;
606: bp->b_mode = BSC_IDLE;
607: #ifdef NBSM
608: if (bp->b_lock != SSLOCK) {
609: bsp->bs_mode = BS_IDLE;
610: bsp->bs_flags &= ~BS_FULL;
611: wakeup ((caddr_t)&bsp->bs_flags);
612: } else{
613: #endif
614: bp->b_hlflgs &= ~BSC_FULL;
615: wakeup ((caddr_t)bp->b_buffer);
616: #ifdef NBSM
617: }
618: #endif
619: bp->b_hlflgs |= BSC_ACK;
620: x = spl8();
621: bp->b_alarm = 1;
622: bp->b_alenb = 1;
623: splx(x);
624: goto closedoor;
625:
626: case D_CKNRTY:
627: ++bp->b_iocout.b_nretry; /* tally retries */
628: bp->b_state =
629: (++bp->b_tmperr >
630: (bp->b_iocin.b_nretry&0xff))?
631: RTYERR:SNDTXT;
632: break;
633:
634: case D_CKNWAK:
635: ++bp->b_iocout.b_nwack; /* tally wacks */
636: bp->b_state =
637: (++bp->b_tmperr >
638: (bp->b_iocin.b_nwack&0xff))?
639: WAKERR:WNGACK;
640: break;
641:
642: case D_CHKRVI:
643: bp->b_state = (iflag&BSCRVIABT)? RVIERR : XFLIP;
644: break;
645:
646: case D_CORACK:
647: bp->b_state = (bp->b_class1==
648: ((iflag&BSC_ACK)?C_AK1:C_AK0))
649: ? XFLIP : SNDTXT;
650: break;
651:
652: case D_CKNRT2:
653: ++bp->b_iocout.b_nretry; /* tally retries */
654: bp->b_state =
655: (++bp->b_tmperr >
656: (bp->b_iocin.b_nretry&0xff))?
657: RTYERR:RTOENQ;
658: break;
659:
660: case D_CKNBID:
661: ++bp->b_iocout.b_nbid;
662: if (!(iflag & BSCPRIM) &&
663: bp->b_class1 == C_ENQ) {
664: bp->b_state = CONTND;
665: break;
666: }
667: if (bp->b_iocin.b_nbid == 0 ||
668: (bp->b_iocin.b_nbid&0xff) >
669: ++bp->b_tmperr) {
670: bp->b_state = SNDBID;
671: break;
672: }
673: bp->b_state = BIDERR;
674: break;
675:
676: case F_SETODD:
677: if (!(iflag & BSCMPT))
678: bp->b_iocin.b_termid[0] = '\0';
679: bp->b_hlflgs |= BSC_ACK;
680: asclst[0].xptr = aack0.xptr;
681: ebclst[0].xptr = eack0.xptr;
682: bp->b_rdflag = 0; /* reset idle t/o */
683: #ifdef NBSM
684: if (bp->b_lock != SSLOCK) /* m/station*/
685: bsp->bs_rdflg = 0;
686: #endif
687: break;
688:
689: case F_SETLST:
690: /* Set ebclst or asclst to point to proper
691: * acknowledgement message (even/odd)
692: */
693: if (iflag & BSC_ACK) { /* next msg odd */
694: /* Response to last should be ACK0 */
695: asclst[0].xptr = aack0.xptr;
696: ebclst[0].xptr = eack0.xptr;
697: } else { /* next msg even */
698: /* Response to last should be ACK1 */
699: asclst[0].xptr = aack1.xptr;
700: ebclst[0].xptr = eack1.xptr;
701: }
702: break;
703:
704: case D_CKRDY:
705: /* If buffer available,
706: * send acknowledgement.
707: * Otherwise, wait up to 2 seconds for it to
708: * become available. If no luck, DELAY.
709: */
710: if ( (bp->b_lock == SSLOCK &&
711: bp->b_mode == BSC_WRITE &&
712: (bp->b_sema & BSC_FACK)) ||
713: (bp->b_lock != SSLOCK &&
714: bsp->bs_mode == BS_WRITE &&
715: (bsp->bs_sema & BSC_FACK)) ) {
716: bp->b_hlflgs |= BSC_ACK;
717: bp->b_state = CKXMIT;
718: bp->b_bscto = 0;
719: break;
720: }
721: if (!(dflag & BSC_FULL)) {
722: bp->b_state = SETLST;
723: bp->b_bscto = 0;
724: break;
725: }
726: if (bp->b_alarm <= -100 &&
727: ++bp->b_bscto >= TWAIT*PSMTPS) {/*time out*/
728: bp->b_bscto = 0;
729: bp->b_state = DELAY;
730: break;
731: }
732: x = spl8();
733: bp->b_alarm = 1; /* pause a tick */
734: bp->b_alenb = 1; /* enable alarm */
735: splx(x);
736: goto closedoor;
737:
738: /* Check text response.
739: * If CRC error or overrun (block too big), send a NAK,
740: * unless we've already sent the limit, in which case
741: * go to error state NAKERR or TOOBIG.
742: * For no error case, count blocks, set response xmit
743: * list element, flip even/odd indicator, new state is
744: * CKRDY. Also mark buffer full and possibly last (if
745: * received ETX). Wake sleepers.
746: */
747: case D_CKBCC:
748: if ((iflag & BSC_CRCERR) ||
749: (bp->b_bsize > BSCMBLK)) {
750: ++bp->b_iocout.b_nnak;
751: bp->b_hlflgs &= ~BSC_CRCERR;
752: bp->b_state = SNDNAK;
753: if (++bp->b_tmperr >
754: (bp->b_iocin.b_nnak&0xff))
755: bp->b_state =
756: (bp->b_bsize > BSCMBLK)?
757: TOOBIG : NAKERR;
758: break;
759: }
760: bp->b_tmperr = 0; /* reset err cnt*/
761: ++bp->b_iocout.b_blks; /* count blocks */
762: bp->b_state = CKRDY;
763: bp->b_hlflgs ^= BSC_ACK;
764: bp->b_hlflgs |= BSC_FULL;
765: if (iflag & BSC_XTRN) /* transp.? */
766: #ifdef NBSM
767: if (bp->b_lock != SSLOCK)
768: bsp->bs_err = BSCTXP;
769: else
770: #endif
771: bp->b_iocout.b_flags = BSCTXP;
772: #ifdef NBSM
773: if (bp->b_lock != SSLOCK) {
774: if (bsp->bs_mode == BS_FREE) {
775: bp->b_hlflgs &= ~BSC_FULL;
776: break;
777: }
778: bsp->bs_flags |= BS_FULL;
779: wakeup ((caddr_t)&bsp->bs_flags);
780: break;
781: }
782: #endif
783: wakeup ((caddr_t)bp->b_buffer);
784: break;
785:
786: case D_CKNTTD:
787: ++bp->b_iocout.b_nttd;
788: bp->b_state =
789: (++bp->b_tmperr >
790: (bp->b_iocin.b_nttd&0xff))?
791: TTDERR:SNDNAK;
792: break;
793:
794: case D_CKABTM:
795: bp->b_state = RDONE;
796: #ifdef NBSM
797: if (bp->b_lock != SSLOCK && bsp &&
798: bsp->bs_mode == BS_FREE)
799: break;
800: #endif
801: bp->b_hlflgs |= BSC_XLAST;
802: if (bp->b_lock != SSLOCK && bsp) {
803: bsp->bs_flags |= BS_LAST;
804: wakeup ((caddr_t)&bsp->bs_flags);
805: break;
806: }
807: wakeup ((caddr_t)bp->b_buffer);
808: break;
809:
810: case D_CKMPT:
811: if (bp->b_mode == BSC_CLOSED)
812: goto closedoor;
813: if (bp->b_class1 == C_EOT) { /* oops */
814: bp->b_hlflgs |= BSC_POLLWT;
815: bp->b_state = MPT;
816: break;
817: }
818: /* First, check out validity */
819: /* First two characters must be same, */
820: /* Next two must also, */
821: /* And first two must be our poll or */
822: /* select address */
823: if ((bp->b_iocout.b_hostid[0] !=
824: bp->b_iocout.b_hostid[1]) ||
825: ((bp->b_iocout.b_hostid[0] !=
826: bp->b_iocin.b_termid[0]) &&
827: (bp->b_iocout.b_hostid[0] !=
828: bp->b_iocin.b_termid[1])) ||
829: (bp->b_iocout.b_hostid[2] !=
830: bp->b_iocout.b_hostid[3])) {
831: /* Not our address, or invalid */
832: bp->b_hlflgs |= BSC_POLLWT;
833: bp->b_state = MPT;
834: break;
835: }
836: /* Check subdevice address */
837: if (bp->b_iocout.b_hostid[2] ==
838: ((iflag&BSCASCII)?0x22:0x7f)) {
839: /* general poll */
840: #ifdef NBSM
841: if (bp->b_lock != SSLOCK) {
842: for (bsp = bscsubs[dev];
843: bsp < &bscsubs[dev][NBSSUB];
844: ++bsp) {
845: if (bsp->bs_mode ==
846: BS_WRITE)
847: goto gotone;
848: }
849: /* Gen Poll, nothing ready */
850: bp->b_hlflgs |= BSC_POLLWT;
851: bp->b_state = POLEOT;
852: break;
853: }
854: #endif
855: goto gottwo;
856: }
857: /* not general poll ... check specific */
858: #ifdef NBSM
859: if (bp->b_lock == SSLOCK) {
860: #endif
861: if(bp->b_iocout.b_hostid[2] ==
862: ((iflag&BSCASCII)?
863: 0x20:0x40))
864: goto gottwo;
865: #ifdef NBSM
866: } else {
867: for (x = 0;
868: x < NBSSUB; ++x)
869: if (bp->b_iocout.b_hostid[2] ==
870: ((iflag&BSCASCII)?
871: ascdev:ebcdev)[x]) {
872: bsp = &bscsubs[dev][x];
873: goto gotone;
874: }
875: }
876: #endif
877: /* don't have that device */
878: bp->b_hlflgs |= BSC_POLLWT;
879: bp->b_state = POLEOT;
880: break;
881:
882: #ifdef NBSM
883: gotone: bp->b_psmbsy = bsp - bscsubs[dev];
884: dflag = bsp->bs_flags;
885: #endif
886: /* Are we being Polled? */
887: gottwo:
888: if (bp->b_iocout.b_hostid[0] ==
889: bp->b_iocin.b_termid[0]) { /* Poll? */
890: #ifdef NBSM
891: if ((bp->b_lock != SSLOCK &&
892: bsp->bs_mode == BS_WRITE) ||
893: (bp->b_lock == SSLOCK &&
894: bp->b_mode == BSC_WRITE)) {
895: if (bp->b_lock != SSLOCK) {
896: bsp->bs_sema &=
897: ~BSC_PDONE;
898: bsp->bs_sema |=
899: BSC_PBUSY;
900: }
901: #else
902: if (bp->b_mode == BSC_WRITE) {
903: #endif
904: /* Polled, ready to send */
905: bp->b_sema &= ~BSC_PDONE;
906: bp->b_sema |= BSC_PBUSY;
907: bp->b_state = CKXMIT;
908: bp->b_hlflgs |= BSC_ACK;
909: bp->b_hlflgs &= ~BSC_POLLWT;
910: } else {
911: /* Polled, not ready */
912: bp->b_hlflgs |= BSC_POLLWT;
913: bp->b_state = POLEOT;
914: bp->b_psmbsy = -1;
915: }
916: break;
917: }
918: /* Otherwise, we've been selected */
919: #ifdef NBSM
920: if ((!(bp->b_hlflgs & BSC_FULL)) &&
921: (bp->b_lock != SSLOCK &&
922: bsp->bs_mode != BS_WRITE) ||
923: (bp->b_lock == SSLOCK &&
924: (bp->b_mode == BSC_READ ||
925: bp->b_mode == BSC_IDLE))) {
926: if (bp->b_lock != SSLOCK) {
927: bsp->bs_sema &= ~BSC_PDONE;
928: bsp->bs_sema |= BSC_PBUSY;
929: }
930: #else
931: if ((!(bp->b_hlflgs & BSC_FULL)) &&
932: (bp->b_mode == BSC_IDLE ||
933: bp->b_mode == BSC_READ)) {
934: #endif
935: bp->b_sema &= ~BSC_PDONE;
936: bp->b_sema |= BSC_PBUSY;
937: bp->b_state = SETODD;
938: bp->b_hlflgs &= ~BSC_POLLWT;
939: #ifdef NBSM
940: if (bp->b_lock != SSLOCK) {
941: if (bsp->bs_mode != BS_FREE)
942: bsp->bs_mode = BS_READ;
943: } else
944: #endif
945: bp->b_mode = BSC_READ;
946: } else { /* Write Contention */
947: bp->b_hlflgs |= BSC_POLLWT;
948: bp->b_state = MPTCNT;
949: bp->b_psmbsy = -1;
950: }
951: break;
952:
953: default: panic("bsc: unknown function#\n");
954: }
955: break;
956:
957: case 's': /* transmit */
958: {
959: register struct xlist *xp;
960:
961: xp = ((bp->b_hlflgs&BSCASCII)?asclist:ebclist)
962: [st->s_ord];
963: bp->b_txlst[1] = xp[0];
964: bp->b_txlst[2] = xp[1];
965: bp->b_txlst[3] = xp[2];
966: bp->b_txlst[4] = xp[3];
967: bp->b_txlst[5] = xp[4];
968: bp->b_txlst[6] = xp[5];
969: if (bp->b_trace > 1)
970: btxtrc(dev, xp, bp->b_state);
971: bscxmit (dev, (int)st->s_next); /*send list */
972: /* b_state will be updated at end of xmit */
973: if (states[st->s_next].s_type == 'r')
974: bp->b_rclptr = rlist[states[st->s_next].s_ord];
975: x = spl8(); /* set the alarm clock */
976: bp->b_alarm = ((st->s_ord == X_TXT)?BSCMBLK/300 + 2:
977: 2)*PSMTPS;
978: bp->b_alenb = 1; /* enable the alarm clock */
979: splx(x);
980: goto closedoor;
981: }
982:
983: case 'r': /* receive */
984: /* 1. Set receive list pointer.
985: * 2. Set alarm for 4 seconds
986: * The alarm will set the new state to st->s_next.
987: */
988: bp->b_rclptr = rlist[st->s_ord];
989: x = spl8();
990: bp->b_alarm = 4*PSMTPS;
991: bp->b_alenb = 1; /* enable clock */
992: splx(x);
993: /* b_state will be updated at end of receive */
994: goto closedoor;
995:
996: case 'e': /* error! */
997: /*
998: * 1. Wake any process waiting on the buffer.
999: * 2. If error given, set error bit and save
1000: * error number.
1001: * 3. Select next state from s_next.
1002: */
1003: #ifdef NBSM
1004: if (bp->b_lock != SSLOCK && bsp)
1005: wakeup ((caddr_t)&bsp->bs_flags);
1006: else
1007: #endif
1008: wakeup ((caddr_t)bp->b_buffer);
1009:
1010: if (bp->b_mode >= BSC_CL1) { /* closing */
1011: bp->b_state = START;
1012: break;
1013: }
1014:
1015: if (st->s_ord) { /* if error given, */
1016: #ifdef NBSM
1017: if (bp->b_lock != SSLOCK && bsp) {
1018: bsp->bs_flags &= ~BS_FULL;
1019: bsp->bs_flags |= BS_ERR;/* set err */
1020: bsp->bs_err = st->s_ord;
1021: } else {
1022: #endif
1023: bp->b_hlflgs &= ~BSC_FULL;
1024: bp->b_hlflgs |= BSC_ERR;/* set err */
1025: bp->b_iocout.b_flags = st->s_ord;
1026: #ifdef NBSM
1027: }
1028: #endif
1029: }
1030: bp->b_state = st->s_next; /* select next state */
1031: break;
1032:
1033: default:
1034: panic ("bsc: unknown state type!\n");
1035: }
1036: };
1037: closedoor: /* Unlock door and leave */
1038: bp->b_sema &= ~BSC_INPSM;
1039: }
1040:
1041: bscpto (dev) /* process timeout */
1042: caddr_t dev;
1043: {
1044: register struct bsc *bp;
1045: register struct state *st;
1046: register struct bscsub *bpsub;
1047: register int i;
1048:
1049: bp = &bsc[(dev_t)dev]; /* current dev info */
1050: st = &states[bp->b_state]; /* current state entry */
1051:
1052: if (bp->b_mode == BSC_CLOSED) /* closed - no further actions! */
1053: return;
1054: if (bp->b_sema & BSC_INPSM) { /* PSM running? */
1055: goto out;
1056: }
1057:
1058: bsckdsr((dev_t)dev,bp); /* local chk for DSR */
1059: if (!(bp->b_hlflgs & BSC_DSR)) {
1060: #ifdef NBSM
1061: if (bp->b_lock != SSLOCK) {
1062: for (i=0; i < NBSSUB; i++) {
1063: bpsub = &bscsubs[(dev_t)dev][i];
1064: bpsub->bs_flags |= BS_ERR;
1065: bpsub->bs_flags &= ~BS_FULL;
1066: bpsub->bs_err = BSCNDSR;
1067: wakeup ((caddr_t)&bpsub->bs_flags);
1068: }
1069: goto out;
1070: }
1071: #endif
1072: bp->b_hlflgs |= BSC_ERR;
1073: bp->b_hlflgs &= ~BSC_FULL;
1074: bp->b_iocout.b_flags = BSCNDSR;
1075: wakeup ((caddr_t)bp->b_buffer);
1076: goto out;
1077: }
1078:
1079: /* check for rd idle timeout */
1080: #ifdef NBSM
1081: if(bp->b_lock != SSLOCK){
1082: for(i=0;i<NBSSUB;i++){
1083: bpsub = &bscsubs[(dev_t)dev][i];
1084: if(bpsub->bs_mode == BS_READ && bpsub->bs_rdflg &&
1085: --bpsub->bs_rdflg == 0 ){
1086: bpsub->bs_err = BSCRXTO;
1087: bpsub->bs_flags |= BS_ERR;
1088: bpsub->bs_mode = BS_IDLE;
1089: wakeup ((caddr_t)&bpsub->bs_flags);
1090: goto done;
1091: }
1092: }
1093: } else {
1094: #endif
1095: if (bp->b_rdflag && --bp->b_rdflag == 0 && bp->b_mode == BSC_READ) {
1096: bp->b_rclptr = 0; /* reset receiver */
1097: brxres((dev_t)dev);
1098: bp->b_iocout.b_flags = BSCRXTO; /* read timeout */
1099: bp->b_mode = BSC_IDLE; /* error state, idle mode */
1100: bp->b_hlflgs |= BSC_ERR;
1101: bp->b_state = START;
1102: wakeup ((caddr_t)bp->b_buffer);
1103: goto done;
1104: }
1105: #ifdef NBSM
1106: }
1107: #endif
1108: if ((!bp->b_alenb) || (--(bp->b_alarm) > 0)) {
1109: /* alarm has yet to go off - sleep */
1110: goto out;
1111: }
1112: bp->b_alenb = 0; /* disable alarm */
1113:
1114: switch (st->s_type) { /* what to do depends on state */
1115: case 's': /* send time out ... modem dead! */
1116: bp->b_state = XTO; /* set state to xmit timeout */
1117: break;
1118:
1119: case 'r': /* receive timeout - take s_next */
1120: if (bp->b_trace) /* if tracing, show rcv t/o */
1121: bsctr ((dev_t)dev, C_RTO, 'c'); /* reCv'd TimeOut */
1122: bp->b_state = st->s_next; /* timeout state */
1123: bp->b_class1 = C_RTO; /* timeout data class */
1124: bp->b_rclptr = 0; /* reset receiver */
1125: brxres((dev_t)dev);
1126: break;
1127:
1128: case 'd': /* function delay */
1129: bp->b_alarm = -100; /* indicate second time through */
1130: break;
1131:
1132: default:
1133: panic ("bsc: timeout in unknown state!\n");
1134: break;
1135: }
1136: done:
1137: bscpsm ((dev_t)dev); /* restart processing */
1138:
1139: out: /* set up next call to bscpto */
1140: timeout (bscpto, dev, PSMTICK); /* timeout again */
1141: }
1142:
1143: /*
1144: * Compare two strings -- return zero if match, non-zero if fail
1145: */
1146: bsccmp(s1,s2)
1147: register char *s1, *s2;
1148: {
1149: while (*s1)
1150: if (*s1++ != *s2++)
1151: return 1;
1152: return (int) *s2;
1153: }
1154:
1155: /*
1156: * NAME
1157: * btxtrc - trace tx data
1158: * SYNOPSIS
1159: * btxtrc(dev,xlptr,state)
1160: * dev_t dev;
1161: * int state;
1162: * struct xlist *xlptr;
1163: * ALGORITHM
1164: * For each transmit list element, call bsctr to trace the
1165: * transmit data (type is 'x'; supply xlen and xptr)
1166: */
1167: btxtrc(dev,xlptr,state)
1168: register dev_t dev;
1169: register int state;
1170: register struct xlist *xlptr;
1171: {
1172: while (xlptr->xptr) {
1173: bsctr(dev,state,'x',(short)xlptr->xnum,xlptr->xptr);
1174: ++xlptr;
1175: }
1176: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.