📄 ci_isr.c
字号:
( void )scs_dg_rec( pccb, scsbp, Appl_size( cippdbp )); } else { ( void )cippd_receive( pccb, cippdbp, ( u_long )cippdbp->mtype ); } continue; } else { switch( cibp->opcode ) { case DGSNT: case RSTSNT: case STRTSNT: case CKTSET: case TCINV: break; case MSGSNT: ( void )scs_msg_snt( pccb, scsbp, Appl_size( cippdbp )); continue; case IDREQ: ( void )cippd_reqid_snt( pccb, Get_pgrp( pccb, cibp )); break; case IDREC: Lock_pccb( pccb ) if(( pb = cippd_get_pb( pccb, scsbp, BUF ))) { Lock_pb( pb ) /* Crash the path if the remote port is not in an * appropriate state. */ if( pb->pinfo.state == PS_OPEN ) { if( Idrec( cippdbp )->port_state != PS_ENAB && Idrec( cippdbp )->port_state != PS_ENAB_MAINT){ ( void )ci_log_packet( pccb, pb, cibp, E_RPORTSTATE, PATH_EVENT ); ( void )cippd_crash_pb( pccb, pb, E_PD, 0, NULL ); Unlock_pb( pb ) Unlock_pccb( pccb ) ( void )gvp_add_dg( pccb, scsbp ); continue; } else { ( void )ci_update_cable( pccb, pb, cibp, CABLE_CROSSED ); ( void )ci_update_cable( pccb, pb, cibp, CABLE_BG ); } } Unlock_pb( pb ) } Unlock_pccb( pccb ) ( void )cippd_receive( pccb, cippdbp, CNFE_ID_REC ); continue; case LBREC: Lock_pccb( pccb ) ( void )ci_update_cable( pccb, NULL, cibp, CABLE_LB_BG ); Unlock_pccb( pccb ) break; case MSGREC: case CNFRET: case DATREQ0: case DATREQ2: case CNTRD: case LBSNT: case MDATSNT: case MDATREQ: case MCNFREC: case MDATREC: case CNFREC: case DATREC: case DGREC: ( void )ci_crash_lport( pccb, SE_INVOPCODE, scsbp ); return; default: ( void )ci_crash_lport( pccb, SE_UNKOPCODE, scsbp ); return; } } ( void )ci_dealloc_pkt( cibp ); } } while( pccb->Pqb.rspq.flink );}/* Name: ci_unmapped_isr - Unmapped CI Adapter Interrupt Service Routine * * Abstract: * * Inputs: * * IPL_CI - Interrupt processor level * pccb - Port Command and Control Block pointer * pd.gvp.type.ci - CI specific PCCB fields * lpstatus.mapped - 0 * lpstatus.power - Port has power status flag * ppd.cippd - CI PPD specific PCCB fields * fsmstatus.broken - Port is broken status flag * fsmstatus.online - 0 * * Outputs: * * IPL_CI - Interrupt processor level * pccb - Port Command and Control Block pointer * pd.gvp.type.ci - CI specific PCCB fields * lpstatus.power - Port has power status flag * ppd.cippd - CI PPD specific PCCB fields * fsmstatus.broken - Port is broken status flag * fsmstatus.cleanup - Cleanup in progress status flag * * SMP: */voidci_unmapped_isr( pccb ) register PCCB *pccb;{ register u_long cnfr, event, log_regs = LOG_REGS, save_ipl; /* The steps involved in processing an interrupt from an unmapped local CI * port are as follows: * * 1. IPL is synchronized to IPL_SCS. * 2. The PCCB is locked. * 3. The mapped state of the local port is verified. * 4. The local port is mapped. * 5. The interrupt is processed according to its nature. * 6. The interrupt is logged. * 7. The local port is disabled. * 8. The PCCB is unlocked. * 9. IPL is restored. * * The local port is always unmapped on entry into this routine; however it * may be found to be mapped following locking of the PCCB( Step 2 ). * There is only one way this can occur, if another thread were to process * an interrupt notifying the port driver of power availability on the * local port. Such processing leaves the local port mapped because the * severe error which caused the port to be unmapped in the first place( * power loss ) has been alleviated. It also removes any reason for * continued execution of the current thread. Either the power up * interrupt processed by the other thread was originally designated for * the current one, or the interrupt designated for the current thread was * superseded by the power up interrupt processed by the other one. In any * event, there is no reason for the current thread to continue execution * when it finds the local port mapped, and this is why the mapped state of * the local port is verified( Step 3 ) after the PCCB is unlocked. * * This routine services interrupts only when the local port is temporarily * without power or marked marked broken and permanently shutdown. A panic * is issued in any other circumstance. * * All interrupts on broken local ports are considered to be stray. * Processing of these stray interrupts includes re-mapping of the local * port adapter I/O space( Step 4 ). This allows access to local port * registers for the purpose of logging the interrupt( Step 6 ) and * disabling the local port( Step 7 ). Note that only the adapter I/O * space is re-mapped. The interrupt service handler for the local port is * NOT restored to the routine appropriate for the local port hardware port * type. All interrupts on this local port continue to be serviced by this * special routine. Furthermore, this re-mapping is only temporary. The * local port is automatically returned to the unmapped state in which it * was found at the beginning of interrupt processing during disablement of * the local port( Step 7 ). * * Interrupts on local ports temporarily without power( CI750/CI780/CIBCI * only ) may occur for many reasons. In all cases the first action taken * is to fully re-map the local port( Step 4 ). This includes restoration * of the appropriate routine as interrupt service handler for the local * port. Full re-mapping is done because the most likely reason for an * interrupt from such a port is notification of restoration of port power. * Such notification is the only interrupt reason which results in the * local port left fully mapped at the conclusion of interrupt processing. * As such, it is just more efficient to fully re-map local ports * temporarily without power during processing of their interrupts. * * Note that full re-mapping of such local ports is not without its * consequences. Restoration of the normal routine as interrupt service * handler forces subsequent interrupts to be processed by that routine, * even if the current interrupt has not yet been fully deallt with. * Fortunately, such sequences of events can only occur on those local * ports subject to independent power loss which may function also in SMP * environments( CIBCI only ). * All routines which normally serve as interrupt service handlers for such * local ports( cibci_isr()) have been modified to deal correctly with * these situations when they occur. * * Once the local port has been re-mapped, the exact cause of the interrupt * may be ascertained from cached contents of the bus specific * configuration register. Cached contents are employed * 1. Port power up. * 2. Port power down. * 3. CI adapter not present( CI750/CIBCI only ). * * Any other interrupt is unexpected and is treated as a stray interrupt. * */ if( pccb == NULL ) { return; } save_ipl = Splscs(); Lock_pccb( pccb ) if( pccb->Lpstatus.mapped ) { Unlock_pccb( pccb ) ( void )splx( save_ipl ); return; } if( pccb->Fsmstatus.broken ) { ( void )ci_map_port( pccb, MAP_REGS ); event = W_STRAY; } else if( !pccb->Lpstatus.power ) { if( ci_map_port( pccb, MAP_FULL ) == RET_SUCCESS ) { cnfr = *pccb->Cnfr; switch( pccb->lpinfo.type.hwtype ) { case HPT_CI750: case HPT_CI780: if( cnfr & CI780_CNF_PUP ) { event = I_POWERUP; pccb->Lpstatus.power = 1; } else if( cnfr & CI780_CNF_PDWN ) { event = W_POWER; } else if( cnfr & CI780_CNF_NOCI ) { event = FE_NOCI; pccb->Fsmstatus.broken = 1; } else { event = W_STRAY; } break; case HPT_CIBCI: if( cnfr & CIBCI_CNF_PUP ) { event = I_POWERUP; pccb->Lpstatus.power = 1; } else if( cnfr & CIBCI_CNF_PDWN ) { event = W_POWER; } else if( cnfr & ( CIBCI_CNF_NOCI | CIBCI_CNF_DCLO )) { event = FE_NOCI; pccb->Fsmstatus.broken = 1; } else { event = W_STRAY; } break; default: ( void )panic( PANIC_HPT ); } } else { event = FE_NOCI; pccb->Fsmstatus.broken = 1; } if(( pccb->Lpstatus.power || pccb->Fsmstatus.broken ) && !pccb->Fsmstatus.cleanup ) { pccb->Fsmstatus.cleanup = 1; Pccb_fork( pccb, ci_init_port, PANIC_PCCBFB ); } } else { ( void )panic( PANIC_BADUNMAP ); } ( void )ci_log_dev_attn( pccb, event, LOG_REGS ); ( void )( *pccb->Disable_port )( pccb, PS_UNINIT ); Unlock_pccb( pccb ) ( void )splx( save_ipl );}/* Name: ci780_isr - CI750/CI780 Interrupt Service Routine * * Abstract: This routine is the primary interrupt service routine for CI750 * and CI780 local ports. It services all interrupts except: * * 1. When a local port adapter has lost power. * 2. When a local port is marked broken and permanently shutdown. * * At such times the local port is unmapped and all interrupts are * serviced instead by ci_unmapped_isr(). * * CI750 adapters are located within their own physically separate * cabinets. They may lose power independently of the rest of the * system. They may also become uncabled from the CMI on which * they nominally reside leading to their local ports being marked * broken and permanently shutdown. When either of these events * occurs, much( but not all ) of adapter I/O space becomes * unaccessible and any access attempt results in a machine check. * It is as a protection against these extraneous machine checks * that the local port is unmapped and interrupts re-directed to * ci_unmapped_isr(). * * CI780 adapters do NOT suffer from the same handicaps as CI750 * adapters. They are not located within their own physically * separate cabinets and are not subject to extraneous machine * checks. There is no need to unmap a local CI780 port on loss * of power. However, such ports are unmapped anyway on loss of * power because it is not worth distinguishing between two * hardware port types( CI750 and CI780 ) which are otherwise so * identical on the occurrence of an extremely rare condition that * the remainder of the system normally panics on. As for * unmapping CI780 adapters whenever they are marked broken and * are permanently shutdown, all local ports regardless of their * hardware port types undergo such unmapping, and there is no * reason to do anything different for CI780 local ports. *
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -