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