📄 ci_subr.c
字号:
* SMP: No locks are required. */u_longci_get_port( pccb, cippdbp ) PCCB *pccb; GVPPPDH *cippdbp;{ register GVPH *cibp = Ppd_to_pd( cippdbp, pccb ); return( Get_pgrp( pccb, cibp ));}/* Name: ci_init_pb - Initialize a Path Block * * Abstract: This function initializes the CI port specific portion of a * Path Block and verifies the suitability of the remote port for * path establishment. The information for PB initialization is * obtained from the ID response received from the target remote * port. This information also indicates whether the remote port * is in a state( ENABLED or MAINTENANCE/ENABLED ) suitable for * path establishment. * * Reception of ID responses from target ports other than the * local port automatically establish the port's connectivity. * * NOTE: This is an optional PD function( Init_pb ) for use by the * CI PPD finite state machine. The CI port driver provides * it because the driver has CI port specific information to * store and because remote CI ports may be in states * unsuitable for path establishment. Other port drivers do * not have such needs and need not provide this function. * Those port drivers which do provide this function and * allow it to return failure status must log the failure * reason in a PD specific fashion. However, only the very * first occurrence of failure on each path should be * logged. Subsequent failures should not be logged until * after a success status is to be returned for the path. * * Inputs: * * IPL_SCS - Interrupt processor level * cippdbp - Address of CI PPD header in ID packet * ( if it had such a header ) * pb - Path Block pointer * pccb - Port Command and Control Block pointer * * Outputs: * * IPL_SCS - Interrupt processor level * pb - Path Block pointer * pinfo.pd.gvp.type.ci - CI specific path information * port_fcn - Remote port function mask * port_fcn_ext - Remote port function extension * reset_port - Address of remote port's last resetter * rport_state - State of remote port * ucode_rev - Remote port microcode revision level * pinfo.type.dual_path - Dual path remote port flag * pinfo.type.hwtype - Hardware type of remote port * pccb - Port Command and Control Block pointer * lpinfo.pd.gvp.type.ci - CI specific local port information * rpslogmap - Remote port state port logging bitmap * pd.gvp.type.ci - CI specific PCCB fields * lpstatus - Local port status flags * connectivity - Port connectivity established status flag * * Return Values: * * RET_SUCCESS - PB successfully initialized * RET_FAILURE - Remote port is NOT in an acceptable state * * SMP: The PCCB is locked( EXTERNALLY ) as required by ci_log_packet() * in case logging becomes necessary. * * The PB is locked( EXTERNALLY ) postponing potential deletion * and allowing exclusive access to PB contents. */u_longci_init_pb( pccb, pb, cippdbp ) PCCB *pccb; register PB *pb; register GVPPPDH *cippdbp;{ register u_long status = RET_SUCCESS; register u_long pktmult; U_long( pb->pinfo.type ) = Idrec( cippdbp )->port_type; U_long( pb->pinfo.Ucode_rev ) = Idrec( cippdbp )->ucode_rev; pb->pinfo.Port_fcn = Idrec( cippdbp )->port_fcn; pb->pinfo.Port_fcn_ext = Idrec( cippdbp )->port_fcn_ext; pb->pinfo.Port_fcn_ext2 = Idrec( cippdbp )->port_fcn_ext2; pb->pinfo.Rport_state = Idrec( cippdbp )->port_state; pb->pinfo.Reset_port = Idrec( cippdbp )->reset_port; if(( pktmult = (( pb->pinfo.Port_fcn_ext & PPR_IBUF_LEN ) >> 25 )) > 0 ) { pktmult--; } if( pktmult > pccb->Pkt_mult ) { pktmult = pccb->Pkt_mult; } pb->pinfo.path_pktmult = pktmult << 28; if( Scaaddr_low( pccb->lpinfo.addr ) != Scaaddr_low( pb->pinfo.rport_addr )) { pccb->Lpstatus.connectivity = 1; } if( pb->pinfo.Rport_state == PS_ENAB || pb->pinfo.Rport_state == PS_ENAB_MAINT ) { Clear_lpinfomap( Rpslogmap, Scaaddr_low( pb->pinfo.rport_addr )) } else { if( !Test_lpinfomap( Rpslogmap, Scaaddr_low( pb->pinfo.rport_addr ))) { Set_lpinfomap( Rpslogmap, Scaaddr_low( pb->pinfo.rport_addr )) ( void )ci_log_packet( pccb, pb, Ppd_to_pd( cippdbp, pccb ), RE_RPORT_STATE, RPORT_EVENT ); } status = RET_FAILURE; } return( status );}/* Name: ci_inv_cache - Invalidate CI Port's Translation Cache * * Abstract: This routine initiates invalidation of a specific local CI * port's translation cache. It is invoked by the CI PPD finite * state machine only during the termination of established paths. * * Translation cache invalidation is initiated by placing a INVTC * command packet onto the highest priority port command queue * and notifying the port when the queue was previously empty. * * A CI port command packet is used to contain the command. It is * provided to this routine and is deallocated following command * execution. * * The port is crashed if the queue interlock can not be obtained. * * NOTE: This is an optional PD routine( Inv_cache ) for use by * the CI PPD finite state machine. The CI port driver * provides it because it oversee ports containing * translation caches requiring invalidation. Other port * drivers do not have such needs and need not provide it. * * Inputs: * * IPL_SCS - Interrupt processor level * pb - Path Block pointer * pd.gvp.ci - CI specific PB fields * invtcpkt - Invalidate translation cache command packet * pccb - Port Command and Control Block pointer * gvp_queue_retry - SCA queuing failure retry count * * Outputs: * * IPL_SCS - Interrupt processor level * pb - Path Block pointer * pd.gvp.ci - CI specific PB fields * invtcpkt - NULL * * SMP: The PB is locked( EXTERNALLY ) postponing premature deletion * and allowing exclusive access to PB contents. * * Access to port command queues is by means of memory * interlocking queuing instructions. * * This routine requires the PCCB to be locked( EXTERNALLY ) * because locks lower than the PCCB in the SCA locking hierarchy * such as the PB may NOT be held without also holding the PCCB * lock in case the port requires crashing. */voidci_inv_cache( pccb, pb, cippdbp ) register PCCB *pccb; PB *pb; GVPPPDH *cippdbp;{ register GVPH *cibp; /* The steps involved in invalidating a local CI port's translation cache * are as follows: * * 1. Retrieve the preallocated emergency invalidate translation cache * command packet associated with the failed path. * 2. Format the generic Vaxport port header of the command packet. * 3. Initiate invalidation of the local CI port's translation cache. * * The port is crashed if command execution can not be successfully * initiated. */ if(( cibp = pb->Invtcpkt )) { pb->Invtcpkt = NULL; } else { panic( PANIC_NOTCPKT ); } Format_gvph( pccb, cibp, INVTC, 0, DEALLOC_BUF ) Insqti_control( cibp, pccb )}/* Name: ci_notify_port - Notify Port of CI PPD Continued Activity * * Abstract: This routine notifies the specified local CI port of CI PPD * continued activity. It is invoked on an ongoing basis by the * CI PPD finite state machine. It is also invoked during * initialization of all local CI ports to initially engage local * port maintenance timers, but only when such timers have been * optionally enabled. * * NOTE: This is an optional PD routine( Notify_port ) for use by * the CI PPD. The CI port driver provides it because the * CI port requires continuous notification of CI PPD * activity. Other ports do not have such needs and their * port drivers need not provide this routine and still * other port drivers may have such needs but utilize * different mechanisms to perform such notifications. * * Inputs: * * IPL_SCS - Interrupt processor level * ci_maint_timer - CI port maintenance timer enable flag * pccb - Port Command and Control Block pointer * * Outputs: * * IPL_SCS - Interrupt processor level * pccb - Port Command and Control Block pointer * pd.gvp.type.ci - CI specific PCCB fields * ciregptrs.pmcsr - Port status register pointer * ciregptrs.pmtcr - Port maintenance timer control reg pointer * lpstatus.mtimer - Maintenance timer is operational flag * * SMP: The PCCB is locked( EXTERNALLY ) allowing exclusive access to * PCCB contents. */voidci_notify_port( pccb ) PCCB *pccb;{ /* Notifying the specified local CI port of continuing CI PPD activity is * required only when CI port maintenance timers have been optionally * enabled. When such enabling occurs, the maintenance timers on all CI * ports must be written to periodically to notify the ports of continued * functioning of host software. Failure to write to a timer within a CI * port specific sanity interval triggers transitioning of the * corresponding port into the Uninitialized/Maintenance port state, * generation of an interrupt, and crashing of the local port. * * The sanity interval for the CI750/CI780/CIBCI maintenance timer is 100 * seconds. The interval for the CIBCA/CIXCA maintenance timer is * variable. * * Management of the specified local CI port maintenance timer includes: * * 1. Reflecting any changes in software maintenance timer state by * disabling or enabling the specified local port maintenance timer as * required. * 2. Poking the specified local CI port maintenance timer if it is * currently software enabled to prevent it from expiring. */ if( ci_maint_timer ^ pccb->Lpstatus.mtimer ) { DELAY( 1000 ); Lock_cidevice( pccb ) if(( pccb->Lpstatus.mtimer = ci_maint_timer )) { *pccb->Pmcsr &= ~PMCSR_MTD; } else { *pccb->Pmcsr |= PMCSR_MTD; } Unlock_cidevice( pccb ) DELAY( 1000 ); } if( pccb->Lpstatus.mtimer ) { Lock_cidevice( pccb ) *pccb->Pmtcr = PMTCR_MTC; Unlock_cidevice( pccb ) WBFLUSH }}/* Name: ci_send_reqid - Request Remote Port Identification * * Abstract: This function initiates a request for the identification of a * specific remote port. It is provided by the port driver for * use by the CI PPD finite state machine during port polling for * the maintenance of existing paths and the initiation of new * ones. It is also invoked by the CI port driver under special * circumstances( See ci_rsp_handler()). * * Execution of this function may also result in scheduling of the * following asynchronous CI PPD notifications: * * 1. Completion of a request for remote port identification. * 2. Reception of information corresponding to the report port * whose identification was requested. * * Neither notification requires scheduling every time this * function is invoked. Notification of the former through * invocation of cippd_reqid_snt() occurs only when the caller * requests deallocation of the packet used in satisfying the * request( dispose == DEALLOC_BUF ). Notification of the latter * through invocation of cippd_receive() occurs only when a * request is made for an existing remote port. Some requests * result in no asynchronous CI PPD notifications. Others result * in both possible notifications with no restrictions placed on * the order in which they occur. * * A request for identification is initiated by placing a REQID * command packet onto the second highest priority port command * queue and notifying the port when the queue was previously * empty. * * Either a CI port command packet or a CI port specific datagram * buffer is used to contain the command. Datagram buffers are * used only when explicitly supplied to the function and are * disposed of following command execution as specified. Command * packets are allocated by the function when datagram buffers are * not provided. They are always deallocated following command * execution. * * The port is crashed if the queue interlock can not be obtained. * * NOTE: This is a mandatory PD function( Send_Reqid ) for use by * the CI PPD finite state machine. Not all port drivers * issue port commands in order to obtain remote port * identifications like the CI port driver. However, all * drivers must still supply this function for scheduling * purposes. All port drivers must schedule CI PPD * reception of remote port identification information. * Those drivers like the CI port driver which have NOT * permanently disabled sanity checking on their local ports * must also schedule CI PPD notification of the completion * of their requests for remote port identifications. How * each driver goes about performing each scheduling is * driver specific, but all notifications MUST be done * asynchronously. They may NOT occur through immediate * call backs. All drivers must also dispose of all port * specific datagram buffers optionally provided to this * function as specified. * * NOTE: SCA port numbers are 6 bytes in size; however, maximum CI * and CI PPD port numbers only occupy 1 byte, the low-order * byte of a port station address. Port numbers are passed * as 4 bytes entities back and forth between the CI PPD and * CI port driver. * * NOTE: The requested identification information must always be * passed back to the CI PPD within a port specific datagram * buffer whenever the requested remote port is found to * exist. The contents of this information is however
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -