|
|
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.