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

📄 mscp_conpol.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 3 页
字号:
 * *   Return	RET_SUCCESS		SCS connection attempt started *   Values:				successfully. *		Other status		SCS connection attempt failed *					and will be retried after the *					connection timeout expires. * */voidmscp_consubr( rp )    register REQB		*rp;{    register CONNB		*cp = rp->connb;    CMSB			cmsb;    register CMSB		*cmsp = &cmsb;    u_long			status;    /* Set up the connection timeout period and fill in the CMSB.     */    cp->cmdtmo_intvl = CONNECT_TMO;    cmsb = cp->classb->cmsb;    cmsp->lport_name = cp->lport_name;    Move_scaaddr( cp->rport_addr, cmsp->rport_addr );    Move_scaaddr( cp->sysid, cmsp->sysid );    cmsp->aux = ( u_char * )cp;    /* Attempt to make a connection via SCS. Exit to wait for the connection     * to complete or for the connection timeout to occur.     */    status = scs_connect( cmsp );    return;}/**//* * *   Name:	mscp_confmtstcon - Format a a STCON command message. * *   Abstract:	Initialize a MSCP message buffer as a set controller *		characteristics message and set up a temporary command *		timeout. * *   Inputs:	rp			Request block pointer *		    msgptr		Message buffer pointer *		    connb		Connection block pointer * *   Outputs:	mp->mscp_		Message buffer pointer *		    cmd_ref		Response ID value *		    opcode		STCON opcode value *		    version		MSCP_VERSION (currently 0) *		    cnt_flgs		Controller flags from connb *		    time		Boot time in VMS format *		Other message buffer fields are zeroed. * *   Return	NONE *   Values: */voidmscp_confmtstcon( rp, hst_tmo )    register REQB		*rp;    u_short			hst_tmo;{    register CONNB		*cp = rp->connb;    register MSCP		*mp = rp->msgptr;    Init_msg( mp, rp->rspid, NULL );    mp->mscp_opcode = MSCP_OP_STCON;    mp->mscp_version = MSCP_VERSION;    mp->mscp_cnt_flgs = cp->cnt_flgs;    mp->mscp_hst_tmo = hst_tmo;    scs_unix_to_vms(( struct timeval * )&boottime,		    ( u_long * )&mp->mscp_time[ 0 ] );    if(( cp->cmdtmo_intvl = cp->cnt_tmo ) == 0 )	cp->cmdtmo_intvl = IMMEDIATE_TMO;    return;}/**//* * *   Name:	mscp_constrstcon - Store results of STCON end message. * *   Abstract:	Store the contents of the set controller characteristics *		end message in the controller block. * *   Inputs:	rp		Request block pointer *		    msgptr	MSCP end message pointer *		    connb	Controller block pointer *		    csb		Communications services block pointer * *   Outputs: * * *   Return	NONE *   Values: */voidmscp_constrstcon( rp )    register REQB		*rp;{    register CONNB		*cp = rp->connb;    register MSCP		*mp = rp->msgptr;    /* Pad the STCON end message out to its full length, then     * copy its contents into the connb.  If the controller     * timeout returned in the end message is 0, store a default     * timeout in the connection block.  If the optional maximum     * byte count field is supplied, use it.  Otherwise, store the     * MSCP specification default for disk or tape, depending on     * the type of device being served.     */    Pad_msg( mp, rp->msgsize );    cp->version = mp->mscp_version;    cp->cnt_flgs = mp->mscp_cnt_flgs;    if(( cp->cnt_tmo = mp->mscp_cnt_tmo ) == 0 ) {	cp->cnt_tmo = 255 - mscp_htmo_overhead;    }    cp->cnt_svr = mp->mscp_cnt_svr;    cp->cnt_hvr = mp->mscp_cnt_hvr;    cp->cnt_id = *( UNIQ_ID * )&mp->mscp_cnt_id[ 0 ];    if(( cp->max_bcnt = mp->mscp_max_bcnt ) == 0 ) {	if( cp->classb->flags.disk ) {	    cp->max_bcnt = ( 1 << 24 );	} else {	    cp->max_bcnt = (( 1 << 16 ) - 1 );	}    }    return;}/**//* * *   Name:	mscp_conqrestart - Queue a REQB on the restart queue * *   Abstract:	Queue a request block on the restart queue in sequence *		number order, after first deallocating all the resources *		that it holds. * *   Inputs:	rp			REQB pointer. * *   Outputs: * * *   Return	NONE *   Values: */voidmscp_conqrestart( rp )    register REQB		*rp;{    register CONNB		*cp = rp->connb;    register REQB		*qrp;    /* Deallocate all the resources held by this REQB.     */    mscp_dealloc_all( rp );    /* Bypass queuing of the driver internal (permanent) request blocks.     */    if( !rp->flags.perm_reqb ) {	/* Find a REQB with a sequence number not less than the one we	 * wish to insert.	 */	for( qrp = cp->restart.flink;	     qrp != ( REQB * )&cp->restart &&	     rp->op_seq_num >= qrp->op_seq_num;	     qrp = qrp->flink )	    ;	/* Sequence numbers should not be duplicated, so if we find two	 * that are equal, panic.	 */	if( rp->op_seq_num == qrp->op_seq_num )	    panic( "mscp_conqrestart: duplicate sequence numbers\n" );	/* Insert the REQB in the restart queue in sequence number order.	 */	Insert_entry( rp->flink, *qrp );    }    return;}/**//* * *   Name:	mscp_consetretry - Reinitialize the connection retry count. * *   Abstract:	 * *   Inputs: * *   Outputs: * * *   Return	NONE *   Values: */u_longmscp_consetretry( event, rp )    u_long		event;    REQB		*rp;{    register CONNB	*cp = rp->connb;    CLASSB		*clp = rp->classb;    /* Set a long timeout interval, reset the connection retry count, and     * call back the routine that started this connection management thread.     */    cp->cmdtmo_intvl = DEAD_TMO;    cp->retry_count = CONNECT_RETRIES;    clp->flags.need_poll = 1;    return( EV_NULL );}/**//* * *   Name:	mscp_polinit - Format and send first GTUNT/next command. * *   Abstract:	 * *   Inputs: * *   Outputs: * * *   Return	NONE *   Values: */u_longmscp_polinit( event, rp )    u_long			event;    register REQB		*rp;{    register CONNB		*cp = rp->connb;    register MSCP		*mp = rp->msgptr;    /* Set the unit polling in progress flag in the connection block,     * initialize the mscp message buffer setting the unit number to 1 and     * format it as a get unit status message, then queue it to be sent out     * on the connection.       */    cp->flags.upoll_busy = 1;    Init_msg( mp, rp->rspid, 1 );    mp->mscp_opcode = MSCP_OP_GTUNT;    mp->mscp_modifier = MSCP_MD_NXUNT;    /* Send the GTUNT command message and wait for the end message to     * come back.     */    return( mscp_send_msg( rp ));}/**//* * *   Name:	mscp_polgtuntem - Find all units attached to a system * *   Abstract:	 * *   Inputs: * *   Outputs: * * *   Return	NONE *   Values: */u_longmscp_polgtuntem( event, rp )    u_long			event;    register REQB		*rp;{    register CONNB		*cp = rp->connb;    register MSCP		*mp = rp->msgptr;    register UNITB		*up;    register u_long		code, subcode;    CLASSB			*clp = rp->classb;    struct uba_ctlr		*um;    /* Pad the GTUNT end message out to the maximum message size,     * and store the updated unit number in the connection block.     */    Pad_msg( mp, rp->msgsize );    cp->cur_unit = mp->mscp_unit;    /* Break apart the end message status for analysis.     */    code = mp->mscp_status & MSCP_ST_MASK;    subcode = mp->mscp_status >> MSCP_ST_SBBIT;    /* If the unit is in a state in which we can potentially     * do operations to it, find/allocate and initialize a unit     * block for the unit.     */    if( code == MSCP_ST_SUCC  ||	code == MSCP_ST_AVLBL ||	code == MSCP_ST_DRIVE ||	( code == MSCP_ST_OFFLN &&	    ( subcode == MSCP_SC_NOVOL || subcode == MSCP_SC_EXUSE ))) {	if(( up = mscp_get_unitb( cp, mp, rp->msgsize )) != NULL ) {	    /* Provide a unit block pointer for the connection permanent	     * request blocks.	     */	    cp->timeout_reqb.unitb = up;	    cp->polling_reqb.unitb = up;	/* The unit block could not be allocated.  Set a flag to cause unit	 * polling to be retried after a few seconds.	 */	} else {	    printf("mscp_polgtuntem: couldn't allocate a unitb\n");	    cp->flags.need_upoll = 1;	}    }    /* If the updated unit number is not zero, we have more units to poll.     * Increment the unit number, initialize the mscp message buffer and format     * it as a get unit status message, then queue it to be sent out on the      * connection.       */    if( cp->cur_unit != 0 && cp->flags.need_upoll == 0 ) {	mscp_recycle_rspid( rp );	Init_msg( mp, rp->rspid, ++cp->cur_unit );	mp->mscp_opcode = MSCP_OP_GTUNT;	mp->mscp_modifier = MSCP_MD_NXUNT;	/* Send the GTUNT command message and wait for the end message to	 * come back.	 */	return( mscp_send_msg( rp ));    /* All units on the connection have been polled.  Deallocate all     * the resources held by the request block, reset the unit polling     * in progress flag in the connection block, dispatch connection     * management with a polling complete event, and terminate the polling     * thread.     */    } else {	mscp_dealloc_all( rp );	cp->flags.upoll_busy = 0;	mscp_dispatch( EV_POLLCOMPLETE, ( REQB * )&cp->timeout_reqb );	return( EV_NULL );    }}/**//* * *   Name:	mscp_get_connb - Find or allocate/initialize connection block * *   Abstract:	 * *   Inputs: * *   Outputs: * * *   Return	NONE *   Values: *//* ?? is there some reason to update the s/w incarnation ?? */CONNB *mscp_get_connb( clp, sysid_ptr, rport_addr_ptr, lport_name )    register CLASSB		*clp;    register c_scaaddr		*sysid_ptr;    register c_scaaddr		*rport_addr_ptr;    u_long			lport_name;{    register CONNB		*cp;    /* Check to see if a connection block for the system exists in the      * data base already.  If so, use it.     */    for( cp = clp->flink; cp != ( CONNB * )&clp->flink; cp = cp->flink ) {	if( Comp_scaaddr( cp->sysid, *sysid_ptr ))	    break;    }    /* If the system isn't already known, attempt to allocate and     * fill in a new connection block.     */    if( cp == ( CONNB * )&clp->flink ) {	KM_ALLOC( cp, CONNB *, sizeof( CONNB ), KM_SCA, KM_NOW_CL_CA );	if( cp != NULL ) {	    mscp_polls++;	    cp->classb = clp;	    cp->unit.flink = ( UNITB * )&cp->unit.flink;	    cp->unit.blink = ( UNITB * )&cp->unit.flink;	    cp->active.flink = ( REQB * )&cp->active.flink;	    cp->active.blink = ( REQB * )&cp->active.flink;	    cp->restart.flink = ( REQB * )&cp->restart.flink;	    cp->restart.blink = ( REQB * )&cp->restart.flink;	    cp->credit_wq.flink = ( REQB * )&cp->credit_wq.flink;	    cp->credit_wq.blink = ( REQB * )&cp->credit_wq.flink;	    cp->buffer_wq.flink = ( REQB * )&cp->buffer_wq.flink;	    cp->buffer_wq.blink = ( REQB * )&cp->buffer_wq.flink;	    cp->map_wq.flink = ( REQB * )&cp->map_wq.flink;	    cp->map_wq.blink = ( REQB * )&cp->map_wq.flink;	    cp->cnt_flgs = MSCP_CF_ATTN | MSCP_CF_MISC | MSCP_CF_THIS;	    cp->timeout_reqb.classb = clp;	    cp->timeout_reqb.connb = cp;	    cp->timeout_reqb.state = ST_CN_INITIAL;	    cp->timeout_reqb.state_tbl = mscp_con_states;	    cp->timeout_reqb.flags.perm_reqb = 1;	    cp->timeout_reqb.flags.nocreditw = 1;	    cp->polling_reqb.classb = clp;	    cp->polling_reqb.connb = cp;	    cp->polling_reqb.state = ST_UP_INITIAL;	    cp->polling_reqb.state_tbl = mscp_pol_states;	    cp->polling_reqb.flags.perm_reqb = 1;	    Insert_entry( cp->flink, *clp );	    ++clp->system_ct;	}    }    /* If we have a connection block in hand, start up a connection     * management thread for it.     */    if( cp != NULL ) {        Move_scaaddr( *sysid_ptr, cp->sysid );        Move_scaaddr( *rport_addr_ptr, cp->rport_addr );        cp->lport_name = lport_name;	mscp_dispatch( EV_INITIAL, ( REQB * )&cp->timeout_reqb );    }    return( cp );}/**//* * *   Name:	mscp_get_unitb - Find or allocate a unit block. * *   Abstract:	Scan the unit list for a connection looking for a unit number *		that matches cur_unit.  If there is no	match, allocate and *		initialize a new UNITB and thread it into the unit list (which *		is maintained in ascending sequence number order.)  Return the *		address of the UNITB to the caller.  If the UNITB could not be *		allocated, return NULL to the caller. * *   Inputs:	cp			Connection block pointer *		mp			MSCP message pointer *		msg_size		MSCP message size * *   Outputs:	NONE * *   Side	A new unit block may be initialized and threaded into the *   Effects:	unit list. * *   Return	up			Unit block pointer if UNITB was found *   Values:				or successfully allocated; else, NULL. */UNITB *mscp_get_unitb( cp, mp, msg_size )    register CONNB		*cp;    register MSCP		*mp;    register u_long		msg_size;{    register UNITB		*up, *next_up;    /* Search for an existing unit block with a unit number equal to the     * cur_unit field in the connection block.  Note that when the for loop     * completes, the unit block pointer is pointing at the listhead or at     * an entry whose unit number is >= the search argument.     */    for( up = cp->unit.flink;	 up != ( UNITB * )&cp->unit.flink && mp->mscp_unit > up->unit;	 up = up->flink ) {}    /* If the unit queue is empty or no matching unit block was found,     * save the address of the next unit block and attempt to allocate     * and initialize a new unit block.     */    if( up == ( UNITB * )&cp->unit.flink || mp->mscp_unit != up->unit ) {		next_up = up;	KM_ALLOC( up, UNITB *, sizeof( UNITB ), KM_SCA, KM_NOW_CL_CA );	if( up != NULL ) {	    up->connb = cp;	    up->request.flink = ( REQB * )&up->request.flink;	    up->request.blink = ( REQB * )&up->request.flink;	    up->unit = mp->mscp_unit;	    up->mult_unt = mp->mscp_mult_unt;	    up->unt_flgs = mp->mscp_unt_flgs;	    up->unit_id = *( UNIQ_ID * )mp->mscp_unit_id;	    up->media_id = mp->mscp_media_id;	    up->unit_svr = mp->mscp_unit_svr;	    up->unit_hvr = mp->mscp_unit_hvr;	    up->unt_flgs = mp->mscp_unt_flgs & MSCP_UF_RMVBL;		    /* Link the new unit block into the connection queue in unit	     * number sequence.	     */	    Insert_entry( up->flink, *next_up );	    	    /* If the controller is present in the configuration tables,	     * try to connect the unit to the configuration tables.	     */	    if( cp->ubctlr ) {		mscp_find_device( up );	    }	}    }    /* Return the address of the unit block (or NULL) to the caller.     */    return( up );}

⌨️ 快捷键说明

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