📄 ci_init.c
字号:
* Return Values: * * RET_SUCCESS - Local port successfully prepared * RET_FAILURE - CI adapter is absent & can't be initialized * - Insufficient memory for port initialization * * SMP: The PCCB is locked( EXTERNALLY ) allowing unrestricted access. * This is probably unnecessary because of lack of conflict for * the PCCB due to the single threadedness of port clean up and * initialization. It is done anyway to guarantee unrestricted * access and because the CI PPD interval timer may still be * operational. * * Access to port free queues is by means of memory interlocking * queuing instructions. */u_longci_setup_port( pccb ) register PCCB *pccb;{ register u_long n; register SCSH *scsbp; register gvpbq *q, *qend; register u_long status = 0; u_long log_regs, sid = Sid; /* The steps involved in preparing a CI port for initialization are as * follows: * * 1. Presence of a local operational port is verified. * 2. All configuration register errors are cleared( CI750, CI780, CIBCI * only ). * 3. The CPU microcode revision level is verified( 11/750 only ). * 4. An initial number of free datagrams and messages, sufficient to fill * the port's internal cache plus 1, are allocated and inserted into the * appropriate local port queues. * * Preparations for local port initialization are aborted on detection of * any errors. Errors in Steps 1,3 permanently abort port initialization. * The fatal event is logged and the local port is taken permanently * offline by marking it broken and unmapping it. Errors in Step 4 abort * only the current consecutive port initialization attempt. The event is * logged and all local port free queues are flushed with all flushed * buffers being deallocated. * * VAX 11/750 CPU microcode revision levels must be checked prior to every * attempt at CI750 port initialization( Step 3 ). This is because 11/750 * writable control store is volatile and can be lost either on power * failure or other very serious errors. * * Allocation of messages and datagrams and their insertion into * appropriate local port free queues( Step 4 ) is bypassed whenever such * buffers had been previously allocated. This can only occur when * preparation of the local port during a previous consecutive * initialization succeeded although all subsequent attempts at starting of * the port itself failed. * * NOTE: The port is not informed of the presence of free datagram and * message buffers even though the queues have been previously empty. * The port is disabled and therefore is in no condition to take * notice. The port is notified of free queue entry availability * only after its successful enabling. */ if( ci_test_port( pccb ) != RET_SUCCESS ) { status = FE_NOCI; log_regs = LOG_REGS; pccb->Fsmstatus.broken = 1; }#ifdef vax else if( cpu == VAX_750 && (( struct cpu750 * )&sid )->cp_urev < MIN_VAX750_REV ) { status = FE_CPU; log_regs = LOG_NOREGS; pccb->Devattn.cicpurevlev.ci_hwtype = lscs.system.hwtype; pccb->Devattn.cicpurevlev.ci_mincpurev = MIN_VAX750_REV; pccb->Devattn.cicpurevlev.ci_currevlev = (( struct cpu750 * )&sid )->cp_urev; pccb->Fsmstatus.broken = 1; }#endif vax else if( pccb->Dfreeq.flink == NULL ) { for( n = pccb->Dg_cache + 1; n; --n ) { if(( scsbp = gvp_alloc_dg( pccb )) == NULL || insqti( Scs_to_pd( scsbp, pccb ), &pccb->Dfreeq, 0 ) > 0 ) { if( scsbp ) { ( void )gvp_dealloc_dg( pccb, scsbp ); } status = E_NOMEM; log_regs = LOG_NOREGS; break; } } if( status == 0 ) { for( n = pccb->Msg_cache + 1; n; --n ) { if(( scsbp = gvp_alloc_msg( pccb )) == NULL || insqti( Scs_to_pd( scsbp, pccb ), &pccb->Mfreeq, 0 ) > 0){ if( scsbp ) { ( void )gvp_dealloc_msg( pccb, scsbp ); } status = E_NOMEM; log_regs = LOG_NOREGS; break; } } } if( status ) { for( q = &pccb->Dfreeq, qend = &pccb->Mfreeq; q <= qend; ++q ) { Flushq( pccb, q ) } } } if( status == 0 ) { status = RET_SUCCESS; } else { ( void )ci_log_dev_attn( pccb, status, log_regs ); if( pccb->Fsmstatus.broken ) { ( void )ci_unmap_port( pccb ); } status = RET_FAILURE; } return( status );}/* Name: ci_test_port - Test Operational Status of Local CI Port * * Abstract: This function checks for the presence of a local CI port and * clears all bus specific errors which require clearing if the * port is both present and operational. It is invoked only * during local port initialization. * * CI780/CIBCA/CIXCD local ports are always present though they * may be broken. CI750/CIBCI local ports may completely * disappear if the condition triggering failure, clean up, and * re-initialization was sufficiently severe. The most likely * cause of such a disappearence would be the powering down or * uncabling of a CI750/CIBCI in its adjacent cabinet. * * Inputs: * * IPL_SCS - Interrupt processor level * cpu - CPU type code * cpusw - CPU switch structure * pccb - Port Command and Control Block pointer * pd.gvp.type.ci - CI specific PCCB fields * lpstatus.mapped - 1 * ppd.cippd - CI PPD specific PCCB fields * fsmstatus.broken - 0 * fsmstatus.online - 0 * * Outputs: * * IPL_SCS - Interrupt processor level * pccb - Port Command and Control Block pointer * pd.gvp.type.ci - CI specific PCCB fields * ciregptrs.cnfr - Configuration register pointer * * Return Values: * * RET_SUCCESS - Local port present and accessible * RET_FAILURE - Local port absent * * 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( The PCCB is locked EXTERNALLY anyway ). */u_longci_test_port( pccb ) register PCCB *pccb;{ register u_long status = RET_SUCCESS; /* The local CI port is declared absent in the following cases: * * 1. CIBCI/CIBCA/CIXCD failed its self-test. * 2. CI750/CI780/CIBCI configuration register is unaccessible. * 3. CIBCI/CIBCA/CIXCD bus specific device type register is unaccessible. * 4. CI750/CIBCI port lacks power or has been uncabled in its separate * cabinet. * 5. Verification of hardware port type fails. * * All errors are cleared from the CI750/CI780/CIBCI configuration. * register( Step 2 ). The CIBCA/CIXCD do not define such a register and * so no clearing of errors is required. * * NOTE: There is never a need to clear errors in the BIIC/XMI error * register because resetting of the node during port disablement * accomplishes that task. */ switch( pccb->lpinfo.type.hwtype ) {#ifdef vax case HPT_CI750: case HPT_CI780: if( Bad_reg( pccb->Cnfr ) || ( *pccb->Cnfr & CI780_CNF_NOCI ) || ( *pccb->Cnfr & CI780_CNF_ADAP ) != NEX_CI ) { status = RET_FAILURE; } else { *pccb->Cnfr = *pccb->Cnfr; } break;#endif vax case HPT_CIBCI: if( Bad_reg( pccb->Bityp ) || ( *pccb->Bictrl & BICTRL_BROKE ) || Bad_reg( pccb->Cnfr ) || ( *pccb->Cnfr & ( CIBCI_CNF_NOCI | CIBCI_CNF_DCLO )) || ( *pccb->Bityp & BITYP_TYPE ) != BI_CIBCI ) { status = RET_FAILURE; } else { *pccb->Cnfr = *pccb->Cnfr; } break; case HPT_CIBCA_AA: case HPT_CIBCA_BA: if( Bad_reg( pccb->Bityp ) || ( *pccb->Bictrl & BICTRL_BROKE ) || ( *pccb->Bityp & BITYP_TYPE ) != BI_CIBCA || ( pccb->lpinfo.type.hwtype == HPT_CIBCA_AA && ( *pccb->Bityp & CIBCA_DEV_BCABA )) || ( pccb->lpinfo.type.hwtype == HPT_CIBCA_BA && ( *pccb->Bityp & CIBCA_DEV_BCABA ) == 0 )) { status = RET_FAILURE; } break; case HPT_CIXCD: Lock_cidevice( pccb ) if( Bad_reg( pccb->Xdev ) || ( *pccb->Xbe & XMI_STF ) || (( *pccb->Xdev & XMIDTYPE_TYPE ) != XMI_CIXCD )) { status = RET_FAILURE; } Unlock_cidevice( pccb ) break; case HPT_CIKMF: if( Bad_reg( pccb->Xdev ) || ( *pccb->Xbe & XMI_STF ) || (( *pccb->Xdev & XMIDTYPE_TYPE ) != XMI_CIKMF )) { status = RET_FAILURE; } break; default: ( void )panic( PANIC_HPT ); } return( status );}/* Name: ci7b_load - Load CI7B Family Functional Microcode * * Abstract: This function loads CI7B family functional microcode during * local CI750/CI780/CIBCI port initialization. * * NOTE: As presently implemented this function is not suitable * for use on hardware platforms requiring matching field * alignments and access types( ie- only longword aligned * entities may be longword accessed ). This is due to how * each 6 byte CI7B family microcode word is currently * accessed during microcode loading and verification. This * can be fixed but it is not worth it because CI7B family * ports will NOT be supported on non-VAX hardware * platforms. * * Inputs: * * IPL_SCS - Interrupt processor level * ci_ucode - CI port functional microcode pointer * pccb - Port Command and Control Block pointer * pd.gvp.type.ci - CI specific PCCB fields * lpstatus.mapped - 1 * lpstatus.onboard - 0 * ppd.cippd - CI PPD specific PCCB fields * fsmstatus.broken - 0 * fsmstatus.online - 0 * * Outputs: * * IPL_SCS - Interrupt processor level * pccb - Port Command and Control Block pointer * pd.gvp.type.ci - CI specific PCCB fields * ciregptrs.madr - Maintenance address register pointer * ciregptrs.mdatr - Maintenance data register pointer * devattn.ciucode - Faulty microcode information * * Return Values: * * RET_SUCCESS - Port microcode successfully loaded * RET_FAILURE - CI port microcode did not pass verification * * SMP: The PCCB is locked( EXTERNALLY ) to synchronize access. This * is probably unnecessary because of lack of conflict for the * PCCB due to the single threadedness of port clean up and * initialization. It is done anyway to guarantee unrestricted * access and because the CI PPD interval timer may still be * active. */u_longci7b_load( pccb ) register PCCB *pccb;{ register u_char *ucode; register u_long csp, event, load_addr, status = RET_SUCCESS; /* The port's writable control store is loaded with the in-core image of * the CI7B functional microcode. Proper loading is verified by reading * the loaded microcode out of the port's writable control store and * comparing it against the in-code microcode image. Any comparison error * aborts the current consecutive attempt at port initialization. The * event is logged and the port itself is disabled to flush out loaded * microcode. * * A panic occurs whenever an attempt is made to load microcode into a * local port with onboard functional microcode. * * NOTE: Where loading begins in the writable control store is dependent * upon whether the port contains both PROM and RAM( CI750, CI780, * and CIBCI ) or is RAM only. */ if( pccb->Lpstatus.onboard ) { ( void )panic( PANIC_ONBOARD ); } load_addr = ( Ci7b_allram( ci_ucode ) ? CI7B_ARAM_LOAD : CI7B_RAM_LOAD ); for( csp = load_addr, ucode = ( u_char * )ci_ucode; csp < C
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -