Annotation of cci/sys/bsc/bscpsm.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.