|
|
1.1 ! root 1: /* $Header$ */ ! 2: /* $Source$ */ ! 3: #ifndef lint ! 4: static char *rcsid = "$Header/**/$"; ! 5: #endif lint ! 6: #define _XEBEC_PG static ! 7: ! 8: #include "tp_states.h" ! 9: ! 10: static struct act_ent { ! 11: int a_newstate; ! 12: int a_action; ! 13: } statetable[] = { {0,0}, ! 14: #include "tp_states.init" ! 15: }; ! 16: ! 17: /* %W% (Berkeley) %G% */ ! 18: #include "param.h" ! 19: #include "socket.h" ! 20: #include "socketvar.h" ! 21: #include "protosw.h" ! 22: #include "mbuf.h" ! 23: #include "time.h" ! 24: #include "errno.h" ! 25: #include "../netiso/tp_param.h" ! 26: #include "../netiso/tp_stat.h" ! 27: #include "../netiso/tp_pcb.h" ! 28: #include "../netiso/tp_tpdu.h" ! 29: #include "../netiso/argo_debug.h" ! 30: #include "../netiso/tp_trace.h" ! 31: #include "../netiso/iso_errno.h" ! 32: #include "../netiso/tp_seq.h" ! 33: #include "../netiso/cons.h" ! 34: ! 35: #define DRIVERTRACE TPPTdriver ! 36: #define sbwakeup(sb) sowakeup(p->tp_sock, sb); ! 37: #define MCPY(d, w) (d ? m_copym(d, 0, (int)M_COPYALL, w): 0) ! 38: ! 39: static trick_hc = 1; ! 40: ! 41: int tp_emit(), ! 42: tp_goodack(), tp_goodXack(), ! 43: tp_stash() ! 44: ; ! 45: void tp_indicate(), tp_getoptions(), ! 46: tp_soisdisconnecting(), tp_soisdisconnected(), ! 47: tp_recycle_tsuffix(), ! 48: tp_etimeout(), tp_euntimeout(), ! 49: tp_euntimeout_lss(), tp_ctimeout(), ! 50: tp_cuntimeout(), tp_ctimeout_MIN(), ! 51: tp_freeref(), tp_detach(), ! 52: tp0_stash(), tp0_send(), ! 53: tp_netcmd(), tp_send() ! 54: ; ! 55: ! 56: typedef struct tp_pcb tpcb_struct; ! 57: ! 58: ! 59: ! 60: typedef tpcb_struct tp_PCB_; ! 61: ! 62: #include "tp_events.h" ! 63: ! 64: _XEBEC_PG int _Xebec_action(a,e,p) ! 65: int a; ! 66: struct tp_event *e; ! 67: tp_PCB_ *p; ! 68: { ! 69: switch(a) { ! 70: case -1: return tp_protocol_error(e,p); ! 71: case 0x1: ! 72: { ! 73: (void) tp_emit(DC_TPDU_type, p, 0, 0, MNULL); ! 74: } ! 75: break; ! 76: case 0x2: ! 77: { ! 78: # ifdef TP_DEBUG ! 79: if( e->ev_number != AK_TPDU ) ! 80: printf("TPDU 0x%x in REFWAIT!!!!\n", e->ev_number); ! 81: # endif TP_DEBUG ! 82: } ! 83: break; ! 84: case 0x3: ! 85: { ! 86: /* oh, man is this grotesque or what? */ ! 87: (void) tp_goodack(p, e->ev_union.EV_AK_TPDU.e_cdt, e->ev_union.EV_AK_TPDU.e_seq, e->ev_union.EV_AK_TPDU.e_subseq); ! 88: /* but it's necessary because this pseudo-ack may happen ! 89: * before the CC arrives, but we HAVE to adjust the ! 90: * snduna as a result of the ack, WHENEVER it arrives ! 91: */ ! 92: } ! 93: break; ! 94: case 0x4: ! 95: { ! 96: tp_detach(p); ! 97: } ! 98: break; ! 99: case 0x5: ! 100: { ! 101: p->tp_refp->tpr_state = REF_OPEN; /* has timers ??? */ ! 102: } ! 103: break; ! 104: case 0x6: ! 105: { ! 106: IFTRACE(D_CONN) ! 107: tptrace(TPPTmisc, "CR datalen data", e->ev_union.EV_CR_TPDU.e_datalen, e->ev_union.EV_CR_TPDU.e_data,0,0); ! 108: ENDTRACE ! 109: IFDEBUG(D_CONN) ! 110: printf("CR datalen 0x%x data 0x%x", e->ev_union.EV_CR_TPDU.e_datalen, e->ev_union.EV_CR_TPDU.e_data); ! 111: ENDDEBUG ! 112: p->tp_refp->tpr_state = REF_OPEN; /* has timers */ ! 113: p->tp_fcredit = e->ev_union.EV_CR_TPDU.e_cdt; ! 114: ! 115: if (e->ev_union.EV_CR_TPDU.e_datalen > 0) { ! 116: /* n/a for class 0 */ ! 117: ASSERT(p->tp_Xrcv.sb_cc == 0); ! 118: sbappendrecord(&p->tp_Xrcv, e->ev_union.EV_CR_TPDU.e_data); ! 119: e->ev_union.EV_CR_TPDU.e_data = MNULL; ! 120: } ! 121: } ! 122: break; ! 123: case 0x7: ! 124: { ! 125: IncStat(ts_tp0_conn); ! 126: IFTRACE(D_CONN) ! 127: tptrace(TPPTmisc, "Confiming", p, 0,0,0); ! 128: ENDTRACE ! 129: IFDEBUG(D_CONN) ! 130: printf("Confirming connection: p" ); ! 131: ENDDEBUG ! 132: soisconnected(p->tp_sock); ! 133: (void) tp_emit(CC_TPDU_type, p, 0,0, MNULL) ; ! 134: p->tp_fcredit = 1; ! 135: } ! 136: break; ! 137: case 0x8: ! 138: { ! 139: IncStat(ts_tp4_conn); /* even though not quite open */ ! 140: IFTRACE(D_CONN) ! 141: tptrace(TPPTmisc, "Confiming", p, 0,0,0); ! 142: ENDTRACE ! 143: IFDEBUG(D_CONN) ! 144: printf("Confirming connection: p" ); ! 145: ENDDEBUG ! 146: soisconnecting(p->tp_sock); ! 147: if ((p->tp_rx_strat & TPRX_FASTSTART) && (p->tp_fcredit > 0)) ! 148: p->tp_cong_win = p->tp_fcredit; ! 149: p->tp_retrans = p->tp_Nretrans; ! 150: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_cc_ticks); ! 151: } ! 152: break; ! 153: case 0x9: ! 154: { ! 155: register struct tp_ref *r = p->tp_refp; ! 156: ! 157: IFDEBUG(D_CONN) ! 158: printf("event: CR_TPDU emit CC failed done " ); ! 159: ENDDEBUG ! 160: soisdisconnected(p->tp_sock); ! 161: tp_recycle_tsuffix( p ); ! 162: tp_freeref(r); ! 163: tp_detach(p); ! 164: } ! 165: break; ! 166: case 0xa: ! 167: { ! 168: int error; ! 169: struct mbuf *data = MNULL; ! 170: ! 171: IFTRACE(D_CONN) ! 172: tptrace(TPPTmisc, "T_CONN_req flags ucddata", (int)p->tp_flags, ! 173: p->tp_ucddata, 0, 0); ! 174: ENDTRACE ! 175: data = MCPY(p->tp_ucddata, M_WAIT); ! 176: if (data) { ! 177: IFDEBUG(D_CONN) ! 178: printf("T_CONN_req.trans m_copy cc 0x%x\n", ! 179: p->tp_ucddata); ! 180: dump_mbuf(data, "sosnd @ T_CONN_req"); ! 181: ENDDEBUG ! 182: } ! 183: ! 184: if (error = tp_emit(CR_TPDU_type, p, 0, 0, data) ) ! 185: return error; /* driver WON'T change state; will return error */ ! 186: ! 187: p->tp_refp->tpr_state = REF_OPEN; /* has timers */ ! 188: if(p->tp_class != TP_CLASS_0) { ! 189: p->tp_retrans = p->tp_Nretrans; ! 190: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_cr_ticks); ! 191: } ! 192: } ! 193: break; ! 194: case 0xb: ! 195: { ! 196: sbflush(&p->tp_Xrcv); /* purge non-delivered data data */ ! 197: if (e->ev_union.EV_DR_TPDU.e_datalen > 0) { ! 198: sbappendrecord(&p->tp_Xrcv, e->ev_union.EV_DR_TPDU.e_data); ! 199: e->ev_union.EV_DR_TPDU.e_data = MNULL; ! 200: } ! 201: /* must return no error, or disc data and reason can't be read */ ! 202: tp_indicate(T_DISCONNECT, p, 0); ! 203: tp_soisdisconnected(p); ! 204: if (p->tp_class != TP_CLASS_0) { ! 205: if (p->tp_state == TP_OPEN ) { ! 206: tp_euntimeout(p->tp_refp, TM_data_retrans); /* all */ ! 207: tp_cuntimeout(p->tp_refp, TM_retrans); ! 208: tp_cuntimeout(p->tp_refp, TM_inact); ! 209: tp_cuntimeout(p->tp_refp, TM_sendack); ! 210: } ! 211: tp_cuntimeout(p->tp_refp, TM_retrans); ! 212: if( e->ev_union.EV_DR_TPDU.e_sref != 0 ) ! 213: (void) tp_emit(DC_TPDU_type, p, 0, 0, MNULL); ! 214: } ! 215: } ! 216: break; ! 217: case 0xc: ! 218: { ! 219: if( e->ev_union.EV_DR_TPDU.e_sref != 0 ) ! 220: (void) tp_emit(DC_TPDU_type, p, 0, 0, MNULL); ! 221: /* reference timer already set - reset it to be safe (???) */ ! 222: tp_euntimeout(p->tp_refp, TM_reference); /* all */ ! 223: tp_etimeout(p->tp_refp, TM_reference, 0, 0, 0, (int)p->tp_refer_ticks); ! 224: } ! 225: break; ! 226: case 0xd: ! 227: { ! 228: tp_cuntimeout(p->tp_refp, TM_retrans); ! 229: tp_indicate(ER_TPDU, p, e->ev_union.EV_ER_TPDU.e_reason); ! 230: tp_soisdisconnected(p); ! 231: } ! 232: break; ! 233: case 0xe: ! 234: { ! 235: tp_cuntimeout(p->tp_refp, TM_retrans); ! 236: tp_soisdisconnected(p); ! 237: } ! 238: break; ! 239: case 0xf: ! 240: { ! 241: tp_indicate(ER_TPDU, p, e->ev_union.EV_ER_TPDU.e_reason); ! 242: tp_cuntimeout(p->tp_refp, TM_retrans); ! 243: tp_soisdisconnected(p); ! 244: } ! 245: break; ! 246: case 0x10: ! 247: { ! 248: tp_cuntimeout(p->tp_refp, TM_retrans); ! 249: tp_soisdisconnected(p); ! 250: } ! 251: break; ! 252: case 0x11: ! 253: { /* don't ask me why we have to do this - spec says so */ ! 254: (void) tp_emit(DR_TPDU_type, p, 0, E_TP_NO_SESSION, MNULL); ! 255: /* don't bother with retransmissions of the DR */ ! 256: } ! 257: break; ! 258: case 0x12: ! 259: { ! 260: tp_soisdisconnecting(p->tp_sock); ! 261: tp_indicate(ER_TPDU, p, e->ev_union.EV_ER_TPDU.e_reason); ! 262: tp_soisdisconnected(p); ! 263: tp_netcmd( p, CONN_CLOSE ); ! 264: } ! 265: break; ! 266: case 0x13: ! 267: { ! 268: if (p->tp_state == TP_OPEN) { ! 269: tp_euntimeout(p->tp_refp, TM_data_retrans); /* all */ ! 270: tp_cuntimeout(p->tp_refp, TM_inact); ! 271: tp_cuntimeout(p->tp_refp, TM_sendack); ! 272: } ! 273: tp_soisdisconnecting(p->tp_sock); ! 274: tp_indicate(ER_TPDU, p, e->ev_union.EV_ER_TPDU.e_reason); ! 275: p->tp_retrans = p->tp_Nretrans; ! 276: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_dr_ticks); ! 277: (void) tp_emit(DR_TPDU_type, p, 0, E_TP_PROTO_ERR, MNULL); ! 278: } ! 279: break; ! 280: case 0x14: ! 281: { ! 282: tp_cuntimeout(p->tp_refp, TM_retrans); ! 283: IncStat(ts_tp0_conn); ! 284: p->tp_fcredit = 1; ! 285: soisconnected(p->tp_sock); ! 286: } ! 287: break; ! 288: case 0x15: ! 289: { ! 290: IFDEBUG(D_CONN) ! 291: printf("trans: CC_TPDU in CRSENT state flags 0x%x\n", ! 292: (int)p->tp_flags); ! 293: ENDDEBUG ! 294: IncStat(ts_tp4_conn); ! 295: p->tp_fref = e->ev_union.EV_CC_TPDU.e_sref; ! 296: p->tp_fcredit = e->ev_union.EV_CC_TPDU.e_cdt; ! 297: p->tp_ackrcvd = 0; ! 298: if ((p->tp_rx_strat & TPRX_FASTSTART) && (e->ev_union.EV_CC_TPDU.e_cdt > 0)) ! 299: p->tp_cong_win = e->ev_union.EV_CC_TPDU.e_cdt; ! 300: tp_getoptions(p); ! 301: tp_cuntimeout(p->tp_refp, TM_retrans); ! 302: if (p->tp_ucddata) { ! 303: IFDEBUG(D_CONN) ! 304: printf("dropping user connect data cc 0x%x\n", ! 305: p->tp_ucddata->m_len); ! 306: ENDDEBUG ! 307: m_freem(p->tp_ucddata); ! 308: p->tp_ucddata = 0; ! 309: } ! 310: soisconnected(p->tp_sock); ! 311: if (e->ev_union.EV_CC_TPDU.e_datalen > 0) { ! 312: ASSERT(p->tp_Xrcv.sb_cc == 0); /* should be empty */ ! 313: sbappendrecord(&p->tp_Xrcv, e->ev_union.EV_CC_TPDU.e_data); ! 314: e->ev_union.EV_CC_TPDU.e_data = MNULL; ! 315: } ! 316: ! 317: (void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, MNULL); ! 318: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); ! 319: } ! 320: break; ! 321: case 0x16: ! 322: { ! 323: struct mbuf *data = MNULL; ! 324: int error; ! 325: ! 326: IncStat(ts_retrans_cr); ! 327: p->tp_cong_win = 1; ! 328: p->tp_ackrcvd = 0; ! 329: data = MCPY(p->tp_ucddata, M_NOWAIT); ! 330: if(p->tp_ucddata) { ! 331: IFDEBUG(D_CONN) ! 332: printf("TM_retrans.trans m_copy cc 0x%x\n", data); ! 333: dump_mbuf(p->tp_ucddata, "sosnd @ TM_retrans"); ! 334: ENDDEBUG ! 335: if( data == MNULL ) ! 336: return ENOBUFS; ! 337: } ! 338: ! 339: p->tp_retrans --; ! 340: if( error = tp_emit(CR_TPDU_type, p, 0, 0, data) ) { ! 341: p->tp_sock->so_error = error; ! 342: } ! 343: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_cr_ticks); ! 344: } ! 345: break; ! 346: case 0x17: ! 347: { ! 348: IncStat(ts_conn_gaveup); ! 349: p->tp_sock->so_error = ETIMEDOUT; ! 350: tp_indicate(T_DISCONNECT, p, ETIMEDOUT); ! 351: tp_soisdisconnected(p); ! 352: } ! 353: break; ! 354: case 0x18: ! 355: { ! 356: int error; ! 357: struct mbuf *data = MCPY(p->tp_ucddata, M_WAIT); ! 358: ! 359: if( error = tp_emit(CC_TPDU_type, p, 0, 0, data) ) { ! 360: p->tp_sock->so_error = error; ! 361: } ! 362: p->tp_retrans = p->tp_Nretrans; ! 363: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_cc_ticks); ! 364: } ! 365: break; ! 366: case 0x19: ! 367: { ! 368: int doack; ! 369: ! 370: /* ! 371: * Get rid of any confirm or connect data, so that if we ! 372: * crash or close, it isn't thought of as disconnect data. ! 373: */ ! 374: if (p->tp_ucddata) { ! 375: m_freem(p->tp_ucddata); ! 376: p->tp_ucddata = 0; ! 377: } ! 378: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); ! 379: tp_cuntimeout(p->tp_refp, TM_retrans); ! 380: soisconnected(p->tp_sock); ! 381: tp_getoptions(p); ! 382: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); ! 383: ! 384: /* see also next 2 transitions, if you make any changes */ ! 385: ! 386: doack = tp_stash(p, e); ! 387: IFDEBUG(D_DATA) ! 388: printf("tp_stash returns %d\n",doack); ! 389: ENDDEBUG ! 390: ! 391: if(doack) { ! 392: (void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, MNULL ); ! 393: tp_ctimeout(p->tp_refp, TM_sendack, (int)p->tp_keepalive_ticks); ! 394: } else ! 395: tp_ctimeout( p->tp_refp, TM_sendack, (int)p->tp_sendack_ticks); ! 396: ! 397: IFDEBUG(D_DATA) ! 398: printf("after stash calling sbwakeup\n"); ! 399: ENDDEBUG ! 400: } ! 401: break; ! 402: case 0x1a: ! 403: { ! 404: tp0_stash(p, e); ! 405: sbwakeup( &p->tp_sock->so_rcv ); ! 406: ! 407: IFDEBUG(D_DATA) ! 408: printf("after stash calling sbwakeup\n"); ! 409: ENDDEBUG ! 410: } ! 411: break; ! 412: case 0x1b: ! 413: { ! 414: int doack; /* tells if we must ack immediately */ ! 415: ! 416: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); ! 417: sbwakeup( &p->tp_sock->so_rcv ); ! 418: ! 419: doack = tp_stash(p, e); ! 420: IFDEBUG(D_DATA) ! 421: printf("tp_stash returns %d\n",doack); ! 422: ENDDEBUG ! 423: ! 424: if(doack) ! 425: (void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, MNULL ); ! 426: else ! 427: tp_ctimeout_MIN( p->tp_refp, TM_sendack, (int)p->tp_sendack_ticks); ! 428: ! 429: IFDEBUG(D_DATA) ! 430: printf("after stash calling sbwakeup\n"); ! 431: ENDDEBUG ! 432: } ! 433: break; ! 434: case 0x1c: ! 435: { ! 436: IFTRACE(D_DATA) ! 437: tptrace(TPPTmisc, "NIW seq rcvnxt lcredit ", ! 438: e->ev_union.EV_DT_TPDU.e_seq, p->tp_rcvnxt, p->tp_lcredit, 0); ! 439: ENDTRACE ! 440: IncStat(ts_dt_niw); ! 441: m_freem(e->ev_union.EV_DT_TPDU.e_data); ! 442: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); ! 443: (void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, MNULL ); ! 444: } ! 445: break; ! 446: case 0x1d: ! 447: { ! 448: if (p->tp_ucddata) { ! 449: m_freem(p->tp_ucddata); ! 450: p->tp_ucddata = 0; ! 451: } ! 452: (void) tp_goodack(p, e->ev_union.EV_AK_TPDU.e_cdt, e->ev_union.EV_AK_TPDU.e_seq, e->ev_union.EV_AK_TPDU.e_subseq); ! 453: tp_cuntimeout(p->tp_refp, TM_retrans); ! 454: ! 455: tp_getoptions(p); ! 456: soisconnected(p->tp_sock); ! 457: IFTRACE(D_CONN) ! 458: struct socket *so = p->tp_sock; ! 459: tptrace(TPPTmisc, ! 460: "called sosiconn: so so_state rcv.sb_sel rcv.sb_flags", ! 461: so, so->so_state, so->so_rcv.sb_sel, so->so_rcv.sb_flags); ! 462: tptrace(TPPTmisc, ! 463: "called sosiconn 2: so_qlen so_error so_rcv.sb_cc so_head", ! 464: so->so_qlen, so->so_error, so->so_rcv.sb_cc, so->so_head); ! 465: ENDTRACE ! 466: ! 467: tp_ctimeout(p->tp_refp, TM_sendack, (int)p->tp_keepalive_ticks); ! 468: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); ! 469: } ! 470: break; ! 471: case 0x1e: ! 472: { ! 473: if( p->tp_state == TP_AKWAIT ) { ! 474: if (p->tp_ucddata) { ! 475: m_freem(p->tp_ucddata); ! 476: p->tp_ucddata = 0; ! 477: } ! 478: tp_cuntimeout(p->tp_refp, TM_retrans); ! 479: tp_getoptions(p); ! 480: soisconnected(p->tp_sock); ! 481: tp_ctimeout(p->tp_refp, TM_sendack, (int)p->tp_keepalive_ticks); ! 482: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); ! 483: } ! 484: IFTRACE(D_XPD) ! 485: tptrace(TPPTmisc, "XPD tpdu accepted Xrcvnxt, e_seq datalen m_len\n", ! 486: p->tp_Xrcvnxt,e->ev_union.EV_XPD_TPDU.e_seq, e->ev_union.EV_XPD_TPDU.e_datalen, e->ev_union.EV_XPD_TPDU.e_data->m_len); ! 487: ENDTRACE ! 488: ! 489: p->tp_sock->so_state |= SS_RCVATMARK; ! 490: e->ev_union.EV_XPD_TPDU.e_data->m_flags |= M_EOR; ! 491: sbinsertoob(&p->tp_Xrcv, e->ev_union.EV_XPD_TPDU.e_data); ! 492: IFDEBUG(D_XPD) ! 493: dump_mbuf(e->ev_union.EV_XPD_TPDU.e_data, "XPD TPDU: tp_Xrcv"); ! 494: ENDDEBUG ! 495: tp_indicate(T_XDATA, p, 0); ! 496: sbwakeup( &p->tp_Xrcv ); ! 497: ! 498: (void) tp_emit(XAK_TPDU_type, p, p->tp_Xrcvnxt, 0, MNULL); ! 499: SEQ_INC(p, p->tp_Xrcvnxt); ! 500: } ! 501: break; ! 502: case 0x1f: ! 503: { ! 504: if( p->tp_Xrcv.sb_cc == 0 ) { ! 505: /* kludge for select(): */ ! 506: /* p->tp_sock->so_state &= ~SS_OOBAVAIL; */ ! 507: } ! 508: } ! 509: break; ! 510: case 0x20: ! 511: { ! 512: IFTRACE(D_XPD) ! 513: tptrace(TPPTmisc, "XPD tpdu niw (Xrcvnxt, e_seq) or not cdt (cc)\n", ! 514: p->tp_Xrcvnxt, e->ev_union.EV_XPD_TPDU.e_seq, p->tp_Xrcv.sb_cc , 0); ! 515: ENDTRACE ! 516: if( p->tp_Xrcvnxt != e->ev_union.EV_XPD_TPDU.e_seq ) ! 517: IncStat(ts_xpd_niw); ! 518: if( p->tp_Xrcv.sb_cc ) { ! 519: /* might as well kick 'em again */ ! 520: tp_indicate(T_XDATA, p, 0); ! 521: IncStat(ts_xpd_dup); ! 522: } ! 523: m_freem(e->ev_union.EV_XPD_TPDU.e_data); ! 524: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); ! 525: /* don't send an xack because the xak gives "last one received", not ! 526: * "next one i expect" (dumb) ! 527: */ ! 528: } ! 529: break; ! 530: case 0x21: ! 531: { ! 532: struct socket *so = p->tp_sock; ! 533: ! 534: /* detach from parent socket so it can finish closing */ ! 535: if (so->so_head) { ! 536: if (!soqremque(so, 0) && !soqremque(so, 1)) ! 537: panic("tp: T_DETACH"); ! 538: so->so_head = 0; ! 539: } ! 540: tp_soisdisconnecting(p->tp_sock); ! 541: tp_netcmd( p, CONN_CLOSE); ! 542: tp_soisdisconnected(p); ! 543: } ! 544: break; ! 545: case 0x22: ! 546: { ! 547: struct socket *so = p->tp_sock; ! 548: struct mbuf *data = MNULL; ! 549: ! 550: /* detach from parent socket so it can finish closing */ ! 551: if (so->so_head) { ! 552: if (!soqremque(so, 0) && !soqremque(so, 1)) ! 553: panic("tp: T_DETACH"); ! 554: so->so_head = 0; ! 555: } ! 556: if (p->tp_state != TP_CLOSING) { ! 557: tp_soisdisconnecting(p->tp_sock); ! 558: data = MCPY(p->tp_ucddata, M_NOWAIT); ! 559: (void) tp_emit(DR_TPDU_type, p, 0, E_TP_NORMAL_DISC, data); ! 560: p->tp_retrans = p->tp_Nretrans; ! 561: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_dr_ticks); ! 562: } ! 563: } ! 564: break; ! 565: case 0x23: ! 566: { ! 567: tp_soisdisconnecting(p->tp_sock); ! 568: tp_netcmd( p, CONN_CLOSE); ! 569: tp_soisdisconnected(p); ! 570: } ! 571: break; ! 572: case 0x24: ! 573: { ! 574: struct mbuf *data = MCPY(p->tp_ucddata, M_WAIT); ! 575: ! 576: if(p->tp_state == TP_OPEN) { ! 577: tp_euntimeout(p->tp_refp, TM_data_retrans); /* all */ ! 578: tp_cuntimeout(p->tp_refp, TM_inact); ! 579: tp_cuntimeout(p->tp_refp, TM_sendack); ! 580: } ! 581: if (data) { ! 582: IFDEBUG(D_CONN) ! 583: printf("T_DISC_req.trans tp_ucddata 0x%x\n", ! 584: p->tp_ucddata); ! 585: dump_mbuf(data, "ucddata @ T_DISC_req"); ! 586: ENDDEBUG ! 587: } ! 588: tp_soisdisconnecting(p->tp_sock); ! 589: p->tp_retrans = p->tp_Nretrans; ! 590: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_dr_ticks); ! 591: ! 592: if( trick_hc ) ! 593: return tp_emit(DR_TPDU_type, p, 0, e->ev_union.EV_T_DISC_req.e_reason, data); ! 594: } ! 595: break; ! 596: case 0x25: ! 597: { ! 598: int error; ! 599: struct mbuf *data = MCPY(p->tp_ucddata, M_WAIT); ! 600: ! 601: IncStat(ts_retrans_cc); ! 602: p->tp_retrans --; ! 603: p->tp_cong_win = 1; ! 604: p->tp_ackrcvd = 0; ! 605: ! 606: if( error = tp_emit(CC_TPDU_type, p, 0, 0, data) ) ! 607: p->tp_sock->so_error = error; ! 608: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_cc_ticks); ! 609: } ! 610: break; ! 611: case 0x26: ! 612: { ! 613: IncStat(ts_conn_gaveup); ! 614: tp_soisdisconnecting(p->tp_sock); ! 615: p->tp_sock->so_error = ETIMEDOUT; ! 616: tp_indicate(T_DISCONNECT, p, ETIMEDOUT); ! 617: (void) tp_emit(DR_TPDU_type, p, 0, E_TP_CONGEST, MNULL); ! 618: p->tp_retrans = p->tp_Nretrans; ! 619: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_dr_ticks); ! 620: } ! 621: break; ! 622: case 0x27: ! 623: { ! 624: tp_euntimeout(p->tp_refp, TM_data_retrans); /* all */ ! 625: tp_cuntimeout(p->tp_refp, TM_inact); ! 626: tp_cuntimeout(p->tp_refp, TM_sendack); ! 627: ! 628: IncStat(ts_conn_gaveup); ! 629: tp_soisdisconnecting(p->tp_sock); ! 630: p->tp_sock->so_error = ETIMEDOUT; ! 631: tp_indicate(T_DISCONNECT, p, ETIMEDOUT); ! 632: (void) tp_emit(DR_TPDU_type, p, 0, E_TP_CONGEST_2, MNULL); ! 633: p->tp_retrans = p->tp_Nretrans; ! 634: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_dr_ticks); ! 635: } ! 636: break; ! 637: case 0x28: ! 638: { ! 639: p->tp_cong_win = 1; ! 640: p->tp_ackrcvd = 0; ! 641: /* resume XPD */ ! 642: if ( p->tp_Xsnd.sb_mb ) { ! 643: struct mbuf *m = m_copy(p->tp_Xsnd.sb_mb, 0, (int)p->tp_Xsnd.sb_cc); ! 644: /* m_copy doesn't preserve the m_xlink field, but at this pt. ! 645: * that doesn't matter ! 646: */ ! 647: ! 648: IFTRACE(D_XPD) ! 649: tptrace(TPPTmisc, "XPD retrans: Xuna Xsndnxt sndhiwat snduna", ! 650: p->tp_Xuna, p->tp_Xsndnxt, p->tp_sndhiwat, ! 651: p->tp_snduna); ! 652: ENDTRACE ! 653: IFDEBUG(D_XPD) ! 654: dump_mbuf(m, "XPD retrans emitting M"); ! 655: ENDDEBUG ! 656: IncStat(ts_retrans_xpd); ! 657: p->tp_retrans --; ! 658: (void) tp_emit(XPD_TPDU_type, p, p->tp_Xuna, 1, m); ! 659: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_xpd_ticks); ! 660: } ! 661: } ! 662: break; ! 663: case 0x29: ! 664: { ! 665: register SeqNum low, lowsave = 0; ! 666: register struct tp_rtc *r = p->tp_snduna_rtc; ! 667: register struct mbuf *m; ! 668: register SeqNum high = e->ev_union.EV_TM_data_retrans.e_high; ! 669: ! 670: low = p->tp_snduna; ! 671: lowsave = high = low; ! 672: ! 673: tp_euntimeout_lss(p->tp_refp, TM_data_retrans, ! 674: SEQ_ADD(p, p->tp_sndhiwat, 1)); ! 675: p->tp_retrans_hiwat = p->tp_sndhiwat; ! 676: ! 677: if ((p->tp_rx_strat & TPRX_EACH) == 0) ! 678: high = (high>low)?low:high; ! 679: ! 680: if( p->tp_rx_strat & TPRX_USE_CW ) { ! 681: register int i; ! 682: ! 683: p->tp_cong_win = 1; ! 684: p->tp_ackrcvd = 0; ! 685: i = SEQ_ADD(p, low, p->tp_cong_win); ! 686: ! 687: high = SEQ_MIN(p, high, p->tp_sndhiwat); ! 688: ! 689: } ! 690: ! 691: while( SEQ_LEQ(p, low, high) ){ ! 692: if ( r == (struct tp_rtc *)0 ){ ! 693: IFDEBUG(D_RTC) ! 694: printf( "tp: retrans rtc list is GONE!\n"); ! 695: ENDDEBUG ! 696: break; ! 697: } ! 698: if ( r->tprt_seq == low ){ ! 699: if(( m = m_copy(r->tprt_data, 0, r->tprt_octets ))== MNULL) ! 700: break; ! 701: (void) tp_emit(DT_TPDU_type, p, low, r->tprt_eot, m); ! 702: IncStat(ts_retrans_dt); ! 703: SEQ_INC(p, low ); ! 704: } ! 705: r = r->tprt_next; ! 706: } ! 707: /* CE_BIT ! 708: if ( SEQ_LEQ(p, lowsave, high) ){ ! 709: */ ! 710: e->ev_union.EV_TM_data_retrans.e_retrans --; ! 711: tp_etimeout(p->tp_refp, TM_data_retrans, (caddr_t)lowsave, ! 712: (caddr_t)high, e->ev_union.EV_TM_data_retrans.e_retrans, ! 713: (p->tp_Nretrans - e->ev_union.EV_TM_data_retrans.e_retrans) * (int)p->tp_dt_ticks); ! 714: /* CE_BIT ! 715: } ! 716: */ ! 717: } ! 718: break; ! 719: case 0x2a: ! 720: { ! 721: p->tp_retrans --; ! 722: (void) tp_emit(DR_TPDU_type, p, 0, E_TP_DR_NO_REAS, MNULL); ! 723: IncStat(ts_retrans_dr); ! 724: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_dr_ticks); ! 725: } ! 726: break; ! 727: case 0x2b: ! 728: { ! 729: p->tp_sock->so_error = ETIMEDOUT; ! 730: p->tp_refp->tpr_state = REF_FROZEN; ! 731: tp_recycle_tsuffix( p ); ! 732: tp_etimeout(p->tp_refp, TM_reference, 0,0,0, (int)p->tp_refer_ticks); ! 733: } ! 734: break; ! 735: case 0x2c: ! 736: { ! 737: tp_freeref(p->tp_refp); ! 738: tp_detach(p); ! 739: } ! 740: break; ! 741: case 0x2d: ! 742: { ! 743: if( p->tp_class != TP_CLASS_0) { ! 744: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); ! 745: if ( e->ev_number == CC_TPDU ) ! 746: (void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, MNULL); ! 747: } ! 748: /* ignore it if class 0 - state tables are blank for this */ ! 749: } ! 750: break; ! 751: case 0x2e: ! 752: { ! 753: IFTRACE(D_DATA) ! 754: tptrace(TPPTmisc, "T_DATA_req sndhiwat snduna fcredit, tpcb", ! 755: p->tp_sndhiwat, p->tp_snduna, p->tp_fcredit, p); ! 756: ENDTRACE ! 757: ! 758: tp_send(p); ! 759: } ! 760: break; ! 761: case 0x2f: ! 762: { ! 763: int error = 0; ! 764: ! 765: /* resume XPD */ ! 766: if ( p->tp_Xsnd.sb_mb ) { ! 767: struct mbuf *m = m_copy(p->tp_Xsnd.sb_mb, 0, (int)p->tp_Xsnd.sb_cc); ! 768: /* m_copy doesn't preserve the m_xlink field, but at this pt. ! 769: * that doesn't matter ! 770: */ ! 771: ! 772: IFTRACE(D_XPD) ! 773: tptrace(TPPTmisc, "XPD req: Xuna Xsndnxt sndhiwat snduna", ! 774: p->tp_Xuna, p->tp_Xsndnxt, p->tp_sndhiwat, ! 775: p->tp_snduna); ! 776: ENDTRACE ! 777: IFDEBUG(D_XPD) ! 778: printf("T_XPD_req: sb_cc 0x%x\n", p->tp_Xsnd.sb_cc); ! 779: dump_mbuf(m, "XPD req emitting M"); ! 780: ENDDEBUG ! 781: error = ! 782: tp_emit(XPD_TPDU_type, p, p->tp_Xuna, 1, m); ! 783: p->tp_retrans = p->tp_Nretrans; ! 784: tp_ctimeout(p->tp_refp, TM_retrans, (int)p->tp_xpd_ticks); ! 785: SEQ_INC(p, p->tp_Xsndnxt); ! 786: } ! 787: if(trick_hc) ! 788: return error; ! 789: } ! 790: break; ! 791: case 0x30: ! 792: { ! 793: IFDEBUG(D_ACKRECV) ! 794: printf("GOOD ACK seq 0x%x cdt 0x%x\n", e->ev_union.EV_AK_TPDU.e_seq, e->ev_union.EV_AK_TPDU.e_cdt); ! 795: ENDDEBUG ! 796: if( p->tp_class != TP_CLASS_0) { ! 797: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); ! 798: tp_euntimeout_lss(p->tp_refp, TM_data_retrans, e->ev_union.EV_AK_TPDU.e_seq); ! 799: } ! 800: sbwakeup( &p->tp_sock->so_snd ); ! 801: ! 802: if (p->tp_sndhiwat <= p->tp_retrans_hiwat && ! 803: p->tp_snduna <= p->tp_retrans_hiwat) { ! 804: ! 805: register struct mbuf *m; ! 806: /* extern struct mbuf *m_copy(); */ ! 807: register struct tp_rtc *r; ! 808: SeqNum high, retrans, low_save; ! 809: ! 810: high = SEQ_MIN(p, SEQ_ADD(p, p->tp_snduna, ! 811: MIN(p->tp_cong_win, p->tp_fcredit)) - 1, ! 812: p->tp_sndhiwat); ! 813: low_save = retrans = SEQ_MAX(p, SEQ_ADD(p, p->tp_last_retrans, 1), ! 814: p->tp_snduna); ! 815: for (; SEQ_LEQ(p, retrans, high); SEQ_INC(p, retrans)) { ! 816: ! 817: for (r = p->tp_snduna_rtc; r; r = r->tprt_next){ ! 818: if ( r->tprt_seq == retrans ){ ! 819: if(( m = m_copy(r->tprt_data, 0, r->tprt_octets )) ! 820: == MNULL) ! 821: break; ! 822: (void) tp_emit(DT_TPDU_type, p, retrans, ! 823: r->tprt_eot, m); ! 824: p->tp_last_retrans = retrans; ! 825: IncStat(ts_retrans_dt); ! 826: break; ! 827: } ! 828: } ! 829: if ( r == (struct tp_rtc *)0 ){ ! 830: IFDEBUG(D_RTC) ! 831: printf( "tp: retrans rtc list is GONE!\n"); ! 832: ENDDEBUG ! 833: break; ! 834: } ! 835: } ! 836: tp_etimeout(p->tp_refp, TM_data_retrans, (caddr_t)low_save, ! 837: (caddr_t)high, p->tp_retrans, (int)p->tp_dt_ticks); ! 838: if (SEQ_DEC(p, retrans) == p->tp_retrans_hiwat) ! 839: tp_send(p); ! 840: } ! 841: else { ! 842: tp_send(p); ! 843: } ! 844: IFDEBUG(D_ACKRECV) ! 845: printf("GOOD ACK new sndhiwat 0x%x\n", p->tp_sndhiwat); ! 846: ENDDEBUG ! 847: } ! 848: break; ! 849: case 0x31: ! 850: { ! 851: IFTRACE(D_ACKRECV) ! 852: tptrace(TPPTmisc, "BOGUS ACK fcc_present, tp_r_subseq e_subseq", ! 853: e->ev_union.EV_AK_TPDU.e_fcc_present, p->tp_r_subseq, e->ev_union.EV_AK_TPDU.e_subseq, 0); ! 854: ENDTRACE ! 855: if( p->tp_class != TP_CLASS_0 ) { ! 856: ! 857: if ( !e->ev_union.EV_AK_TPDU.e_fcc_present ) { ! 858: /* send ACK with FCC */ ! 859: IncStat( ts_ackreason[_ACK_FCC_] ); ! 860: (void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 1, MNULL); ! 861: } ! 862: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); ! 863: } ! 864: } ! 865: break; ! 866: case 0x32: ! 867: { ! 868: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); ! 869: tp_cuntimeout(p->tp_refp, TM_retrans); ! 870: ! 871: sbwakeup( &p->tp_sock->so_snd ); ! 872: ! 873: /* resume normal data */ ! 874: tp_send(p); ! 875: } ! 876: break; ! 877: case 0x33: ! 878: { ! 879: IFTRACE(D_ACKRECV) ! 880: tptrace(TPPTmisc, "BOGUS XACK eventtype ", e->ev_number, 0, 0,0); ! 881: ENDTRACE ! 882: if( p->tp_class != TP_CLASS_0 ) { ! 883: tp_ctimeout(p->tp_refp, TM_inact, (int)p->tp_inact_ticks); ! 884: } ! 885: } ! 886: break; ! 887: case 0x34: ! 888: { ! 889: IFTRACE(D_TIMER) ! 890: tptrace(TPPTsendack, -1, p->tp_lcredit, p->tp_sent_uwe, ! 891: p->tp_sent_lcdt, 0); ! 892: ENDTRACE ! 893: IncPStat(p, tps_n_TMsendack); ! 894: (void) tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, MNULL); ! 895: } ! 896: break; ! 897: case 0x35: ! 898: { ! 899: if (sbspace(&p->tp_sock->so_rcv) > 0) ! 900: tp0_openflow(p); ! 901: } ! 902: break; ! 903: case 0x36: ! 904: { ! 905: if( trick_hc ) { ! 906: IncStat(ts_ackreason[_ACK_USRRCV_]); ! 907: ! 908: /* send an ACK only if there's new information */ ! 909: LOCAL_CREDIT( p ); ! 910: if ((p->tp_rcvnxt != p->tp_sent_rcvnxt) || ! 911: (p->tp_lcredit != p->tp_sent_lcdt)) ! 912: ! 913: return tp_emit(AK_TPDU_type, p, p->tp_rcvnxt, 0, MNULL); ! 914: } ! 915: } ! 916: break; ! 917: case 0x37: ! 918: { ! 919: if(trick_hc) ! 920: return ECONNABORTED; ! 921: } ! 922: break; ! 923: case 0x38: ! 924: { ! 925: ASSERT( p->tp_state != TP_LISTENING ); ! 926: tp_indicate(T_DISCONNECT, p, ECONNRESET); ! 927: tp_soisdisconnected(p); ! 928: } ! 929: break; ! 930: } ! 931: return 0; ! 932: } ! 933: ! 934: _XEBEC_PG int ! 935: _Xebec_index( e,p ) ! 936: struct tp_event *e; ! 937: tp_PCB_ *p; ! 938: { ! 939: switch( (e->ev_number<<4)+(p->tp_state) ) { ! 940: case 0x12: ! 941: if ( p->tp_retrans > 0 ) return 0x1e; ! 942: else return 0x1f; ! 943: case 0x13: ! 944: if ( p->tp_retrans > 0 ) return 0x2f; ! 945: else return 0x30; ! 946: case 0x14: ! 947: if ( p->tp_retrans > 0 ) return 0x32; ! 948: else return 0x31; ! 949: case 0x15: ! 950: if ( p->tp_retrans > 0 ) return 0x34; ! 951: else return 0x35; ! 952: case 0x54: ! 953: if ( e->ev_union.EV_TM_data_retrans.e_retrans > 0 ) return 0x33; ! 954: else return 0x31; ! 955: case 0x64: ! 956: if (p->tp_class == TP_CLASS_0) return 0x1a; ! 957: else return 0x1b; ! 958: case 0x77: ! 959: if ( p->tp_class == TP_CLASS_0) return 0xd; ! 960: else return 0xe; ! 961: case 0x86: ! 962: if ( e->ev_union.EV_DR_TPDU.e_sref != 0 ) return 0x2; ! 963: else return 0x3; ! 964: case 0xa2: ! 965: if (p->tp_class == TP_CLASS_0) return 0x1c; ! 966: else return 0x1d; ! 967: case 0xb2: ! 968: if (p->tp_class == TP_CLASS_0) return 0x5; ! 969: else return 0x0; ! 970: case 0xb4: ! 971: if ( tp_goodack(p, e->ev_union.EV_AK_TPDU.e_cdt, e->ev_union.EV_AK_TPDU.e_seq, e->ev_union.EV_AK_TPDU.e_subseq) ) return 0x3a; ! 972: else return 0x3b; ! 973: case 0xc3: ! 974: if ( IN_RWINDOW( p, e->ev_union.EV_DT_TPDU.e_seq, ! 975: p->tp_rcvnxt, SEQ(p, p->tp_rcvnxt + p->tp_lcredit)) ) return 0x21; ! 976: else return 0x24; ! 977: case 0xc4: ! 978: if ( p->tp_class == TP_CLASS_0 ) return 0x22; ! 979: else if ( IN_RWINDOW( p, e->ev_union.EV_DT_TPDU.e_seq, ! 980: p->tp_rcvnxt, SEQ(p, p->tp_rcvnxt + p->tp_lcredit)) ) return 0x23; ! 981: else return 0x25; ! 982: case 0xd3: ! 983: if (p->tp_Xrcvnxt == e->ev_union.EV_XPD_TPDU.e_seq) return 0x27; ! 984: else return 0x2a; ! 985: case 0xd4: ! 986: if (p->tp_Xrcvnxt == e->ev_union.EV_XPD_TPDU.e_seq) return 0x27; ! 987: else return 0x29; ! 988: case 0xe4: ! 989: if ( tp_goodXack(p, e->ev_union.EV_XAK_TPDU.e_seq) ) return 0x3c; ! 990: else return 0x3d; ! 991: case 0x102: ! 992: if ( p->tp_class == TP_CLASS_0 ) return 0x2d; ! 993: else return 0x2e; ! 994: case 0x104: ! 995: if ( p->tp_class == TP_CLASS_0 ) return 0x2d; ! 996: else return 0x2e; ! 997: case 0x144: ! 998: if (p->tp_class == TP_CLASS_0) return 0x3f; ! 999: else return 0x40; ! 1000: case 0x162: ! 1001: if (p->tp_class == TP_CLASS_0) return 0x2b; ! 1002: else return 0x2c; ! 1003: case 0x172: ! 1004: if ( p->tp_class != TP_CLASS_4 ) return 0x42; ! 1005: else return 0x46; ! 1006: case 0x174: ! 1007: if ( p->tp_class != TP_CLASS_4 ) return 0x42; ! 1008: else return 0x47; ! 1009: case 0x177: ! 1010: if ( p->tp_class != TP_CLASS_4 ) return 0x42; ! 1011: else return 0x43; ! 1012: case 0x188: ! 1013: if ( p->tp_class == TP_CLASS_0 ) return 0xf; ! 1014: else if (tp_emit(CC_TPDU_type, p, 0,0, MCPY(p->tp_ucddata, M_NOWAIT)) == 0) return 0x10; ! 1015: else return 0x11; ! 1016: default: return 0; ! 1017: } /* end switch */ ! 1018: } /* _Xebec_index() */ ! 1019: static int inx[26][9] = { {0,0,0,0,0,0,0,0,0,}, ! 1020: {0x0,0x0,0x0,0x0,0x31,0x0,0x0,0x0,0x0, }, ! 1021: {0x0,0x0,-1,-1,-1,-1,0x0,0x0,0x0, }, ! 1022: {0x0,0x0,0x0,0x0,0x3e,0x0,0x0,0x0,0x0, }, ! 1023: {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, }, ! 1024: {0x0,0x0,0x0,0x0,0x0,0x0,0x36,0x0,0x0, }, ! 1025: {0x0,0x0,0x0,0x0,-1,0x0,0x0,0x0,0x0, }, ! 1026: {0x0,0x7,0x15,0x1b,-1,0x17,0x3,0xa,0x0, }, ! 1027: {0x0,0x19,0x6,0x20,0x37,0x8,0x3,-1,0x0, }, ! 1028: {0x0,0x14,0x13,0x13,0x13,0x16,-1,0xa,0x0, }, ! 1029: {0x0,0x7,0x6,0x1,0x9,0x18,0x3,0xa,0x0, }, ! 1030: {0x0,0x19,-1,0x1,0x37,0x8,0x3,0xa,0x0, }, ! 1031: {0x0,0x7,-1,0x26,-1,0x8,0x3,0xa,0x0, }, ! 1032: {0x0,0x7,0x6,-1,-1,0x8,0x3,0xa,0x0, }, ! 1033: {0x0,0x7,0x6,-1,-1,0x8,0x3,0xa,0x0, }, ! 1034: {0x0,0x7,0x6,0x1,-1,0x8,0x3,0xa,0x0, }, ! 1035: {0x0,0x12,0x0,0x0,0x0,0x0,0x0,0x0,0x0, }, ! 1036: {0x0,0x0,-1,0x2e,-1,0x0,0x4,0x0,0x2e, }, ! 1037: {0x0,0xb,0x0,0x0,0x0,0x0,0x0,0x0,0x0, }, ! 1038: {0x0,0x0,0x0,0x0,0x38,0x0,0x0,0x0,0x0, }, ! 1039: {0x0,0x0,0x0,0x0,0x39,0x0,0x0,0x0,0x0, }, ! 1040: {0x0,0x0,0x0,0x0,-1,0x0,0x41,0x0,0x0, }, ! 1041: {0x0,0x0,0x0,0x0,0x28,0x0,0x41,0x0,0x0, }, ! 1042: {0x0,0xc,-1,0x2c,0x0,0x2c,0x4,0xc,0x2c, }, ! 1043: {0x0,0x49,-1,0x45,-1,0x44,0x48,-1,0x0, }, ! 1044: {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,-1, }, ! 1045: }; ! 1046: tp_driver(p, e) ! 1047: register tp_PCB_ *p; ! 1048: register struct tp_event *e; ! 1049: { ! 1050: register int index, error=0; ! 1051: struct act_ent *a; ! 1052: static struct act_ent erroraction = {0,-1}; ! 1053: ! 1054: index = inx[1 + e->ev_number][p->tp_state]; ! 1055: if(index<0) index=_Xebec_index(e, p); ! 1056: if (index==0) { ! 1057: a = &erroraction; ! 1058: } else ! 1059: a = &statetable[index]; ! 1060: ! 1061: if(a->a_action) ! 1062: error = _Xebec_action( a->a_action, e, p ); ! 1063: IFTRACE(D_DRIVER) ! 1064: tptrace(DRIVERTRACE, a->a_newstate, p->tp_state, e->ev_number, a->a_action, 0); ! 1065: ! 1066: ENDTRACE ! 1067: if(error==0) ! 1068: p->tp_state = a->a_newstate; ! 1069: return error; ! 1070: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.