📄 uqserv.c
字号:
return (SCS_msg_header(uqbp)); } else { Unlock_pccb (pccb); uq_poll_cring(pccb); /* See if there are any on the cmd ring */ Lock_pccb (pccb); if ((uqbp = (UQH *)Pccb.uq_freel) != (UQH *)NULL){ Pccb.uq_freel = uqbp->flink; Unlock_pccb (pccb); return (SCS_msg_header(uqbp)); } else { Unlock_pccb (pccb); return(NULL); } }}/* * * * Name: uq_dealloc_dg - Deallocate Datagram Buffer * * Abstract: This function deallocates a port specific message buffer. * * Inputs: * * IPL_SCS - Interrupt processor level * * pccb - Port Command and Control Block * scsbp - Address of SCS header in message buffer * * * Outputs: * * IPL_SCS - Interrupt processor level * * * Return * Values: * * RET_SUCCESS - Successful deallocation * * * Side - Buffer is added either to the response * Effects: ring (if not full) or to the internal * free queue * */void uq_dealloc_dg( pccb, scsbp)PCCB *pccb;SCSH *scsbp;{register UQH *uqbp; uqbp = UQ_header( scsbp); uq_ins_rspring(uqbp,pccb); /* Insert in response ring if not */ /* full. Else insert on free queue */ return;}/* * * * Name: uq_add_dg - Add a Datagram to Free Pool * * Abstract: This function adds a datagram buffer to the Free Pool * * Inputs: * * IPL_SCS - Interrupt processor level * * pccb - Port Command and Control Block * scsbp - Address of SCS header in message buffer * * * Outputs: * * IPL_SCS - Interrupt processor level * * * Return * Values: * * * Side - Buffer is added to response ring (if not * Effects: full) or to the internal free queue * */void uq_add_dg(pccb,scsbp)PCCB *pccb;SCSH *scsbp;{UQH *uqbp; uqbp = UQ_header( scsbp ); uq_ins_rspring(uqbp,pccb);}/* * * * Name: uq_remove_dg - Remove a Datagram Buff from Free Pool * * * Abstract: This function removes a UQSSP port specific * datagram buffer from the internal free pool * * Inputs: * * IPL_SCS - Interrupt processor level * pccb - Port Command and Control Block ptr * * Outputs: * * IPL_SCS - Interrupt processor level * scsbp - Add of SCS header in message buffer * * Return * Values: * * Address of SCS header in message buffer on success * Otherwise ( SCSH * )NULL * * * Side - Buffer is removed from the internal free queue * Effects: on success * */SCSH *uq_remove_dg(pccb)PCCB *pccb;{UQH *uqbp; Lock_pccb (pccb); if ((uqbp = (UQH *)Pccb.uq_freel) != (UQH *)NULL){ Pccb.uq_freel = uqbp->flink; Unlock_pccb (pccb); return(SCS_msg_header(uqbp)); } else { Unlock_pccb (pccb); uq_poll_cring(pccb); /* See if there are any on the cmd ring */ Lock_pccb (pccb); if ((uqbp = (UQH *)Pccb.uq_freel) != (UQH *)NULL){ Pccb.uq_freel = uqbp->flink; Unlock_pccb (pccb); return (SCS_msg_header(uqbp)); } else { Unlock_pccb (pccb); return(NULL); } }}/* * * * Name: uq_alloc_msg - Allocate Message Buffer * * Abstract: This function allocates a UQSSP port specific * message buffer. * * Inputs: * * IPL_SCS - Interrupt processor level * pccb - Port Command and Control Block ptr * * Outputs: * * IPL_SCS - Interrupt processor level * scsbp - Add of SCS header in message buffer * * Return * Values: * * Address of SCS header in message buffer on success * Otherwise ( SCSH * )NULL * * Side - Buffer is removed from the internal free queue * Effects: * */ SCSH *uq_alloc_msg( pccb )PCCB *pccb;{UQH *uqbp; uq_alloc_cnt++; Lock_pccb (pccb); if ((uqbp = (UQH *)Pccb.uq_freel) != (UQH *)NULL){ Pccb.uq_freel = uqbp->flink; Unlock_pccb (pccb); return (SCS_msg_header(uqbp)); } else { Unlock_pccb (pccb); uq_poll_cring(pccb); /* See if there are any on the cmd ring */ Lock_pccb (pccb); if ((uqbp = (UQH *)Pccb.uq_freel) != (UQH *)NULL){ Pccb.uq_freel = uqbp->flink; Unlock_pccb (pccb); return (SCS_msg_header(uqbp)); } else { Unlock_pccb (pccb); return(NULL); } }}/* * * * Name: uq_dealloc_msg - Deallocate Message Buffer * * Abstract: This function deallocates a port specific message buffer. * * Inputs: * * IPL_SCS - Interrupt processor level * * pccb - Port Command and Control Block * scsbp - Address of SCS header in message buffer * * * Outputs: * * IPL_SCS - Interrupt processor level * * * Return * Values: * * RET_SUCCESS - Successful deallocation * * * Side - Buffer is added either to the response * Effects: ring (if not full) or to the internal * free queue * */void uq_dealloc_msg( pccb, scsbp)PCCB *pccb;SCSH *scsbp;{register UQH *uqbp; uqbp = UQ_header( scsbp); uq_ins_rspring(uqbp,pccb); /* Insert in response ring if not */ /* full. Else insert on free queue */ return;}/* * * * Name: uq_add_msg - Add a Message to Free Pool * * Abstract: This function adds a message buffer to the Free Pool * * Inputs: * * IPL_SCS - Interrupt processor level * * pccb - Port Command and Control Block * scsbp - Address of SCS header in message buffer * * * Outputs: * * IPL_SCS - Interrupt processor level * * * Return * Values: * * * Side - Buffer is added to response ring (if not * Effects: full) or to the internal free queue * */void uq_add_msg(pccb,scsbp)PCCB *pccb;SCSH *scsbp;{UQH *uqbp; uqbp = UQ_header( scsbp ); uq_ins_rspring(uqbp,pccb);}/* * * * Name: uq_remove_msg - Remove a Message Buff from Free Pool * * * Abstract: This function removes a UQSSP port specific * message buffer from the internal free pool * * Inputs: * * IPL_SCS - Interrupt processor level * pccb - Port Command and Control Block ptr * * Outputs: * * IPL_SCS - Interrupt processor level * scsbp - Add of SCS header in message buffer * * Return * Values: * * Address of SCS header in message buffer on success * Otherwise ( SCSH * )NULL * * * Side - Buffer is removed from the internal free queue * Effects: on success * */SCSH *uq_remove_msg(pccb)PCCB *pccb;{UQH *uqbp; Lock_pccb (pccb); if ((uqbp = (UQH *)Pccb.uq_freel) != (UQH *)NULL){ Pccb.uq_freel = uqbp->flink; Unlock_pccb (pccb); return(SCS_msg_header(uqbp)); } else { Unlock_pccb (pccb); uq_poll_cring(pccb); /* See if there are any on the cmd ring */ Lock_pccb (pccb); if ((uqbp = (UQH *)Pccb.uq_freel) != (UQH *)NULL){ Pccb.uq_freel = uqbp->flink; Unlock_pccb (pccb); return (SCS_msg_header(uqbp)); } else { Unlock_pccb (pccb); return(NULL); } }}/* * * * Name: uq_send_msg * * Abstract: This routine is called by SCS to send a message * across the port. Since UQSSP devices do not * handle SCS level messages, those messages are * processed by this routine. Application level * messages are sent to the port via uq_ins_cring. * * Inputs: * * pccb - Port Command and Control Block ptr * pb - Path Block ptr * scsbp - Ptr to SCS portion of message buffer * size - Size of message buffer * disposal - Flag for disposal of buffer * * * * Outputs: * * * * * * Return * Values: * * * * * Side * Effects: * */void uq_send_msg( pccb, pb, scsbp, size, disposal)PCCB *pccb;PB *pb;SCSH *scsbp;u_long size;u_long disposal;{ACCEPT_RSP *accrsp;struct _connid tcon;CREDIT_RSP *credrsp;UQH *uqbp; /* Pointer to UQ header in buffer */UQPPDH *uqpbp;SCSH *lfbp;u_long con;short msglen;/* If the SCS message type is not an application message then we must *//* handle it in the driver because UQSSP devices do not support SCA. */ if (scsbp->mtype != SCS_APPL_MSG) { /* Not an application msg *//* Since UQSSP devices do not support SCA this driver must fake the *//* connection handshake. */ switch (scsbp->mtype){ /* For the following requests, we queue to a wait queue */ /* This queue is processed via the timer routine. This */ /* is necessary because it is possible to have multiple */ /* SCS requests simultaneously */ /* Connection Request - We fork to the connect routine */ /* and then return to the caller (SCS) */ /* Disconnect Request - To process a disconnect we must */ /* fork so we can generate a response and start our own */ /* disconnect sequence. */ /* Credit Request - This operation is essentially a no-op. */ /* We fork and then generate a response. */ case SCS_CREDIT_REQ: case SCS_DISCONN_REQ: case SCS_CONN_REQ: uqbp = UQ_header(scsbp); Lock_pccb (pccb); Insert_entry(uqbp->flink,Pccb.scswaitq); Unlock_pccb (pccb); break; /* Accept Response - If the response is not success */ /* then the record of the connection is removed. */ /* In either case we then return to the caller (SCS) */ case SCS_ACCEPT_RSP: accrsp = (ACCEPT_RSP *)scsbp; if (accrsp->reason != ADR_SUCCESS) { Pccb.uq_con &= (short)~(1<<Load_connid(accrsp->rconnid)); Pccb.ncon--; } else { /* If last fail packet waiting to be sent then send it */ /* This probably doesn't need to smp-locked; but MSCP */ /* controllers are permitted to send duplicate */ /* datagrams, and lets play it safe anyway. */ con = Load_connid(accrsp->rconnid); if (Pccb.lfptr[con]) { Lock_pccb (pccb); if (Pccb.lfptr[con]) { /* Is it still != 0? */ uqbp = Pccb.lfptr[con]; Pccb.lfptr[con] = 0; Unlock_pccb (pccb); uqpbp = Pos_to_ppdh(uqbp); msglen = uqpbp->uqp_msglen; lfbp = SCS_msg_header(uqbp); lfbp->credit = 0; lfbp->rconnid = Pccb.contab[con]; Store_connid( lfbp->sconnid ) = con; lfbp->mtype = SCS_APPL_DG; scs_dg_rec(pccb,lfbp,(sizeof(SCSH)+msglen)); } else Unlock_pccb (pccb); } } /* FALL THROUGH */ /* Reject Response - This is the last step of the */ /* reject. Decrement connection count and retu
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -