📄 mscp_subr.c
字号:
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 + -