⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mscp_conpol.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 3 页
字号:
		else			cp->hst_tmo = cp->cnt_tmo + mscp_htmo_overhead;	    }	    mscp_confmtstcon( rp, cp->hst_tmo );			    /* If the message is queued successfully, exit to wait for the	     * end message or timeout.  Otherwise, resynch the controller.	     */	    if( mscp_send_msg( rp ) == EV_NULL ) {		return( EV_NULL );	    } else {		return( EV_EXRETRY );	    }	}    }        /* The the controller characteristics have been set successfully.     * If the controller requires host initiated bad block replacement,     * allocate and initialize the BBR work area (BBRB).     */    if( cp->classb->flags.disk && !( cp->cnt_flgs & MSCP_CF_REPLC )) {	mscp_bbr_init( cp );    }         return( EV_CONACTIVE );    }/**//* * *   Name:	mscp_conmarkopen - Mark the connection open. * *   Abstract:	 * *   Inputs: * *   Outputs: * * *   Return	NONE *   Values: */u_longmscp_conmarkopen( event, rp )    u_long		event;    REQB		*rp;{    CONNB		*cp = rp->connb;    /* Initiate polling for units attached to the server on this     * connection, and exit.     */    mscp_find_controller( cp );    cp->polling_reqb.state_tbl = mscp_pol_states;    cp->polling_reqb.state = ST_CMN_INITIAL;    mscp_dispatch( EV_INITIAL, &cp->polling_reqb );    return( EV_NULL );}/**//* * *   Name:	mscp_conrestore - Restore the unit states. * *   Abstract:	 * *   Inputs: * *   Outputs: * * *   Return	NONE *   Values: */u_longmscp_conrestore( event, rp )    u_long			event;    register REQB		*rp;{    register CONNB		*cp = rp->connb;    register CLASSB		*clp = rp->classb;    /* If connection recovery is in progress, initiate a thread to     * restore the state of any units that were online when the     * connection was lost.     */    if( cp->flags.restart ) {	cp->polling_reqb.state_tbl = clp->recov_states;	cp->polling_reqb.state = ST_CMN_INITIAL;	mscp_dispatch( EV_INITIAL, &cp->polling_reqb );    }    mscp_polls--;    return( EV_NULL );}u_short	mscp_force_reset = 0;/**//* * *   Name:	mscp_conwatchdog - Check activity of an open connection. * *   Abstract:	 * *   Inputs: * *   Outputs: * * *   Return	NONE *   Values: */u_longmscp_conwatchdog( event, rp )    u_long		event;    register REQB	*rp;{    register CONNB	*cp = rp->connb;    register REQB	*hrp = cp->active.flink;    register MSCP	*mp = rp->msgptr;    register u_long	new_event = EV_NULL;    if( mscp_force_reset ) {	mscp_force_reset = 0;	return( EV_EXRETRY );    }	    /* If the message pointer is NULL, the controller never responded     * to the previous GTUNT or GTCMD message.  Redispatch to     * resynchronize the connection.     */    if( mp == NULL ) {	new_event =  EV_EXRETRY;    /* Check to see if there are any requests outstanding in     * the active queue.     */    } else if( hrp != ( REQB * )&cp->active.flink ) {	/* Check to see if the command reference number (RSPID) of the oldest	 * active command has changed during the timeout interval.  If the	 * RSPIDs are different, at least one command must have completed in	 * the interval.  Update the oldest active RSPID field in the CONNB,	 * and re-init the command status.	 */	if( *( u_long * )&hrp->rspid != *( u_long *)&cp->old_rspid ) {		    cp->old_rspid = hrp->rspid;		    cp->old_cmd_sts = 0xffffffff;	/* The RSPIDs are the same, indicating that the oldest command did not	 * complete within the previous timeout interval.  Check to see if any	 * progress has been made on the execution of the oldest command by	 * sending a Get Command Status message out on the connection.	 */	} else {	    Init_msg( mp, rp->rspid, NULL );	    if( hrp->unitb != NULL )		mp->mscp_unit = hrp->unitb->unit;	    mp->mscp_opcode = MSCP_OP_GTCMD;	    mp->mscp_out_ref = *( u_long * )&cp->old_rspid;	    new_event = mscp_send_msg( rp );	}    /* No messages are active on the connection.  In order to keep     * the controller from timing the host (us) out, send a Get     * Unit Status command for unit 0 to give the controller a little     * work to do.     */    } else {	Init_msg( mp, rp->rspid, 0 );	mp->mscp_opcode = MSCP_OP_GTUNT;	new_event = mscp_send_msg( rp );    }    /* Begin another timeout interval and exit.  Any errors encountered     * above will cause redispatch to resynchronize the port.     */    cp->cmdtmo_intvl = cp->cnt_tmo;    return( new_event );}/**//* * *   Name:	mscp_conendmsg - Process a GTCMD end message. * *   Abstract:	 * *   Inputs: * *   Outputs: * * *   Return	NONE *   Values: */u_longmscp_conendmsg( event, rp )    u_long		event;    register REQB	*rp;{    register CONNB	*cp = rp->connb;    register MSCP	*mp = rp->msgptr;    /* If the command was a GTCMD, check the progress indicator in     * the end message.     */    if( mp->mscp_endcode == ( MSCP_OP_GTCMD | MSCP_OP_END )) {	/* If no progress has been made, error log the end message and 	 * redispatch to break the connection.  Otherwise, update the	 * command status.	 */	if( cp->old_cmd_sts <= mp->mscp_cmd_sts ) {	    /* Error log the end message */	    return( EV_EXRETRY );	} else	    cp->old_cmd_sts = mp->mscp_cmd_sts;    }    mscp_recycle_rspid( rp );    return( EV_NULL );}/**//* * *   Name:	mscp_conresynch - Resynchronize with a failed (sub-)system. * *   Abstract:	 * *   Inputs: * *   Outputs: * * *   Return	NONE *   Values: */u_longmscp_conresynch( event, rp )    u_long		event;    register REQB	*rp;{    register CONNB	*cp = rp->connb;    MSB			*msp = ( MSB * )&cp->classb->msb;    u_long		status;    printf( "mscp\t- resynching " );    if( cp->cnt_name != NULL ) {	printf( "controller %s%d\n", cp->cnt_name, cp->cnt_number );    } else {	printf( "controller ***** at local port %4s ", &cp->lport_name );	printf( "remote port %x\n", cp->rport_addr );    }    /* Turn off connection timeouts and fill in the MSB.     */    cp->cmdtmo_intvl = 0;    msp->lport_name = cp->lport_name;    Move_scaaddr( cp->rport_addr, msp->rport_addr );    Move_name( cp->classb->cmsb.lproc_name, msp->Lproc_name )    /* Crash the path to the remote system. If the remote system is a     * hardware server, reset and restart it.  If the reset or restart     * fails, check the reason for the failure.  RET_NOLPORT and RET_NOPATH     * represent internal errors and result in panic.  Other errors may     * represent transient lack of a resource and are retried indefinitely.     */    status = scs_crash_path( msp );    if( cp->cnt_id.model != MSCP_CM_VMS &&	cp->cnt_id.model != MSCP_CM_TOPS &&	cp->cnt_id.model != MSCP_CM_ULTRIX32 ) {	msp->Force = 1;	if(( status = scs_reset( msp )) != RET_SUCCESS ) {	    if( status == RET_NOLPORT || status == RET_NOPATH ) {		panic( "mscp_conresynch: scs_reset failure.\n" );	    } else {		cp->cmdtmo_intvl = MAINT_TMO;	    }	} else {	    msp->Startaddr = 0;	    if(( status =  scs_restart( msp )) != RET_SUCCESS ) {		if( status == RET_NOLPORT || status == RET_NOPATH ) {		    panic( "mscp_conresynch: scs_restart failure.\n" );		} else {		    cp->cmdtmo_intvl = MAINT_TMO;		}	    }	}    }    return( EV_NULL );}/**//* * *   Name:	mscp_concleanup - Clean up after a lost connection. * *   Abstract:	This routine is entered when connection management is notified *		that a virtual path has failed or a disconnect has been *		received.  Deallocate all resources held by REQBs on the *		connection, and funnel the REQBs onto the restart queue.  Then *		attempt to restore the connection. * *   Inputs: * *   Outputs: * * *   Return	NONE *   Values: */u_longmscp_concleanup( event, rp )    u_long		event;    REQB		*rp;{    register UNITB		*up = rp->unitb;    register CONNB		*cp = rp->connb;    register REQB		*wrp, *savwrp;    CLASSB			*clp = rp->classb;    CMSB			cmsb;    u_long			status;    u_long			new_event = EV_NULL;    /* Turn off connection timeouts.     */    cp->cmdtmo_intvl = 0;    /* Bump the resource wait reason count for each UNITB attached to     * this CONNB in order to stall all new requests on the connection.     */    for( up = cp->unit.flink;	 (( up != ( UNITB * )&cp->unit.flink ) && ( !up->flags.wait_bump ));	 up = up->flink ) {	up->flags.wait_bump = 1;	up->rwaitct++;    }    /* Return resources held by the permanent request blocks.     */    mscp_dealloc_all( &cp->timeout_reqb );    mscp_dealloc_all( &cp->polling_reqb );    /* ***** NEED TO ADD CODE TO SCAN BBR WAIT QUEUE *****     */    /* Scan the RSPID wait queue looking for REQBs for the current      * connection.  Requeue each REQB in the restart queue.     */    for( wrp = ( REQB * )mscp_rspid_wait_lh.flink;	 wrp != ( REQB * )&mscp_rspid_wait_lh;	 wrp = savwrp ) {	/* save off flink because of wrp requeue on restart queue */	savwrp = wrp->flink;	/* If the REQB is for the current connection, remove it from	 * the wait queue, decrement the wait reasons counter, and	 * queue it on the restart queue.	 */	if( cp == wrp->connb ) {	    Remove_entry( wrp->flink );	    Decr_rwait( wrp );	    mscp_conqrestart( wrp );	}    }    /* Drain the buffer, credit, and mapping wait queues into the     * restart queue.  For each REQB encountered, decrement the     * appropriate resource wait reasons counter before requeueing.     */    for( wrp = cp->buffer_wq.flink;	 wrp != (REQB *)&cp->buffer_wq;	 wrp = cp->buffer_wq.flink ) {	Remove_entry( wrp->flink );	Decr_rwait( wrp );	mscp_conqrestart( wrp );    }    for( wrp = cp->credit_wq.flink;	 wrp != (REQB *)&cp->credit_wq;	 wrp = cp->credit_wq.flink ) {	Remove_entry( wrp->flink );	Decr_rwait( wrp );	mscp_conqrestart( wrp );    }    for( wrp = cp->map_wq.flink;	 wrp != (REQB *)&cp->map_wq;	 wrp = cp->map_wq.flink ) {	Remove_entry( wrp->flink );	Decr_rwait( wrp );	mscp_conqrestart( wrp );    }    /* Drain the queue of requests active in the controller into     * the restart queue.     */    for( wrp = cp->active.flink;	 wrp != (REQB *)&cp->active;	 wrp = cp->active.flink ) {	Remove_entry( wrp->flink );	mscp_conqrestart( wrp );    }        /* Issue an SCS disconnect.  If the disconnect succeeds, and the     * path had failed, the disconnect completes synchronously, so it     * is possible to redispatch immediately to restart the connection.     * Otherwise, the disconnect occurs asynchronously, in which case     * we exit to await disconnect completion.     */    cmsb = clp->cmsb;    Move_connid( cp->connid, cmsb.connid );    cmsb.Reason = ADR_SUCCESS;        if(( status = scs_disconnect( &cmsb )) == RET_SUCCESS ) {	if( cp->flags.path_fail ) {	    cp->flags.path_fail = 0;	    cp->flags.restart = 1;	    new_event = EV_ERRECOV;	}    /* The disconnect failed.  Shouldn't happen.  Panic.     */    } else {	panic( "mscp_concleanup: disconnect failed\n" );    }    return( new_event );}/**//* * *   Name:	mscp_condisccmplt - process completed disconnect. * *   Abstract:	 * *   Inputs: * *   Outputs: * * *   Return	NONE *   Values: */u_longmscp_condisccmplt( event, rp )    u_long		event;    register REQB	*rp;{    register CONNB	*cp = rp->connb;    /* Mark the connection block as being restarted and redispatch to     * attempt reconnection.     */    cp->flags.restart = 1;    return( EV_ERRECOV );}/**//* * *   Name:	mscp_condealmsg - Deallocate message buffers during restart. * *   Abstract:	 * *   Inputs: * *   Outputs: * * *   Return	NONE *   Values: */ u_longmscp_condealmsg( event, rp )    u_long			event;    register REQB		*rp;{    register CONNB		*cp = rp->connb;    CSB				csb;    register CSB		*csp = ( CSB * )&csb;    u_long			scs_status;    /* Return the buffer to SCS ignoring any error that may occur.     */    Move_connid( cp->connid, csp->connid );    csp->buf = ( u_char * )rp->msgptr;    rp->msgptr = NULL;    scs_status = scs_dealloc_msg( csp );    return( EV_NULL );}/**//* * *   Name:	mscp_consubr - Issue scs_connect and analyze return status * *   Abstract:	This routine attempts to make an SCS connection and *		analyzes the return status.  If the connect attempt *		starts successfully, the connection state is updated. * *   Inputs:	rp			Request block *		    connb		Connection block pointer * *   Outputs:	cp			Connection block *		    state		Connection state *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -