📄 ci_isr.c
字号:
* whenever a local port executes a command with an invalid or * unimplemented opcode field, invalid flags field, or non-zero * status field. * * - Aborted Local Port Command Encountered. Packets with this * status should never be encountered. Only those port commands * currently being processed by the port when it transitions * into the disabled state can have this status. However once * a port enters the disabled state it either is in the process * of being crashed or shortly will be, and all packets on all * port queues are flushed during crashing of the port. * * - All Other( Unknown ) Error Statuses. * * If a response does not contain any errors, or the error is only * informational in nature, then the response is itself processed according * to its port operation code. Processing then continues with the next * response on the port's response queue. There is one exception to this * rule: detection of a NOPATH status in a SNDLB packet. The detection of * this informational error forces deallocation of the packet instead of * queuing it to the appropriate local port datagram free queue as would * have automatically taken place had not the error occurred. Deallocation * of the packet is forced by explicit setting of the response bit within * the flags field of the generic Vaxport driver header. * * Response processing terminates either when this queue is exhausted or a * fatal error is detected triggering crashing of the port. The port is * also crashed if the queue interlock can not be obtained. * * Only cable statuses of open paths are ever updated. */ do { Remqhi_rspq( pccb, cibp ) if( cibp == NULL ) { break; } cibp->opcode &= 0x3f; if( cibp->status.failure ) { u_long crash_lport = 0; register u_long dispatch = 0, event = 0; Lock_pccb( pccb ) if(( pb = cippd_get_pb( pccb, Pd_to_scs( cibp, pccb ), BUF ))) { Lock_pb( pb ) } switch((( cibp->status.type != T_OTHER ) ? cibp->status.type : ( T_OTHER + cibp->status.subtype ))) { case T_OK: dispatch = 1; if( pb && pb->pinfo.state == PS_OPEN ) { ( void )ci_update_cable( pccb, pb, cibp, CABLE_GB ); } break; case T_VCC: break; case T_INVBNAME: crash_lport = 1; event = SE_INVBNAME; break; case T_INVBSIZE: crash_lport = 1; event = SE_INVBSIZE; break; case T_ACCVIO: crash_lport = 1; event = SE_BACCVIO; break; case T_NOPATH: if( cibp->opcode == IDREQ ) { dispatch = 1; if( Cselect( cibp ) != CS_AUTO ) { if( pb && pb->pinfo.state == PS_OPEN ) { ( void )ci_update_cable( pccb, pb, cibp, CABLE_GB ); if( pb->Pstatus.cable0 && pb->Pstatus.cable1 ){ event = E_NOCABLES; /* The response IDREQ packet is not re-used for * the transmission of a REQID over the other * cable. Its processing must continue in case * it represents the REQID currently being * sanity checked. */ } else { register u_long save_cable; save_cable = pccb->Poll_cable; if( Cselect( cibp ) == CS_CABLE0 ) { pccb->Poll_cable = CS_CABLE1; } else { pccb->Poll_cable = CS_CABLE0; } ( void )ci_send_reqid( pccb, NULL, Get_pgrp( pccb,cibp), DEALLOC_BUF ); pccb->Poll_cable = save_cable; } } } else if( pb && pb->pinfo.state != PS_PATH_FAILURE ) { event = E_NOCABLES; } } else if( cibp->opcode == LBSNT ) { cibp->flags.rsp = 1; } else if( cibp->opcode == DGSNT || cibp->opcode == RSTSNT || cibp->opcode == STRTSNT ) { if( pb && pb->pinfo.state != PS_PATH_FAILURE ) { event = E_NOCABLES; } } else if( pb ) { pb->Fsmpstatus.path_closed = 1; if( pb->pinfo.state != PS_PATH_FAILURE ) { event = E_NOCABLES; } } break; case T_BMSE: event = SE_BMSE; break; case( T_OTHER + ST_PSVIO ): if( cibp->opcode == DGSNT || cibp->opcode == MSGSNT || cibp->opcode == DATSNT || cibp->opcode == DATREC || cibp->opcode == LBSNT || cibp->opcode == LBREC ) { crash_lport = 1; event = SE_INVLPKTSIZE; } else { event = SE_INVRPKTSIZE; if( cibp->opcode != DGREC && pb ) { pb->Fsmpstatus.path_closed = 1; } } break; case( T_OTHER + ST_UPKT ): if( cibp->opcode != SNDRST && cibp->opcode != SNDSTRT ) { event = SE_UNRECPKT; } break; case( T_OTHER + ST_DPORT ): crash_lport = 1; event = SE_INVDPORT; break; case( T_OTHER + ST_UCMD ): crash_lport = 1; event = SE_UNKCMD; break; case( T_OTHER + ST_ABORT ): crash_lport = 1; event = SE_ABORTPKT; break; case( T_OTHER + ST_INVPA ): crash_lport = 1; event = SE_INVPA; break; case( T_OTHER + ST_INVSN ): crash_lport = 1; event = SE_INVSN; break; case( T_OTHER + ST_IRESVCD ): crash_lport = 1; event = SE_IRESVCD; break; case( T_OTHER + ST_IRESEQ ): crash_lport = 1; event = SE_IRESEQ; break; case( T_OTHER + ST_DISCVCPKT ): crash_lport = 1; event = SE_DISCVCPKT; break; case( T_OTHER + ST_INVDDL): crash_lport = 1; event = SE_INVDDL; break; default: crash_lport = 1; event = SE_UNKSTATUS; break; } if( event ) { if( crash_lport == 0 ) { ( void )ci_log_packet( pccb, pb, cibp, event, PATH_EVENT ); ( void )cippd_crash_pb( pccb, pb, (( Eseverity( event ) == ES_E ) ? E_PD : SE_PD ), 0, NULL ); } else { ( void )ci_crash_lport( pccb, event, Pd_to_scs( cibp, pccb )); } } if( pb ) { Unlock_pb( pb ) } Unlock_pccb( pccb ) if( crash_lport ) { return; } if( !cibp->flags.rsp ) { if( cibp->opcode == IDREC || cibp->opcode == IDREQ || cibp->opcode == DGSNT || cibp->opcode == DGREC || cibp->opcode == LBSNT || cibp->opcode == LBREC || ( cibp->status.type == T_OTHER && cibp->status.subtype == ST_UPKT )) { ( void )gvp_add_dg( pccb, Pd_to_scs( cibp, pccb )); } else { ( void )gvp_add_msg( pccb, Pd_to_scs( cibp, pccb )); } continue; } else if( !dispatch ) { ( void )ci_dealloc_pkt( cibp ); continue; } } /* Responses with good or informational status are processed according * to their port operation codes as follows: * * Response Processing * * Received/Transmitted - SCS processes and disposes of response. * Sequence Message * * Completed Block Data - SCS is notified of block data transfer * Transfer completion. * - Port driver disposes of response. * * Received Datagram - SCS processes and disposes of datagram( * application datagrams only ). * - CI PPD processes and disposes of datagram( * all other datagrams ). * * Invalidate - Port driver disposes of response. * Translation Cache * Command * Transmitted Datagram * Reset Request * Start Request * Set Circuit Command * * Transmitted - CI PPD is notified of request identification * Identification command completion. * Request - Port driver disposes of response. * * Received - The appropriate PB's cable status is updated( * Identification open paths only ). * Packet - Log all crossed->uncrossed, * uncrossed->crossed, and bad->good cable * transitions( open paths only ). * - CI PPD processes and disposes of response. * * Received - The appropriate PCCB's loopback cable status * Loopback Response is updated. * - Log all loopback bad->good transitions. * - Port driver disposes of response. * * All other port - The local port is crashed. * operation codes - Response processing is terminated. * * Received sequenced messages, datagrams, and block data transfer * completion packets are checked for and processed BEFORE dispatching * on the operation code contained within the response. Such special * handling results in significantly improved performance. */ { register SCSH *scsbp = Pd_to_scs( cibp, pccb ); register GVPPPDH *cippdbp = Pd_to_ppd( cibp, pccb ); if( cibp->opcode == MSGREC ) { ( void )scs_msg_rec( pccb, scsbp, Appl_size( cippdbp )); continue; } else if( cibp->opcode == CNFREC || cibp->opcode == DATREC ) { ( void )scs_data_done( pccb, scsbp, &Cnfrec( cippdbp )->xctid ); } else if ( cibp->opcode == DGREC ) { if( cippdbp->mtype == SCSDG ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -