📄 bvp_subr.c
字号:
#ifndef lintstatic char *sccsid = "@(#)bvp_subr.c 4.5 (ULTRIX) 11/13/90";#endif lint/************************************************************************ * * * Copyright (c) 1987 - 1989 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//* * Modification History * * 13-Nov-1990 Pete Keilty * Change all instances of PF_ERROR to PF_PORTERROR because of a * fix to SCS resource deallocation. * * 25-Sep-1990 JAW * initial wait value of zero is incorrect for routine bvp_wait_prt. * According to the spec, -1 is the proper (non-legal) value. Also * found some missing "{}" in loop in the same routine. * * 19-Sep-1989 Pete Keilty * Added pccb to macro Pd_to_ppd. * * 23-Aug-1989 Pete Keilty * Change wbflush() to macro define in scamachmac.h WBFLUSH. * * 25-May-1989 Pete Keilty * Add wbflush() for mips cpu's ISIS. * Add Splscs() to reinit & cleanup routines, fork no longer raises ipl. * * 05-Mar-1989 Todd M. Katz TMK0003 * 1. Include header file ../vaxmsi/msisysap.h. * 2. Use the ../machine link to refer to machine specific header files. * * 19-Aug-1988 Todd M. Katz TMK0002 * 1. Change all instances of PF_FATALERROR -> PF_ERROR as no current * instance of crashing the local port is fatal. * 2. SCA event codes have been completed revised. All former BVP SSP * local port crash codes are now defined as severe error events. The * local port crash attribute itself is applied by bvp_crash_lport(). * 3. Currently bvp_proc_rsp() incorrectly crashes the path when it * encounters a packet with an unknown status. Change it so that it * crashes the local port with a reason code of SE_UNKSTATUS. * * 02-Jun-1988 Ricky S. Palmer * Removed inclusion of header file ../vaxmsi/msisysap.h * * 09-Jan-1988 Todd M. Katz TMK0001 * Included new header files ../vaxscs/scaparam.h, ../vaxmsi/msisysap.h, * and ../vaxmsi/msiscs.h. * * 21-Dec-87 map * Added missing {} in wait_prt() routine. Caused port initialization * to fail if Self-test not done. *//* Include files */#include "../machine/pte.h"#include "../h/param.h"#include "../h/systm.h"#include "../h/buf.h"#include "../h/conf.h"#include "../h/dir.h"#include "../h/kmalloc.h"#include "../h/user.h"#include "../h/map.h"#include "../h/vm.h"#include "../h/vmmac.h"#include "../h/dk.h"#include "../h/cmap.h"#include "../h/uio.h"#include "../h/ioctl.h"#include "../h/fs.h"#include "../machine/cpu.h"#include "../machine/scb.h"#include "../io/uba/ubareg.h"#include "../io/uba/ubavar.h"#ifdef vax#include "../machine/mtpr.h"#endif vax#include "../io/bi/bireg.h"#include "../io/bi/buareg.h"#include "../io/bi/bvpreg.h"#include "../io/bi/bvpport.h"#include "../io/bi/bdareg.h"#include "../h/errlog.h"#include "../h/ksched.h"#include "../io/scs/sca.h"#include "../io/scs/scaparam.h"#include "../io/scs/scamachmac.h"#include "../io/ci/cippdsysap.h"#include "../io/ci/cisysap.h"#include "../io/msi/msisysap.h"#include "../io/bi/bvpsysap.h"#include "../io/gvp/gvpsysap.h"#include "../io/uba/uqsysap.h"#include "../io/sysap/sysap.h"#include "../io/ci/cippdscs.h"#include "../io/ci/ciscs.h"#include "../io/msi/msiscs.h"#include "../io/bi/bvpscs.h"#include "../io/gvp/gvpscs.h"#include "../io/uba/uqscs.h"#include "../io/scs/scs.h"#include "../io/gvp/gvp.h"#include "../io/bi/bvpppd.h"/* Data definitions */u_long bvp_wait_prt();void bvp_cleanup(), bvp_disable();extern u_long gvp_queue_retry;extern struct bidata bidata[];extern int hz;/* Port Info Block */extern struct bvp_port_info bvp_port_info[];/* BVP switch structure */extern struct bvp_sw bvp_sw[];extern int nbvptypes;/* BVP command table */extern struct bvp_cmd bvp_cmd[];#define DELAYONE 5/**//* * * * Name: bvp_init_port * * Abstract: * * Inputs: * * * * * * Outputs: * * * * * * Return * Values: * * * * * Side * Effects: * */short bvp_init_port( pccb )PCCB *pccb;{GVPPQB *pqb;GVPPQB *phys_pqb;struct bvpregs *bvrg;u_long ps;int count; if( bvp_wait_prt(pccb) != RET_SUCCESS) { return(RET_FAILURE); /* Port is dead */ } pqb = &pccb->Pqb; /* Get pointer to PQB */ phys_pqb = (GVPPQB *)svtophy(pqb); /* Physical address of PQB */ bvrg = (struct bvpregs *)Pccb.port_regs; /* Get addr of port regs *//* * Issue Port Init command */ bvrg->bvp_pc = BVP_PC_OWN | ((u_long)phys_pqb & 0xffffff00) | BVP_CMD_PINIT; /* Write Port Init Instruction */ WBFLUSH count = 0; while ( count < DELAYONE ) { /* Wait for at most 1 second */ if ( (bvrg->bvp_pc & BVP_PC_OWN) == 0 ) break; DELAY(200000) count = count + 1; } if ( count == DELAYONE ) { return( RET_FAILURE ); /* Init Failed */ } ps = bvrg->bvp_ps; if ( (ps & BVP_PS_PST) != BVP_PSTATE_INIT ) { return( RET_FAILURE ); } bvrg->bvp_ps = ps & ~BVP_PS_OWN; /* Clear ownership bit */ WBFLUSH return( RET_SUCCESS ); /* and return success */}/**//* * * * Name: bvp_wait_prt * * Abstract: * * Inputs: * * * * * * Outputs: * * * * * * Return * Values: * * * * * Side * Effects: * */u_long bvp_wait_prt(pccb)PCCB *pccb;{struct bvpregs *bvrg;u_long prog_count = -1;u_long bvp_status;int count; bvrg = Pccb.port_regs; /* Get address of Port Registers */ for(;;) { for(;;) { if( (bvrg->bvp_ps & BVP_PS_STD) == 0) { /* Self test not done */ if (prog_count != bvrg->bvp_pd) { /* Any progress ? */ prog_count = bvrg->bvp_pd; /* Yes - update */ DELAY(1000000) /* Delay 1 second */ } else { bvp_crash_lport( pccb, SE_NOPATH, (SCSH *)NULL ); /* No - we died */ return( RET_FAILURE ); } } else break; } bvp_status = bvrg->bvp_ps; /* Get copy of status register */ bvrg->bvp_ps = bvp_status & ~BVP_PS_OWN; WBFLUSH switch( bvp_status & BVP_PS_PST ) { case BVP_PSTATE_STOP: bvrg->bvp_pc = BVP_PC_OWN | BVP_CMD_RESTART; WBFLUSH DELAY(1000000) /* Delay 1 second */ for(;;) { if( (bvrg->bvp_pc & BVP_PC_OWN) != 0 ) { /* Cmd not complete */ prog_count = bvrg->bvp_pd; /* Reset counter */ DELAY(1000000) /* Delay 1 second */ if (prog_count != bvrg->bvp_pd) { /* Any progress ? */ prog_count = bvrg->bvp_pd; /* Yes - update */ } else { bvp_crash_lport( pccb, SE_NOPATH, (SCSH *)NULL ); /* No - we died */ return( RET_FAILURE ); } } else break; } bvp_status = bvrg->bvp_ps; /* Get copy of status register */ bvrg->bvp_ps = bvp_status & ~BVP_PS_OWN; WBFLUSH if ( (bvp_status & BVP_PS_PST) != BVP_PSTATE_UNDF ) { return( RET_FAILURE ); } return( RET_SUCCESS ); break; case BVP_PSTATE_UNDF: if ( (BVP_PS_OWN | BVP_PS_XSTP | BVP_PS_ACC | BVP_PS_STD ) == bvp_status ) /* All o.k. ? */ return ( RET_SUCCESS ); /* Yes indeed */ if ( BVP_PS_ACC & bvp_status ) /* No - Can we at least communicate */ return ( RET_SUCCESS ); /* Yes find out what we can */ return( RET_FAILURE ); /* Port is dead in the water */ break; case BVP_PSTATE_ENAB: return( RET_SUCCESS ); break; default: break; } }}/**//* * * * Name: bvp_proc_rsp * * Abstract: * * Inputs: * * * * * * Outputs: * * * * * * Return * Values: * * * * * Side * Effects: * */void bvp_proc_rsp(pccb)PCCB *pccb;{register GVPH *bvpbp;SCSH *tmpscs;u_long port_crash = 0;u_long path_crash = 0; /* Remove and process each packet on the local port's response queue until * either the queue is exhausted or the local port is crashed. */ do { Remqhi_rspq( pccb, bvpbp ) if ( bvpbp == ( GVPH * )NULL ) break; if( bvpbp->status.failure ) { switch((( bvpbp->status.type != T_OTHER ) ? bvpbp->status.type : ( T_OTHER + bvpbp->status.subtype ))) { /* Unknown Local Port Command. * * This status is generated whenever the local port executes a * command with an invalid opcode field. * * The local port is crashed and the current packet is disposed * of. Any packets remaining within the local port's response * queue are flushed during crashing of the port. */ case ( T_OTHER + ST_URCMD ): port_crash = SE_UNKCMD; break; /* Unimplemented Port Command. * * This status is generated whenever the local port executes a * command with an unimplemented opcode field. * * The local port is crashed and the current packet is * disposed of. Any packets remaining within the local port's * response queue are flushed during crashing of the port. */ case ( T_OTHER + ST_UICMD ): port_crash = SE_UNKCMD; break; /* Invalid FLAGS or STATUS field * * This status is generated whenever the local port executes a * command with an invalid flags or non-zero status field. * * The local port is crashed and the current packet is * disposed of. Any packets remaining within the local port's * response queue are flushed during crashing of the port. */ case ( T_OTHER + ST_IVLP ): port_crash = SE_UNKCMD; break; /* All Other Error Statuses. * * The local port is crashed and the current packet is disposed * of. Any packets remaining within the local port's response * queue are flushed during crashing of the port. */ default: port_crash = SE_UNKSTATUS; break; } /* Crash the local port. Crashing the local port immediately * terminates all response processing. */ ( void )bvp_crash_lport( pccb, port_crash, Pd_to_scs( bvpbp, pccb )); return; } /* Process the current packet according to its port operation code. * * Received sequenced messages are checked for and processed BEFORE * dispatching on the operation code contained within the packet. Such * special handling results in significantly improved performance. * * Received messages are always processed and disposed of by SCS. */ if ( bvpbp->opcode == MSGREC ) { if( (Lpinfo.bvp_type == BI_AIE) || (Lpinfo.bvp_type == BI_AIE_TK) || (Lpinfo.bvp_type == BI_AIE_TK70)) { tmpscs = Pd_to_scs( bvpbp, pccb ); } ( void )scs_msg_rec( pccb, Pd_to_scs( bvpbp, pccb ), ( Pd_to_ppd( bvpbp, pccb )->length - 2 )); continue; } switch( bvpbp->opcode ) { /* Transmitted sequenced messages are always processed and * disposed of by SCS. */ case MSGSNT: ( void )scs_msg_snt( pccb, Pd_to_scs( bvpbp, pccb ), ( Pd_to_ppd( bvpbp, pccb )->length - 2 )); continue; /* Received datagrams are processed and disposed of by SCS if they * contain application datagrams. If they are not application * datagrams then the port is sick and the path is crashed. */ case DGREC: { register GVPPPDH *bvpppdbp; if (( bvpppdbp = Pd_to_ppd( bvpbp, pccb ))->mtype == SCSDG ) ( void )scs_dg_rec( pccb, Pd_to_scs( bvpbp, pccb ), bvpppdbp->length - 2 ); else { ( void )bvp_crash_lport( pccb, SE_INVOPCODE, Pd_to_scs( bvpbp, pccb )); return; } continue; } /* Crash the local port for all other known port operation codes. * Crashing the local port immediately terminates all response * processing. */ case DGSNT: ( void )bvp_crash_lport( pccb, SE_INVOPCODE, Pd_to_scs( bvpbp, pccb )); return; /* Crash the local port for all unknown port operation codes. * Crashing the local port immediately terminates all response * processing. */ default: ( void )bvp_crash_lport( pccb, SE_UNKOPCODE, Pd_to_scs( bvpbp, pccb )); return; } } while( pccb->Pqb.rspq.flink != ( gvpbq * )NULL );}/**//* * * * Name: bvp_qtrans * * Abstract: Queue transition handler * * Inputs: * * pccb - Pointer to PCCB for the port * mask - Number representing queue that transitioned * * * Outputs: * * * * * * Return * Values: * * * * * Side * Effects: * */void bvp_qtrans( pccb, queno )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -