From 6359717ac516237d4c2f61e70273b69ada6e6898 Mon Sep 17 00:00:00 2001 From: Peter Jansen Date: Sat, 4 Nov 2017 03:07:44 +0100 Subject: [PATCH] Additional CTCE bug fixes and stability and recovery improvements. (#13) CTCE fix for CTCA command SCB at initialization and additional stability and recovery improvements. --- ctcadpt.c | 268 ++++++++++++++++++++++++++++++++++++------------------ msgenu.h | 2 +- 2 files changed, 178 insertions(+), 92 deletions(-) diff --git a/ctcadpt.c b/ctcadpt.c index a677a8712..9b973e3cb 100644 --- a/ctcadpt.c +++ b/ctcadpt.c @@ -58,6 +58,7 @@ typedef struct _CTCE_INFO u_int attn_can : 1; /* = 1 : Atttention Cancelled */ u_int con_lost : 1; /* = 1 : contention lost */ u_int con_won : 1; /* = 1 : contention won */ + u_int sel_reset : 1; /* = 1 : selective reset */ int wait_rc; /* CTCE_Send Wait RC if used */ int de_ready_attn_rc; /* device_attention RC */ int working_attn_rc; /* device_attention RC */ @@ -111,7 +112,7 @@ static void* CTCE_RecvThread( void* argp ); static void* CTCE_ListenThread( void* argp ); -static BYTE CTCE_HaltOrClear( DEVBLK* pDEVBLK ); +static BYTE CTCE_Reset( DEVBLK* pDEVBLK ); static U32 CTCE_ChkSum( const BYTE* pBuf, const U16 BufLen ); @@ -278,8 +279,6 @@ static BYTE CTCE_command[256] = { #define IS_CTCE_YWW(c) (((c)&0x07)==0x03) #define IS_CTCE_YAV(c) ((CTCE_STATE(c))==0x04) #define IS_CTCE_YNR(c) ((CTCE_STATE(c))==0x05) -#define IS_CTCE_XWK(c) (((c)&0x07)==0x06) -#define IS_CTCE_XIP(c) (((c)&0x07)==0x07) /* These two are useful combinations : */ /* - The 0 (YWP) or 4 (YAV) states READY */ @@ -293,17 +292,9 @@ static BYTE CTCE_command[256] = { /* includes the not ready state. */ #define IS_CTCE_XAV(c) (((c)<6)) -/* And the corresponding SET macros for these */ -/* The first four, i.e. a SET to any YWK, */ -/* includes the setting of the CTCE_WAIT bit. */ -#define SET_CTCE_YWP(c) (c=(((c)&0xF8)|0x00)) -#define SET_CTCE_YWC(c) (c=(((c)&0xF8)|0x01)) -#define SET_CTCE_YWR(c) (c=(((c)&0xF8)|0x02)) -#define SET_CTCE_YWW(c) (c=(((c)&0xF8)|0x03)) +/* Useful SET macros for the above. */ #define SET_CTCE_YAV(c) (c=(((c)&0xF8)|0x04)) #define SET_CTCE_YNR(c) (c=(((c)&0xF8)|0x05)) -#define SET_CTCE_XWK(c) (c=(((c)&0xF8)|0x06)) -#define SET_CTCE_XIP(c) (c=((c)|0x07)) /* One letter CTC state abbreviations */ static char *CTCE_StaStr[8] = {"P", "C", "R", "W", "A", "N", "X", "I"}; @@ -356,6 +347,14 @@ static char *CTCE_StaStr[8] = {"P", "C", "R", "W", "A", "N", "X", "I"}; /* in the device configuration statement. */ #define CTCE_MTU_MIN ( (int)( 61578 + sizeof(CTCE_SOKPFX) + sizeof(U16 /* sCount */) ) ) +#define CTCE_RESET_TYPE \ + ( ( pDEVBLK->scsw.flag2 & ( SCSW2_FC_HALT ) ) ) ? _("Halt Reset") : _("") \ + , ( ( pDEVBLK->scsw.flag2 & ( SCSW2_FC_CLEAR ) ) ) ? _("Clear Reset") : _("") \ + , ( ( ! ( pDEVBLK->scsw.flag2 & ( SCSW2_FC_HALT | SCSW2_FC_CLEAR ) ) ) && \ + ! ( IS_CTCE_YWK( pDEVBLK->ctcexState ) | IS_CTCE_YWK( pDEVBLK->ctceyState ) ) ) ? _("System Reset") : _("") \ + , ( ( ! ( pDEVBLK->scsw.flag2 & ( SCSW2_FC_HALT | SCSW2_FC_CLEAR ) ) ) && \ + ( IS_CTCE_YWK( pDEVBLK->ctcexState ) | IS_CTCE_YWK( pDEVBLK->ctceyState ) ) ) ? _("Selective Reset") : _("") + /**********************************************************************/ /* A summary of the Channel-to-Channel command operations this CTCE */ /* device emulates can be found in IBM publications SA22-7203-00 in */ @@ -416,7 +415,6 @@ static char *CTCE_StaStr[8] = {"P", "C", "R", "W", "A", "N", "X", "I"}; #define ACDSM { A, CSW_CE | CSW_DE , 0, CTCE_SEND | CTCE_MATCH } #define ACDS { A, CSW_CE | CSW_DE , 0, CTCE_SEND } #define AUCS { A, CSW_UC , 0, CTCE_SEND } -#define CDSM { U, CSW_CE | CSW_DE , 0, CTCE_SEND | CTCE_MATCH } #define CDS { U, CSW_CE | CSW_DE , 0, CTCE_SEND } #define CD { U, CSW_CE | CSW_DE , 0, 0 } #define B { U, CSW_BUSY , 0, 0 } @@ -439,12 +437,12 @@ const CTCE_Fsm[16][8] = { /* CTL */ {CC_SMW , BA , BA , BA ,C__S_WA, UCS , B , B }, /* RED */ {R__SMW , BA , BA ,ACDSM ,R__S_WA, UCS , B , B }, /* WRT */ {W__SMW , BA ,ACDSM , BA ,W__S_WA, UCS , B , B }, -/* SCB */ { CD ,ACDSM , CD , CD , CD , UCS , B , B }, +/* SCB */ { CD ,ACDSM , CD , CD ,ACDS , UCS , B , B }, /* nus */ { UC , UC , UC , UC , UC , UC , B , B }, /* RBK */ {R__SMW , BA , BA ,ACDSM ,R__S_WA, UCS , B , B }, /* WEF */ { CDS , BA ,ACDSM , BA , CDS , UCS , B , B }, /* NOP */ { CD , BA , BA , BA , CD , UC , B , B }, -/* SEM */ { CDS , BA , BA , BA ,ACDS ,AUCS , B , B }, +/* SEM */ { CDS , CDS , CDS , CDS ,ACDS ,AUCS , B , B }, /* C, R, W imply Selective Reset */ /* SAS */ { CD , CD , CD , CD , CD , CD , B , B }, /* SID */ { CD , CD , CD , CD , CD , CD , B , B }, @@ -452,7 +450,7 @@ const CTCE_Fsm[16][8] = { /* inv */ { UC , UC , UC , UC , UC , UC , B , B }, /* CB0 */ { UC , UC , UC , UC , UC , UC , B , B }, -/* SBM */ { CDS , BA , BA , BA ,ACDS ,AUCS , B , B } +/* SBM */ { CDS , CDS , CDS , CDS ,ACDS ,AUCS , B , B } /* C, R, W imply Selective Reset */ }; #undef P @@ -475,7 +473,6 @@ const CTCE_Fsm[16][8] = { #undef ACDSM #undef ACDS #undef AUCS -#undef CDSM #undef CDS #undef CD #undef B @@ -626,7 +623,7 @@ DEVHND ctce_device_hndinfo = NULL, /* Device End channel pgm */ NULL, /* Device Resume channel pgm */ NULL, /* Device Suspend channel pgm */ - &CTCE_HaltOrClear, /* Device Halt channel pgm */ + &CTCE_Reset, /* Device Halt channel pgm */ NULL, /* Device Read */ NULL, /* Device Write */ NULL, /* Device Query used */ @@ -1898,6 +1895,7 @@ void CTCE_ExecuteCCW( DEVBLK* pDEVBLK, BYTE bCode, CTCE_Info.sent = 0; CTCE_Info.con_lost = 0; CTCE_Info.con_won = 0; + CTCE_Info.sel_reset = 0; CTCE_Info.sok_buf_len = 0; CTCE_Info.state_x_prev = pDEVBLK->ctcexState; CTCE_Info.state_y_prev = pDEVBLK->ctceyState; @@ -2023,27 +2021,27 @@ void CTCE_ExecuteCCW( DEVBLK* pDEVBLK, BYTE bCode, // Copy control command byte in x command register pDEVBLK->ctcexCmd = bCode; - // A valid Set Extended / Base Mode (SEM / SBM) command will have - // an immediate effect so that it can from then on be handled as - // a NOP command. Valid means x-state Available and y-state - // not in Working(D) with Control, Read or Write (CRW). - // Please note that the Basic to Extended mode switch influences - // the CTCS FSM table indexing which is why this is done up front. - // So we set Extended mode and enforce Available x-state. - if( IS_CTCE_CCW_SEM( pDEVBLK->ctcexCmd ) && - IS_CTCE_YAV( pDEVBLK->ctcexState ) && - !IS_CTCE_CRW( pDEVBLK->ctceyState ) ) - { - pDEVBLK->ctcxmode = 1; - SET_CTCE_YAV( pDEVBLK->ctcexState ); - } - - // Or we just set Base mode. - else if( IS_CTCE_CCW_SBM( pDEVBLK->ctcexCmd ) && - IS_CTCE_YAV( pDEVBLK->ctcexState ) && - !IS_CTCE_CRW( pDEVBLK->ctceyState ) ) - { - pDEVBLK->ctcxmode = 0; + // A valid Set Extended / Base Mode (SEM / SBM) command implies a + // Reset took place immediately prior to it, for which currently + // no explicit device handler exit capability exists (i.e. in + // "channel.c"). Hence that we implement this here, as well + // when a SEM / SBM instruction is received at the other (y-)side. + // Because the 'extended mode' influences the FSM state, the SEM + // command immediately needs to result in the 'available' state. + if( IS_CTCE_CCW_SEM( pDEVBLK->ctcexCmd ) || + IS_CTCE_CCW_SBM( pDEVBLK->ctcexCmd ) ) + { + CTCE_Info.sel_reset = ( ( IS_CTCE_YWK( pDEVBLK->ctcexState ) | IS_CTCE_YWK( pDEVBLK->ctceyState ) ) ? 1 : 0 ) ; + CTCE_Reset( pDEVBLK ); + if( IS_CTCE_CCW_SEM( pDEVBLK->ctcexCmd ) ) + { + pDEVBLK->ctcxmode = 1; + SET_CTCE_YAV( pDEVBLK->ctcexState ); + } + else + { + pDEVBLK->ctcxmode = 0; + } } // The new X-state and transition actions are derived from the FSM table. @@ -2053,21 +2051,9 @@ void CTCE_ExecuteCCW( DEVBLK* pDEVBLK, BYTE bCode, *pUnitStat = CTCE_Fsm[CTCE_CMD( pDEVBLK->ctcexCmd )][CTCE_X_STATE_FSM_IDX].x_unit_stat; - // CTC CCW programs for z/VM SSI ISFC links have been observed to - // issue a SEM command that may be redundant, after the other side - // has already issued a WRITE. The BUSY+ATTN response to that - // will cause this to happen endlessly, hence that we avoid this - // here. - if( IS_CTCE_CCW_SEM( pDEVBLK->ctcexCmd ) && - IS_CTCE_YAV( pDEVBLK->ctcexState ) && - *pUnitStat == ( CSW_BUSY | CSW_ATTN ) ) - { - *pUnitStat = CSW_CE | CSW_DE; - } - // If a READ or READ_BACKWARD command is received whilst the WEOF // bit is set then the sole case for a Unit Exception applies. - else if( IS_CTCE_WEOF( pDEVBLK->ctcexState ) && + if( IS_CTCE_WEOF( pDEVBLK->ctcexState ) && IS_CTCE_CCW_RDA( pDEVBLK->ctcexCmd ) ) { CLR_CTCE_WEOF( pDEVBLK->ctcexState ); @@ -2173,9 +2159,10 @@ void CTCE_ExecuteCCW( DEVBLK* pDEVBLK, BYTE bCode, } // if( !( CTCE_Info.x_unit_stat & CSW_BUSY ) ) // We merge a Unit Check in case the Y state is Not Ready. - // But only when pUnitStat is still 0 or just Busy (no Attn). + // But only when pUnitStat is still 0 or Unit Check or Busy (no Attn). + // SENSE bit 1 for Intervention Required will be set as well. if( IS_CTCE_YNR( pDEVBLK -> ctceyState ) && - ( ( *pUnitStat & (~ CSW_BUSY ) ) == 0 ) ) + ( ( *pUnitStat & (~ ( CSW_BUSY | CSW_UC ) ) ) == 0 ) ) { *pUnitStat |= CSW_UC; pDEVBLK->sense[0] = SENSE_IR; @@ -2238,7 +2225,7 @@ static int CTCE_Init( DEVBLK *dev, int argc, char *argv[] ) dev->excps = 0; // The halt_device exit is established; in version 4 this is in DEVHND in the ctce_device_hndinfo. -// dev->halt_device = &CTCE_HaltOrClear; +// dev->halt_device = &CTCE_Reset; // Mark both socket file descriptors as not yet connected. dev->fd = -1; @@ -2563,7 +2550,14 @@ static void CTCE_Send( DEVBLK* pDEVBLK, U32 sCount, { WRMSG( HHC05072, "S", /* CTCE: Not all sockets connected: send=%d, receive=%d */ CTCX_DEVNUM( pDEVBLK ), pDEVBLK->fd, pDEVBLK->ctcefd ); +/* PJJ VTAM */ + if( !IS_CTCE_CCW_SCB( pDEVBLK->ctcexCmd ) ) + { + *pUnitStat = 0; + } +/* PJJ VTAM * *pUnitStat = 0; + * PJJ VTAM */ return ; } pCTCE_Info->sent = 1; @@ -2606,6 +2600,14 @@ static void CTCE_Send( DEVBLK* pDEVBLK, U32 sCount, // Write all of this to the other (y-)side. rc = write_socket( pDEVBLK->fd, pDEVBLK->buf, pSokBuf->SndLen ); + // The sending of IOBuf for WRT commands has been completed so we need to + // mark the used device buffer part as free by zeroing the data length field + // as CTCE_RecvThread will wait for this when it receives a WRT command. + if( IS_CTCE_CCW_WRT( pDEVBLK->ctcexCmd ) ) + { + *(U16*)( pDEVBLK->buf + sizeof(CTCE_SOKPFX) ) = 0; + } + if( rc < 0 ) { WRMSG( HHC05074, "E", /* CTCE: Error writing to %s: %s */ @@ -2631,7 +2633,8 @@ static void CTCE_Send( DEVBLK* pDEVBLK, U32 sCount, // in a Working(D) state, then we will need to wait until a // matching command arrives from the other (y-)side. The WAIT // timeout is chosen to be long enough to not timeout over periods - // if inactivity; we experienced up to 6 secs, so we set it to 60. + // if inactivity; we experienced up to exactly 15 minutes following + // (non-matching) PREPARE CCW commands, so we set it to 1000 sec. if( IS_CTCE_WAIT( pCTCE_Info->actions ) ) { // Produce a CTCE Trace logging if requested. @@ -2647,7 +2650,7 @@ static void CTCE_Send( DEVBLK* pDEVBLK, U32 sCount, pCTCE_Info->wait_rc = timed_wait_condition_relative_usecs( &pDEVBLK->ctceEvent, &pDEVBLK->ctceEventLock, - 60000000, + 1000000000, NULL ); pDEVBLK->ctce_sendwaiting = 0; @@ -2726,14 +2729,15 @@ static void CTCE_Send( DEVBLK* pDEVBLK, U32 sCount, } // If the command (by now matched) was a CONTROL command, then this - // side become the contention loser. + // side becomes the contention loser. if( IS_CTCE_CCW_CTL( pDEVBLK->ctcexCmd ) ) { pDEVBLK->ctce_contention_loser = 1; } - // Command collisions never return data. - if( pDEVBLK->ctce_UnitStat == (CSW_BUSY | CSW_ATTN) ) + // Command collisions or resets (CSW_UC) never return data. + if( ( pDEVBLK->ctce_UnitStat == (CSW_BUSY | CSW_ATTN) ) || + ( pDEVBLK->ctce_UnitStat & CSW_UC ) ) { *pResidual = sCount; } @@ -2755,6 +2759,9 @@ static void CTCE_Send( DEVBLK* pDEVBLK, U32 sCount, memcpy( pIOBuf, pDEVBLK->buf + sizeof(CTCE_SOKPFX) + sizeof(pSokBuf->sCount), pSokBuf->sCount ) ; *pResidual = sCount - pSokBuf->sCount; + + // We show the device buffer as being processed by zeroing the data length field. + *(U16*)( pDEVBLK->buf + sizeof(CTCE_SOKPFX) ) = 0; } else { @@ -2790,7 +2797,6 @@ static void* CTCE_RecvThread( void* argp ) obtain_lock( &pDEVBLK->lock ); // Enhanced CTC adapter intiialization for command register and CB - pDEVBLK->ctcexCmd = 0x00; pDEVBLK->ctceyCmd = 0x00; pDEVBLK->ctceyCmdSCB = 0x00; @@ -2834,8 +2840,24 @@ static void* CTCE_RecvThread( void* argp ) return NULL; // make compiler happy } - // Changes to DEVBLK must be lock protected as other threads might update as well. + // Commands sent by the other (y-)side most likely cause DEVBLK + // changes to our (x-)side and thus need to be lock protected. + // The write command data in the socket buffer needs to be copied + // into the device buffer, but we can only do this if that buffer + // is empty; we may have to wait for that to be the case. obtain_lock(&pDEVBLK->lock); + if( IS_CTCE_CCW_WRT( pSokBuf->CmdReg ) ) + { + for( CTCE_Info.busy_waits = 0; + ( *(U16*)( pDEVBLK->buf + sizeof(CTCE_SOKPFX) ) != 0 ) && + ( CTCE_Info.busy_waits <= 20 ) ; + CTCE_Info.busy_waits++ ) + { + release_lock( &pDEVBLK->lock ); + usleep( 200 ); + obtain_lock( &pDEVBLK->lock ); + } + } // Check for other error condition if( iLength < 0 ) @@ -2868,10 +2890,19 @@ static void* CTCE_RecvThread( void* argp ) CTCE_Info.state_x_prev = pDEVBLK->ctcexState; CTCE_Info.state_y_prev = pDEVBLK->ctceyState; - // Set extended mode from the other side also applies to this side. - if( IS_CTCE_CCW_SEM( pDEVBLK->ctceyCmd ) ) + // SEM / SBM commands imply the other (y-)side performed a + // Reset (Selective or otherwise), which the (x-)side needs + // to act on as well. SEM also requires 'extended' mode + // to be set on this side as well. + if( IS_CTCE_CCW_SEM( pSokBuf->CmdReg ) || + IS_CTCE_CCW_SBM( pSokBuf->CmdReg ) ) { - pDEVBLK->ctcxmode = 1; + CTCE_Info.sel_reset = ( ( IS_CTCE_YWK( pDEVBLK->ctcexState ) | IS_CTCE_YWK( pDEVBLK->ctceyState ) ) ? 1 : 0 ) ; + CTCE_Reset( pDEVBLK ); + if( IS_CTCE_CCW_SEM( pSokBuf->CmdReg ) ) + { + pDEVBLK->ctcxmode = 1; + } } // The command received from the other (y-)side may cause a @@ -2891,8 +2922,6 @@ static void* CTCE_RecvThread( void* argp ) // crossing each other in xfer to the other side (e.g. two // READ or WRITE commands). Both sides would respond with // a Busy+Attention device status. - // (Command collision wass never experienced with GRS or XCF - // CCP programs, but occurred first with z/VM SSI ISCF links.) if( ( CTCE_Info.x_unit_stat == ( CSW_BUSY | CSW_ATTN ) ) && IS_CTCE_CCW_DEP( pSokBuf->CmdReg ) ) { @@ -2907,7 +2936,7 @@ static void* CTCE_RecvThread( void* argp ) // side as if a matching command was received, but // only after re-instating the original FSM state // and ensuring that the required Busy+Attention - // device status will bereturned. Effectively, + // device status will be returned. Effectively, // this is a contention lost situation. CTCE_Info.con_lost = 1; pDEVBLK->ctcexState = CTCE_Info.state_new; @@ -2985,17 +3014,21 @@ static void* CTCE_RecvThread( void* argp ) // condition so that CTCE_Send no longer needs to wait. if( IS_CTCE_MATCH( CTCE_Info.actions ) ) { - obtain_lock( &pDEVBLK->ctceEventLock ); - signal_condition( &pDEVBLK->ctceEvent ); - release_lock( &pDEVBLK->ctceEventLock ); - // Both sides return to the available state. + // Our (x-)side returns to the available state, but the + // other (y-)side is decided for via the FSM table entry. SET_CTCE_YAV( pDEVBLK->ctcexState ); - SET_CTCE_YAV( pDEVBLK->ctceyState ); + pDEVBLK->ctceyState = CTCE_Info.state_new; // All matching commands result in a final UnitStat // CE + DE stat at the local device end. ctce_recv_mods_UnitStat = CSW_CE | CSW_DE; + pDEVBLK->ctce_UnitStat = CSW_CE | CSW_DE; + + // We now signal CTCE_Send that the MATCHing command has been received. + obtain_lock( &pDEVBLK->ctceEventLock ); + signal_condition( &pDEVBLK->ctceEvent ); + release_lock( &pDEVBLK->ctceEventLock ); } // if( IS_CTCE_MATCH( CTCE_Info.actions ) ) // If the other (y-)side sent us a Device-End status @@ -3010,6 +3043,8 @@ static void* CTCE_RecvThread( void* argp ) // Reset sense byte 0 bits 1 and 7. pDEVBLK->sense[0] &= ~( SENSE_IR | SENSE_OC ); + // Another attention would be harmful and is not needed. + CLR_CTCE_ATTN( CTCE_Info.actions ); } // If the other (y-)side sent us a command that may require @@ -3129,27 +3164,28 @@ static void* CTCE_RecvThread( void* argp ) } // -// CTCE_HaltOrClear -- Halt device or Clear Subchannel for CTCE adapter +// CTCE_Reset -- Selective Reset or System Reset a CTCE adapter device // -static BYTE CTCE_HaltOrClear( DEVBLK* pDEVBLK ) +static BYTE CTCE_Reset( DEVBLK* pDEVBLK ) { BYTE unitstat = 0; - // obtain_lock( &pDEVBLK->lock ) already carried out by caller in channel.c - if (pDEVBLK->ccwtrace || pDEVBLK->ccwstep) - { - // "%1d:%04X CTCE: -| Halt x=%s y=%s" - WRMSG( HHC05078, "I", - CTCX_DEVNUM( pDEVBLK ), - CTCE_StaStr[ pDEVBLK->ctcexState & 0x07 ], - CTCE_StaStr[ pDEVBLK->ctceyState & 0x07 ] ); - } + // The call already did an obtain_lock( &pDEVBLK->lock ) + // which is either in channel.c or earlier in here. + // Reset the y-command to 0 and set sense bit 1, and + // clear any WEOF state. + pDEVBLK->ctceyCmdSCB = 0x00; + pDEVBLK->sense[0] |= SENSE_IR; + CLR_CTCE_WEOF( pDEVBLK->ctcexState ); + + // Initialize the device buffer by zeroing the data length field. + *(U16*)( pDEVBLK->buf + sizeof(CTCE_SOKPFX) ) = 0; - // Halt device for a CTCE device is a selective reset, - // requiring our (x-)side to cancel any Working(D) wait state - // if needed, and to return to the not ready state. - if (IS_CTCE_YWK( pDEVBLK->ctcexState )) + // A selective reset requires cancelling any Working(D) wait state + // at our (x-)side, and to return to the not ready state. Also, + // sense bit 7 needs to be set, and unit status set to CE+DE+UC. + if( IS_CTCE_YWK( pDEVBLK->ctcexState ) ) { obtain_lock( &pDEVBLK->ctceEventLock ); { @@ -3161,10 +3197,25 @@ static BYTE CTCE_HaltOrClear( DEVBLK* pDEVBLK ) } release_lock( &pDEVBLK->ctceEventLock ); - CLR_CTCE_ALLF( pDEVBLK->ctcexState ); - SET_CTCE_YNR( pDEVBLK->ctcexState ); + CLR_CTCE_ALLF(pDEVBLK->ctcexState); + SET_CTCE_YNR(pDEVBLK->ctcexState); + pDEVBLK->sense[0] |= SENSE_OC; + pDEVBLK->ctce_UnitStat = CSW_CE | CSW_DE | CSW_UC; + } + if( IS_CTCE_YWK( pDEVBLK->ctceyState ) ) + { + SET_CTCE_YAV( pDEVBLK->ctceyState ); } + // Produce a CTCE Trace logging if requested. + if( pDEVBLK->ccwtrace || pDEVBLK->ccwstep ) + { + WRMSG( HHC05078, "I", /* CTCE: -| %s%s%s%s x=%s y=%s cmd=%s*/ + CTCX_DEVNUM( pDEVBLK ), CTCE_RESET_TYPE, + CTCE_StaStr[CTCE_STATE( pDEVBLK->ctcexState )], + CTCE_StaStr[CTCE_STATE( pDEVBLK->ctceyState )], + CTCE_CmdStr[CTCE_CMD( pDEVBLK->ctcexCmd )] ); + } return unitstat; } @@ -3242,6 +3293,41 @@ void CTCE_Trace( const DEVBLK* pDEVBLK, ctce_trace_xtra[0] = '\0' ; + // An SEM / SBM command implies a Reset happened immediately prior + // to it, which we report on. + if( eCTCE_Cmd_Xfr == CTCE_RCV ) + { + ctce_Cmd = pDEVBLK->ctceyCmd; + } + else + { + ctce_Cmd = pDEVBLK->ctcexCmd; + } + if( IS_CTCE_CCW_SEM( ctce_Cmd ) || + IS_CTCE_CCW_SBM( ctce_Cmd ) ) + { + if( pDEVBLK->scsw.flag2 & ( SCSW2_FC_HALT ) ) + { + strlcat( ctce_trace_xtra, " Halt Reset", sizeof( ctce_trace_xtra ) ); + } + else if ( pDEVBLK->scsw.flag2 & ( SCSW2_FC_CLEAR ) ) + { + strlcat( ctce_trace_xtra, " Clear Reset", sizeof( ctce_trace_xtra ) ); + } + else if ( ! pCTCE_Info->sel_reset ) + { + strlcat( ctce_trace_xtra, " System Reset", sizeof( ctce_trace_xtra ) ); + } + else if ( pCTCE_Info->sel_reset ) + { + strlcat( ctce_trace_xtra, " Selective Reset", sizeof( ctce_trace_xtra ) ); + } + else + { + strlcat( ctce_trace_xtra, "??? ", sizeof( ctce_trace_xtra ) ); + } + } + // The other side's entering a "Working" state may // require an Attention or not, which will be shown. // Please note that the CTCE_ACTIONS_PRT macro in @@ -3506,4 +3592,4 @@ int CTCE_Connect_Timeout(int sockfd, // Switch back to original non-blocking mode and return socket_set_blocking_mode( sockfd, 1 ) ; return rc; -} +} \ No newline at end of file diff --git a/msgenu.h b/msgenu.h index 78842e7b9..514a20036 100644 --- a/msgenu.h +++ b/msgenu.h @@ -2227,7 +2227,7 @@ LOGM_DLL_IMPORT int panel_command_capture( char* cmd, char** resp ); #define HHC05075 "%1d:%04X CTCE: Halt or Clear Recognized" #define HHC05076 "%1d:%04X CTCE: Connection closed; %"PRIu64" MB received in %"PRIu64" packets from %s" #define HHC05077 "%1d:%04X CTCE: Error reading from %s: %s" -#define HHC05078 "%1d:%04X CTCE: -| Halt x=%s y=%s" +#define HHC05078 "%1d:%04X CTCE: -| %s%s%s%s x=%s y=%s cmd=%s" #define HHC05079 "%1d:%04X CTCE: %s %.6s #%04X cmd=%s=%02X xy=%.2s%s%.2s l=%04X k=%08X %s%s%s%s%s%s" // range 05100 - 05199 available