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

📄 mscp_subr.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 4 页
字号:
	Move_connid( cp->connid, csp->connid);	csp->buf = ( u_char * )rp->msgptr;	csp->size = sizeof( MSCP_CMDMSG );	csp->Disposal = RECEIVE_BUF;	/* Attempt to send the sequenced message. If scs_send_msg	 * returns successfully, remove the request from the credit	 * wait queue, decrement the wait counter, queue the request	 * to the controller active queue, and zero out the message	 * buffer pointer to prevent its inadvertent reuse.	 */	if(( status = scs_send_msg( csp )) == RET_SUCCESS ) {	    Remove_entry( rp->flink );	    Decr_rwait( rp );	    Insert_entry( rp->flink, cp->active );	    rp->msgptr = NULL;	/* If scs_send_message returned an error, break out of the loop.	 */	} else {	    break;	}    }    return;}/**//* * *   Name:	mscp_reserve_credit - reserve a send credit * *   Abstract:	Reserve a send credit for use by connection management. * *   Inputs:    rp			Request block pointer. * *   Outputs:	 * * *   Return	NONE *   Values: */voidmscp_reserve_credit( rp )    register REQB		*rp;{    register CONNB		*cp = rp->connb;    CSB				csb;    register CSB		*csp = ( CSB * )&csb;    u_long			scs_status;    Move_connid( cp->connid, csp->connid );    if(( scs_status = scs_rsv_credit( csp )) == RET_SUCCESS ) {	cp->flags.need_cr = 0;    }}/**//* * *   Name:	mscp_unstall_unit - activate stalled requests on a unit * *   Abstract:	This routine dispatches requests which were stalled on *		a unit's request queue. * *   Inputs:    up			Unit block pointer. * *   Outputs:	NONE. * * *   Return	NONE *   Values: */voidmscp_unstall_unit( up )    register UNITB		*up;{    register REQB		*rp;    while(( up->rwaitct == 0) &&           (( rp = up->request.flink ) != ( REQB * )&up->request )) {        Remove_entry( rp->flink );	mscp_dispatch( EV_INITIAL, rp );    }}/**//* * *   Name:	mscp_alloc_reqb - allocate a request block * *   Abstract:	Allocate and initialize a request block and return its *		address to the caller.  If no request block is available, *		return NULL to the caller. * *   Inputs:	up			Unit block pointer. *		bp			Buf structure pointer or NULL. *		stbl			State table used by request. *		p1			Function-dependent parameter 1.  *		p2			Function-dependent parameter 2.  * *   Outputs:	NONE * * *   Return	NONE *   Values: */REQB *mscp_alloc_reqb( up, bp, stbl, p1, p2 )    register UNITB		*up;    register struct buf		*bp;    STATE			*stbl;    u_long			p1;    u_long			p2;{    register REQB		*rp;    register CLASSB		*clp = up->connb->classb;    int				saved_ipl;    /* Allocate a request block (sleeping until it becomes available),     * clear and format it.  Then pass control to a functional routine     * to start a sequence of MSCP operations or queue the request if     * activity on the unit is stalled.     */    saved_ipl = Splscs();    while( 1 ) {	KM_ALLOC( rp, REQB *, sizeof( REQB ), KM_CDRP, KM_NOW_CL );	if( rp != NULL )	    break;	timeout( wakeup, ( caddr_t )up, 5 * hz );	( void )sleep(( caddr_t )up, PSWP+1 );	untimeout( wakeup, ( caddr_t )up );    }    rp->unitb = up;    rp->connb = up->connb;    rp->classb = clp;    rp->bufptr = bp;    rp->p1 = p1;    rp->p2 = p2;    rp->op_seq_num = clp->operation_ct++;    rp->rwaitptr = &up->rwaitct;    rp->state_tbl = stbl;    if( up->rwaitct == 0 ) {	mscp_dispatch( EV_INITIAL, rp );    } else {	Insert_entry( rp->flink, up->request );    }    splx( saved_ipl );    return( rp );}/**//* * *   Name:	mscp_dealloc_reqb - deallocate a request block * *   Abstract:	Deallocate a request block and all of the resources *		it holds. * *   Inputs:    rp			Request block pointer. * *   Outputs:	NONE * * *   Return	NONE *   Values: */voidmscp_dealloc_reqb( rp )    register REQB		*rp;{    register CONNB		*cp = rp->connb;    register struct buf		*bp;    /* Deallocate all resources held by the request block.     */    mscp_dealloc_all( rp );    /* If there is a buf structure pointer associated with the operation,     * fill in the residual byte count and issue an iodone on the buffer.     */    if( bp = rp->bufptr ) {	bp->b_resid = rp->p1;	iodone( bp );	rp->bufptr = NULL;    } else {	wakeup(( caddr_t )rp );    }    /* If the request block is not permanently allocated, deallocate it.     */    if( !rp->flags.perm_reqb ) {	KM_FREE( rp, KM_CDRP );    }    /* If the connection is in single stream mode, attempt to restart     * the next request on the restart queue.     */    if( cp->flags.sngl_strm )	mscp_restart_next( cp );    return;}/**//* * *   Name:	mscp_restart_next - Restart next single streamed request * *   Abstract:	This routine is called during connection recovery to *		restart the next request block on the restart queue. *		Requests on the restart queue are retried one at a time *		in order to isolate and eliminate the command(s) which *		may have caused the connection failure. * *   Inputs:    cp			Connection block pointer. * *   Outputs:	NONE * * *   Return	NONE *   Values: */voidmscp_restart_next( cp )    register CONNB		*cp;{    register REQB		*rp;    register struct buf		*bp;    register UNITB		*up;    /* Get the next request on the restart queue, if any.     */    while(( rp = cp->restart.flink ) != ( REQB * )&cp->restart ) {        Remove_entry( rp->flink );	/* If this is the first time through restart for this request,	 * set the single stream flag, update the pointer to the request	 * being restarted and set the restart command retry count to its	 * maximum value.	 */	if( !cp->flags.sngl_strm || rp != cp->restart_reqb ) {	    cp->flags.sngl_strm = 1;	    cp->restart_reqb = rp;	    cp->restart_count = COMMAND_RETRIES;	/* This request has been through restart before.  Decrement the	 * restart retry count.	 */	} else {	    --cp->restart_count;	}	/* If any retries remain, set the state to INITIAL, dispatch	 * the request and break out of the while loop.	 */	if( cp->restart_count ) {	    rp->state = ST_CMN_INITIAL;	    mscp_dispatch( EV_INITIAL, rp );	    break;	/* This request has repeatedly caused the connection to be lost.	 * If the request has a buf structure associated with it, fill	 * in the appropriate fields in the buf structure.  Then deallocate	 * the request block and associated resources.	 */	} else {	    if( bp = rp->bufptr ) {		bp->b_flags |= B_ERROR;		bp->b_error = EIO;		rp->p1 = bp->b_bcount;	    }	    mscp_dealloc_reqb( rp );	}    }        /* If the restart queue is empty, reset single stream mode then scan     * the list of unit blocks on the connection and decrement the wait     * count for each, unstalling the units as appropriate.  When the     * last unit has been seen, reset the connection restart flag.     */    if( cp->restart.flink == ( REQB * )&cp->restart ) {	cp->flags.sngl_strm = 0;	for( up = cp->unit.flink;	     up != ( UNITB * )&cp->unit.flink;	     up = up->flink ) {	    if( up->flags.wait_bump ) {		up->flags.wait_bump = 0;		--up->rwaitct;	    }	    if( up->rwaitct == 0 )		mscp_unstall_unit( up );	}	cp->flags.restart = 0;    }    return;}/**//* * *   Name:	dealloc_all - Deallocate all resources held by REQB * *   Abstract:	Deallocate any resource that is associated with the *		input REQB.  Resources may include RSPID, message *		buffer or mapping information (local buffer handle). * *   Inputs:	rp			REQB pointer *		    rspid		RSPID *		    msgptr		message buffer pointer *		    lbhandle		local buffer handle * *   Outputs: * * *   Return	NONE *   Values: */voidmscp_dealloc_all( rp )    REQB		*rp;{    /* If there is a RSPID in the request block, deallocate it.     */    if( *( u_long * )&rp->rspid )	mscp_dealloc_rspid( rp );    /* If there is a non-NULL message buffer pointer in the REQB,     * deallocate the message buffer.     */    if( rp->msgptr )	mscp_dealloc_msg( rp );    /* If there is a non-NULL local buffer handle in the REQB,     * deallocate it.     */    if( !Test_bhandle( rp->lbhandle ))	mscp_unmap_buffer( rp );    return;}/**//* * *   Name:	mscp_media_to_ascii - Convert MSCP media code to ASCII. * *   Abstract:	 * *   Inputs: * *   Outputs: * * *   Return	NONE *   Values: */voidmscp_media_to_ascii( media, ascii )    register u_long		media;    register u_char		*ascii;{    register u_long		temp;    *ascii++ = (( media >> 17 ) & 0x1f ) + 'A' - 1;    if( temp = (( media >> 12 ) & 0x1f )) {	*ascii++ = ( temp + 'A' - 1 );	if( temp = (( media >> 7 ) & 0x1f ))	    *ascii++ = ( temp + 'A' - 1 );    }    *ascii++ = (( media & 0x7f ) / 10 ) + '0';    *ascii++ = (( media & 0x7f ) % 10 ) + '0';    *ascii = '\0';}/**//* * *   Name:	mscp_common_init - Do tape and disk common initialization. * *   Abstract:	 * *   Inputs: * *   Outputs: * * *   Return	NONE *   Values: */voidmscp_common_init(){    register	int		i;    register	RSPID_TBL	*rtp;    int		s;    s = Splscs();    if( !mscp_gbl_flags ) {	for( i = 0, rtp = mscp_rspid_tbl;	     i < nrspid;	     i++, rtp++ ) {	    Insert_entry( rtp->flink, mscp_rspid_lh );	    rtp->reqb = NULL;	    rtp->rspid.index = i;	    rtp->rspid.seq_no = 1;	}	mscp_gbl_flags = 1;    }    splx( s );    return;}/**//* * *   Name:	mscp_poll_wait  * *   Abstract:	- wait up to 15*count seconds for mscp polling to complete.  *      	Global variable mscp_polls is incremented for each *      	connection attempt and decremented for each connection  *		completion.  If there are no known controllers left to *		poll (mscp_polls == 0) then delay one more iteration to *		allow recognition of controllers which are slow in making *		their presence known. * *   Inputs:    count - specifies the number of 15 second intervals which are *		granted to allow controllers time to report their presence. * *   Outputs: * * *   Return	NONE *   Values: */#ifdef vaxint mscp_polls = 0;int pollwait = 0;#elsevolatile int mscp_polls = 0;volatile int pollwait = 0;#endif vaxvoidmscp_poll_wait(  count )int count;{    if((( mscp_polls > 0 ) && ( count-- > 0 )) ||	(( mscp_polls == 0 ) && ( pollwait == 0 ))) {	( void )timeout( mscp_poll_wait, ( caddr_t )count, hz*15 );	if ( pollwait++ == 0)  {	    while ( pollwait ) {}	}    } else {	pollwait = 0;    }}

⌨️ 快捷键说明

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