📄 mscp_subr.c
字号:
} return;}/**//* * * Name: mscp_message - Message input routine * * Abstract: * This routine handles end messages and attention * messages arriving on a connection. End messages are * distinguished from attention messages by the presence * of the end flag in the mscp opcode. * * Inputs: * * Outputs: * * * Return NONE * Values: */voidmscp_message( csp ) register CSB *csp;{ register CONNB *cp = ( CONNB * )csp->Aux; register MSCP *mp = ( MSCP * )csp->buf; register REQB *rp; register u_short index, seq_no; /* If the message is an end message, interpret the command reference * number as a RSPID and break it into its component parts. */ if( mp->mscp_opcode & MSCP_OP_END ) { index = (( RSPID * )&mp->mscp_cmd_ref )->index; seq_no = (( RSPID * )&mp->mscp_cmd_ref )->seq_no; /* If the RSPID index is out of range or the sequence number is not * current, deallocate the message without further processing. */ if(( index >= nrspid ) || ( seq_no != mscp_rspid_tbl[ index ].rspid.seq_no )) { printf( "mscp_message: dropping msg: mp %x, op %x, RSPID %x\n", mp, mp->mscp_opcode, mp->mscp_cmd_ref ); if( scs_dealloc_msg( csp ) != RET_SUCCESS ) panic( "mscp_message: scs_dealloc_msg failed\n" ); return; } else { /* If the RSPID represents the oldest command outstanding in * the controller, clear the oldest command field in the * connection block to let connection management know that work * is progressing. */ if( mp->mscp_cmd_ref == *( u_long * )&cp->old_rspid ) *( u_long * )&cp->old_rspid = NULL; /* Get the request block pointer that corresponds to the RSPID, * remove the request block from the connection active queue, * store the MSCP message buffer address and size in the REQB, * and call back the thread that was waiting for message completion. */ rp = mscp_rspid_tbl[ index ].reqb; if( mp->mscp_cmd_ref != *( u_long * )&rp->rspid ) { printf( "mscp_message: end msg rspid %x != rp rspid %x\n", mp->mscp_cmd_ref, *( u_long * )&rp->rspid ); panic( "mscp_message: invalid rspid\n"); } Remove_entry( rp->flink ); rp->flink = NULL; rp->blink = NULL; rp->msgptr = mp; rp->msgsize = csp->size; mscp_dispatch( EV_ENDMSG, rp ); } /* The message is not an end message. Treat it as an attention message * and dispatch on MSCP opcode. */ } else { switch( mp->mscp_opcode ) { default: printf( "mscp_message: unknown attention message 0x%2x\n", mp->mscp_opcode ); case MSCP_OP_AVATN: mscp_avail_attn( csp ); case MSCP_OP_DUPUN: case MSCP_OP_ACPTH: if( scs_dealloc_msg( csp ) != RET_SUCCESS ) panic( "mscp_message: scs_dealloc_msg failed\n" ); } } return;}/**//* * * Name: mscp_avail_attn- Process available attention messages * * Abstract: * * Inputs: * * Outputs: * * * Return NONE * Values: */voidmscp_avail_attn( csp ) register CSB *csp;{ register CONNB *cp = ( CONNB * )csp->Aux; register MSCP *mp = ( MSCP * )csp->buf; UNITB *up; up = mscp_get_unitb( cp, mp, csp->size );}/**//* * * Name: mscp_datagram - Datagram input routine * * Abstract: * This routine handles error logging datagrams. * * Inputs: * * Outputs: * * * Return NONE * Values: */voidmscp_datagram( csp ) CSB *csp;{ register CONNB *cp = (CONNB *)csp->Aux; register MSLG *mp = (MSLG *)csp->buf; register REQB *rp = &cp->bbrb->bbr_reqb; /* bbr request cmd */ register MSLG *bbrmp = &cp->bbrb->bbr_mslg; /* bbr mslg */ void mscp_logerr(); /* error durning bbr cmd - log via bbr code */ if ((cp->bbrb != 0) && (cp->bbrb->flags.bit.busy == 1) && (mp->mslg_cmd_ref == *(u_long *)&rp->rspid)) { if (cp->bbrb->flags.bit.logerr == 0) { *(bbrmp) = *(mp); } } else { mscp_logerr( cp, mp , csp->size); } csp->Nbufs = 0; scs_queue_dgs( csp ); return;}/**//* * Name: mscp_logerr - mscp log error routine * * Abstract: * This routine logs datagram error packets to the system * error log. * * Inputs: cp - connection pointer * mp - mslg packet pointer * size - mslg packet size * * Outputs: * * * Return NONE * Values: */ voidmscp_logerr( cp, mp, size) CONNB *cp; MSLG *mp; long size;{ register struct el_rec *elp; int class, type, devtype, unitnum, subidnum; if ((elp = ealloc((sizeof(struct el_bdev)), EL_PRIHIGH)) == EL_FULL) return; switch (mp->mslg_format) { case MSLG_FM_CNT_ER: case MSLG_FM_BUS_ADDR: class = ELCT_DCNTL; /* Device controller class */ if (mp->mslg_cnt_id[7] == 3) type = ELTMSCP_CNTRL; /* TMSCP controller type */ else type = ELMSCP_CNTRL; /* MSCP controller type */ unitnum = cp->cnt_number; /* Controller number */ devtype = mp->mslg_cnt_id[6] & 0xFF; /* Need to find adpt or bus # from ? */ subidnum = EL_UNDEF; /* adpt or bus controller # */ break; case MSLG_FM_DISK_TRN: case MSLG_FM_SDI: case MSLG_FM_SML_DSK: case MSLG_FM_REPLACE: class = ELCT_DISK; /* Disk class */ type = ELDEV_MSCP; /* MSCP disk type */ devtype = (mp->mslg_unit_id[1] >> 16) & 0xFF; unitnum = mp->mslg_unit; /* Unit number */ subidnum = cp->cnt_number; /* Controller number */ break; case MSLG_FM_TAPE_TRN: case MSLG_FM_STI_ERR: case MSLG_FM_STI_DEL: case MSLG_FM_STI_FEL: case MSLG_FM_IBMSENSE: class = ELCT_TAPE; /* Disk class */ type = ELDEV_MSCP; /* MSCP disk type */ devtype = (mp->mslg_unit_id[1] >> 16) & 0xFF; unitnum = mp->mslg_unit; /* Unit number */ subidnum = cp->cnt_number; /* Controller number */ break; default: class = EL_UNDEF; /* Unknown */ type = EL_UNDEF; /* Unknown */ devtype = EL_UNDEF; /* Unknown */ unitnum = EL_UNDEF; /* Unknown */ subidnum = EL_UNDEF; /* Unknown */ break; } LSUBID(elp, class, type, devtype, subidnum, unitnum, (u_long)mp->mslg_format) /* What should go in here? */ elp->el_body.elbdev.eldevhdr.devhdr_dev = EL_UNDEF; elp->el_body.elbdev.eldevhdr.devhdr_flags = EL_UNDEF; elp->el_body.elbdev.eldevhdr.devhdr_bcount = EL_UNDEF; elp->el_body.elbdev.eldevhdr.devhdr_blkno = EL_UNDEF; elp->el_body.elbdev.eldevhdr.devhdr_retrycnt = EL_UNDEF; elp->el_body.elbdev.eldevhdr.devhdr_herrcnt = EL_UNDEF; elp->el_body.elbdev.eldevhdr.devhdr_serrcnt = EL_UNDEF; elp->el_body.elbdev.eldevhdr.devhdr_csr = EL_UNDEF; elp->el_body.elbdev.eldevdata.elmslg.mslg_len = size; elp->el_body.elbdev.eldevdata.elmslg.mscp_mslg = *(mp); EVALID(elp);}/**//* * * Name: mscp_alloc_rspid - Allocate a Response ID * * Abstract: Allocate a Response ID (RSPID) for use as a command * reference number. If there are no RSPIDs available, * insert the REQB onto the tail of the RSPID wait queue. * * Inputs: rp Request block pointer * connb Connection block pointer * classb Class block pointer * * Outputs: rp * rspid The allocated RSPID * * * Return NONE * Values: *//* ** TO DO ** Put the RSPID table or a pointer to it in the CLASSB * so that it doesn't have to be referenced as a global variable. */u_longmscp_alloc_rspid( event, rp ) u_long event; register REQB *rp;{ register RSPID_TBL *rtp; register u_long new_event = EV_RSPID; /* ** TEMP ** Panic if this reqb already has a RSPID. */ if( *( u_long * )&rp->rspid ) { printf(" rp %x has non-zero RSPID %x\n", rp, rp->rspid ); panic( "mscp_alloc_rspid: double RSPID allocation\n" ); } /* If the RSPID wait queue is empty and there is an available RSPID, * store the REQB address in the RSPID table and copy the RSPID from * the RSPID table into the REQB. */ if(( mscp_rspid_wait_lh.flink == ( QE * )&mscp_rspid_wait_lh.flink ) && ((rtp = (RSPID_TBL *)mscp_rspid_lh.flink) != ( RSPID_TBL *)&mscp_rspid_lh )) { Remove_entry( rtp->flink ); rtp->reqb = rp; rp->rspid = rtp->rspid; /* If the wait queue is not empty or there are no available RSPIDs, * thread the REQB into the RSPID wait queue and bump the wait count * to stall requests on the unit. */ } else { Insert_entry( rp->flink, mscp_rspid_wait_lh ); Incr_rwait( rp ); rspid_wq_cnt++; new_event = EV_NULL; } return( new_event );}/**//* * * Name: mscp_recycle_rspid - Recycle a Response ID * * Abstract: Recycle a response ID by updating its sequence number * field. Recycling has no effect on threads in the RSPID * wait queue. * * Inputs: rp Request block pointer * rspid RSPID * rtp RSPID table pointer * rspid RSPID * * Outputs: rp Request block pointer * rspid Updated RSPID. * * * Return NONE * Values: */voidmscp_recycle_rspid( rp ) register REQB *rp;{ register RSPID_TBL *rtp; /* Locate the RSPID table entry that corresponds to the input RSPID. */ rtp = &mscp_rspid_tbl[ rp->rspid.index ]; /* If the sequence numbers don't agree, something has been corrupted. * Panic. */ if( rtp->rspid.seq_no != rp->rspid.seq_no) panic( "mscp_recycle_rspid - sequence number error.\n" ); /* Update the sequence number and copy the RSPID into the REQB. */ else { if( ++rtp->rspid.seq_no == 0 ) ++rtp->rspid.seq_no; rp->rspid = rtp->rspid; return; }}/**//* * * Name: mscp_dealloc_rspid - deallocate Response ID * * Abstract: Return a RSPID entry to the free queue and activate * the first thread on the RSPID wait queue, if any. * * Inputs: rp Request block pointer * rspid Response ID * rtp RSPID table pointer * rspid Response ID * flink Forward link * * Outputs: * * * Return NONE * Values: */voidmscp_dealloc_rspid( rp ) register REQB *rp;{ register RSPID_TBL *rtp; register REQB *wrp; register CLASSB *clp = rp->classb; /* Locate the RSPID table entry that corresponds to the input RSPID. */ rtp = &mscp_rspid_tbl[ rp->rspid.index ]; /* If the sequence numbers don't agree, something has been corrupted. * Panic. */ if( rtp->rspid.seq_no != rp->rspid.seq_no) { printf("mscp_dealloc_rspid: error rtp->rspid %x, rp->rspid %x\n", *( u_long * )&rtp->rspid, *( u_long * )&rp->rspid); panic( "mscp_dealloc_rspid: sequence number mismatch\n" ); /* Update the sequence number in the RSPID table and zero the * RSPID field in the request block as a safety precaution. */ } else { if( ++rtp->rspid.seq_no == 0 ) ++rtp->rspid.seq_no; rp->rspid.index = 0; rp->rspid.seq_no = 0; /* If there is a request block waiting for a RSPID, do the * required bookkeeping and dispatch the waiting thread. */ if(( wrp = (REQB *)mscp_rspid_wait_lh.flink ) != (REQB *)&mscp_rspid_wait_lh ) { Remove_entry( wrp->flink ); rtp->reqb = wrp; wrp->rspid = rtp->rspid; mscp_dispatch( EV_RSPID, wrp ); Decr_rwait( wrp ); /* No waiters. Clear the request block pointer in the RSPID * table and put the deallocated entry in the free list. */ } else { rtp->reqb = NULL; Insert_entry( rtp->flink, mscp_rspid_lh ); } return; }}/**//* * * Name: mscp_alloc_msg - Allocate a sequenced message buffer * * Abstract: Allocate a sequenced message buffer via SCS. If * the allocation fails because of a shortage of * buffers, insert the REQB on the buffer wait queue. * If the allocation fails for any other reason, panic.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -