📄 msi_subr.c
字号:
* CI PPD and MSI 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 * driver specific. It is passed by the CI PPD to the * driver's optionally provided Init_pb routine during path * establishment, presumably for storage in the PB * corresponding to the new path being established. * * NOTE: All attempts to transmit packets to the local ports own * station address are bypassed. The SII chip is not * capable of either internal loopback or simultaneous * transmission and reception; and, no need exists to * provide this function in software. * * Inputs: * * IPL_SCS - Interrupt processor level * cippdbp - Address of CI PPD header in datagram buffer * dispose - RECEIVE_BUF or DEALLOC_BUF * pccb - Port Command and Control Block pointer * rport_addr - Address of target remote port * * Outputs: * * IPL_SCS - Interrupt processor level * pccb - Port Command and Control Block pointer * pd.msi - MSI specific PCCB fields * comql - MSIB low priority command queue * lpstatus.xfork - 1 * xforkb - Transmit Fork Process fork block * * Return Values: * * RET_SUCCESS - Successfully initiated request transmission * RET_ALLOCFAIL - Unable to allocate MSI command packet * * SMP: The PCCB is locked( EXTERNALLY ) allowing exclusive access to * PCCB contents. * * The PCCB specific COMQL is locked allowing exclusive access to * the corresponding low priority command queue */u_longmsi_send_reqid( pccb, cippdbp, rport_addr, dispose ) register PCCB *pccb; CIPPDH *cippdbp; u_long rport_addr; u_long dispose;{ register MSIB *msibp; /* Only the Transmit Fork Process( XFP ) interfaces directly with the SII * chip for the purpose of processing outgoing MSI packets. All other * driver routines must interface with the XFP. Therefore, the steps * involved in requesting transmission of a remote port identification * request are as follows: * * 1. Verify the target port station address. * 2. Allocate a MSI port command packet if a MSI port specific datagram * buffer was not explicitly provided. * 3. Format the MSIB buffer. * 4. Insert the MSIB buffer onto the appropriate command queue. * 5. Request the XFP to process outgoing MSI packets. * * Requests for identification of the local ports own station address are * always satisfied without transmitting an IDREQ packet( Step 1 ). All * MSI port specific datagram buffers provided are immediately disposed of * as directed. Furthermore, the CI PPD is purposely never asynchronously * notified of the existence of the local port. * * Formatting the MSIB buffer( Step 3 ) consists of formatting the: * * MSIB buffer header - information needed by XFP for packet transmission * MSI port header - common MSI packet fields * MSI packet body - IDREQ specific MSI packet fields * * IDREQ specific MSI packet fields requiring formatting by this routine * include only the transaction identifier. This field is currently always * set to 0. * * MSIB buffers containing identification requests are always inserted onto * the appropriate low priority command queue( Step 4 ). The PCCB specific * COMQL is locked immediately prior to insertion and unlocked immediately * afterwards. This guarantees exclusive access to the queue. * * The XFP is requested to begin processing of outgoing MSI packets( Step * 5 ) by scheduling its asynchronous execution. This step is bypassed * whenever XFP execution has already been scheduled but has not yet * commenced. During XFP scheduling the PCCB is locked( EXTERNALLY ) to * guarantee the existence of only 1 scheduled asynchronous XFP thread at * any given moment. * * NOTE: It is possible for a XFP thread to be currently active. This * does not prevent scheduling of asynchronous XFP execution. * However, the new thread does not begin to process outgoing MSI * packets until the currently active thread completes. Also, no * other additional XFP threads are scheduled until the new thread * begins processing outgoing MSI packets. * * NOTE: Existence of the targeted remote port results in automatic * remote initiated transmission of its identification. Reception * of this information automatically triggers asynchronous CI PPD * notification of identification reception. */ if( rport_addr == Scaaddr_lob( pccb->lpinfo.addr )) { if( cippdbp ) { msibp = Ppd_to_pd( pccb, cippdbp ); if( dispose == DEALLOC_BUF ) { ( void )msi_dealloc_pkt( msibp ); } else { Reset_msib( Msibp ) Insert_dfreeq( pccb, msibp ) } } return( RET_SUCCESS ); } if( cippdbp ) { msibp = Ppd_to_pd( pccb, cippdbp ); } else if(( msibp = msi_alloc_pkt( pccb ))) { dispose = DEALLOC_BUF; } else { return( RET_ALLOCFAIL ); } Format_msibh( msibp, rport_addr, sizeof( MSI_IDREQ ), dispose ) Format_msih( msibp, IDREQ ) Format_idreq( msibp ) Insert_comql( pccb, msibp ) Xstart_xfp( pccb ) return( RET_SUCCESS );}/* Name: msi_set_circuit - Set Virtual Circuit State to On/Off * * Abstract: This function sets the virtual circuit associated with a * specific remote port to either an on or an off state. It is * provided by the port driver for use by the CI PPD finite state * machine during path establishment and disablement. * * NOTE: This is a mandatory PD function( Set_circuit ) for use by * the CI PPD finite state machine. Some port drivers are * required to issue port commands in order to set the * virtual circuit. The MSI port driver does not possess * this requirement. However, all drivers must supply this * function for use by the CI PPD. How each driver * accomplishes circuit state modification is left up to it. * * NOTE: SCA port numbers are 6 bytes in size; however, maximum * MSI 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 MSI port driver. * * Inputs: * * IPL_SCS - Interrupt processor level * pb - Path Block pointer * pccb - Port Command and Control Block pointer * rport_addr - Address of target remote port * state - SET_VC_CLOSE or SET_VC_OPEN * * Outputs: * * IPL_SCS - Interrupt processor level * pccb - Port Command and Control Block pointer * perport - Per-DSSI port information * rpstatus.vc - Virtual circuit enabled flag * rseqno - 0 * xseqno - 0 * * Return Values: * * RET_SUCCESS - Virtual circuit state set as directed * * SMP: The PB is locked( EXTERNALLY ) allowing exclusive access to PB * contents. * * The PCCB specific XFP and RFP are locked to synchronize access. * Both locks are required for exclusive access to the MSI * specific PCCB remote port status flag corresponding to the * virtual circuit state of the target remote port. * * PCCB addresses are always valid because these data structures * are never deleted once their corresponding ports have been * initialized( The PCCB is locked EXTERNALLY anyway ). */u_longmsi_set_circuit( pccb, pb, rport_addr, state ) register PCCB *pccb; PB *pb; register u_long rport_addr; u_long state;{ register MSI_PPORTINFO *tpi = &pccb->Perport[ rport_addr ]; Lock_rfp( pccb ) Lock_xfp( pccb ) tpi->xseqno = 0; tpi->rseqno = 0; tpi->rpstatus.vc = state; Unlock_xfp( pccb ) Unlock_rfp( pccb ) return( RET_SUCCESS );}/* Name: msi_alloc_pkt - Allocate MSI Port Command Packet * * Abstract: This function allocates a MSI port specific command packet from * dynamic kernel memory. Such packets must always be deallocated * following packet transmission. They must never be inserted * onto the appropriate local port free queue. * * NOTE: The MSI specific PCCB field pkt_size must contain the * size of the largest MSI port command to always be * deallocated following packet transmission. Currently * this is the STRT port command. * * Inputs: * * IPL_SCS - Interrupt processor level * pccb - Port Command and Control Block pointer * pd.msi - MSI specific PCCB fields * pkt_size - Size of port command packet * * Outputs: * * IPL_SCS - Interrupt processor level * * Return Values: * * Address of MSIB buffer in buffer on success * Otherwise NULL * * SMP: No locks are required. PCCB addresses are always valid * allowing access to static fields because these data structures * are never deleted once their corresponding ports have been * initialized. */MSIB *msi_alloc_pkt( pccb ) register PCCB *pccb;{ register MSIB *msibp; KM_ALLOC( msibp, MSIB *, pccb->Pkt_size, KM_SCABUF, KM_NOWAIT ) if( msibp ) { Format_msib( msibp, pccb->Pkt_size, DYN_MSICMD ) } return( msibp );}/* Name: msi_dealloc_pkt - Deallocate MSI Port Command Packet * * Abstract: This routine deallocates a MSI port specific command packet to * dynamic kernel memory. * * Inputs: * * IPL_SCS - Interrupt processor level * msibp - Address of MSIB buffer * * Outputs: * * IPL_SCS - Interrupt processor level * * SMP: No locks are required. */voidmsi_dealloc_pkt( msibp ) MSIB *msibp;{ KM_FREE(( char * )msibp, KM_SCABUF )}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -