Files
Rhialto The M 8175ad07bc Fix UB when calling ctype functions. (#570)
Compiling Hercules with gcc 10 produces many warnings like this one:
```
  CC       hao.lo
In file included from /usr/include/ctype.h:97,
                 from hstdinc.h:117,
                 from hao.c:17:
hao.c: In function 'hao_message':
hao.c:812:37: warning: array subscript has type 'char' [-Wchar-subscripts]
  812 |                         if (isdigit(p[2]))
      |                             ^
```
Gcc should really present these as compile time errors, since each and every
one represents a potential case of Undefined Behaviour.
I changed (almost) all of these calls, except a few where the parameter was an
int that just came from a getc()-type function.
2023-06-12 11:43:50 -07:00

666 lines
23 KiB
C

/* MPC.C (C) Copyright Jan Jaeger, 2010-2012 */
/* (C) Copyright Ian Shorter, 2011-2012 */
/* (C) Copyright Harold Grovesteen, 2011-2012 */
/* MPC (Multi-Path Channel) functions */
/* */
/* Released under "The Q Public License Version 1" */
/* (http://www.hercules-390.org/herclic.html) as modifications to */
/* Hercules. */
/* This implementation is based on the S/390 Linux implementation */
#include "hstdinc.h"
#define _MPC_C_
#define _HENGINE_DLL_
#include "hercules.h"
#include "mpc.h"
/*--------------------------------------------------------------------*/
/* mpc_point_ipa(): */
/*--------------------------------------------------------------------*/
DLL_EXPORT MPC_IPA* mpc_point_ipa( DEVBLK* pDEVBLK, MPC_TH* pMPC_TH, MPC_RRH* pMPC_RRH )
{
MPC_PH* pMPC_PH;
MPC_IPA* pMPC_IPA;
U32 uOffData;
U16 uOffPH;
UNREFERENCED( pDEVBLK );
// Point to the MPC_PH.
FETCH_HW( uOffPH, pMPC_RRH->offph );
pMPC_PH = (MPC_PH*)((BYTE*)pMPC_RRH + uOffPH);
// Get the length of and point to the data referenced by the
// MPC_PH. The data contain a MPC_IPA.
FETCH_FW( uOffData, pMPC_PH->offdata );
pMPC_IPA = (MPC_IPA*)((BYTE*)pMPC_TH + uOffData);
return pMPC_IPA;
} /* End function mpc_point_ipa() */
/*--------------------------------------------------------------------*/
/* mpc_point_puk(): */
/*--------------------------------------------------------------------*/
DLL_EXPORT MPC_PUK* mpc_point_puk( DEVBLK* pDEVBLK, MPC_TH* pMPC_TH, MPC_RRH* pMPC_RRH )
{
MPC_PH* pMPC_PH;
MPC_PUK* pMPC_PUK;
U32 uOffData;
U16 uOffPH;
UNREFERENCED( pDEVBLK );
// Point to the MPC_PH.
FETCH_HW( uOffPH, pMPC_RRH->offph );
pMPC_PH = (MPC_PH*)((BYTE*)pMPC_RRH + uOffPH);
// Get the length of and point to the data referenced by the
// MPC_PH. The data contain a MPC_PUK and one or more MPC_PUSs.
FETCH_FW( uOffData, pMPC_PH->offdata );
pMPC_PUK = (MPC_PUK*)((BYTE*)pMPC_TH + uOffData);
return pMPC_PUK;
} /* End function mpc_point_puk() */
/*--------------------------------------------------------------------*/
/* mpc_point_pus(): */
/*--------------------------------------------------------------------*/
/* Return a pointer to the MPC_PUS of the required type. If the */
/* required type is not found a null pointer is returned. Although */
/* never seen, if multiple MPC_PUS of the required type exist, only */
/* the first MPC_PUS of the required type will ever be returned. */
DLL_EXPORT MPC_PUS* mpc_point_pus( DEVBLK* pDEVBLK, MPC_PUK* pMPC_PUK, BYTE bType )
{
MPC_PUS* pMPC_PUS;
int iTotLenPUS;
U16 uTotLenPUS;
U16 uLenPUS;
U16 uLenPUK;
UNREFERENCED( pDEVBLK );
/* Get the length of the MPC_PUK, the total length of the */
/* following MPC_PUSs, then point to the first MPC_PUS. */
FETCH_HW( uLenPUK, pMPC_PUK->length );
FETCH_HW( uTotLenPUS, pMPC_PUK->lenpus );
iTotLenPUS = uTotLenPUS;
pMPC_PUS = (MPC_PUS*)((BYTE*)pMPC_PUK + uLenPUK);
/* Find the required MPC_PUS. */
while( iTotLenPUS > 0 )
{
/* Ensure there are at least the first 4-bytes of an MPC_PUS. */
if( iTotLenPUS < 4 )
return NULL;
/* Get the length of the MPC_PUS. */
FETCH_HW( uLenPUS, pMPC_PUS->length );
if( uLenPUS == 0 ) /* Better safe than sorry */
return NULL;
/* Ensure there is the whole of the MPC_PUS. */
if( iTotLenPUS < uLenPUS )
return NULL;
/* Check for the required MPC_PUS. */
if( pMPC_PUS->type == bType )
return pMPC_PUS;
/* Point to the next MPC_PUS. */
pMPC_PUS = (MPC_PUS*)((BYTE*)pMPC_PUS + uLenPUS);
iTotLenPUS -= uLenPUS;
}
return NULL;
} /* End function mpc_point_pus() */
/*--------------------------------------------------------------------*/
/* mpc_display_description(): */
/*--------------------------------------------------------------------*/
DLL_EXPORT void mpc_display_description( DEVBLK* pDEVBLK, char* pDesc )
{
/* Display description, if one has been provided. */
if( pDesc )
{
if( pDEVBLK )
{
// HHC03983 "%1d:%04X %s: %s
WRMSG(HHC03983, "D", SSID_TO_LCSS(pDEVBLK->ssid), pDEVBLK->devnum, pDEVBLK->typname, pDesc );
}
else
{
// HHC03984 "%s"
WRMSG(HHC03984, "D", pDesc );
}
}
return;
} /* End function mpc_display_description() */
/*--------------------------------------------------------------------*/
/* mpc_display_stuff() */
/*--------------------------------------------------------------------*/
/* Function to display storage. */
DLL_EXPORT void mpc_display_stuff( DEVBLK* pDEVBLK, char* cWhat, BYTE* pAddr, int iLen, BYTE bDir )
{
int offset;
unsigned int i;
u_char c = '\0';
u_char e = '\0';
char print_ascii[17];
char print_ebcdic[17];
char print_line[64];
char tmp[32];
for( offset = 0; offset < iLen; )
{
memset( print_ascii, ' ', sizeof(print_ascii)-1 ); /* set to spaces */
print_ascii[sizeof(print_ascii)-1] = '\0'; /* with null termination */
memset( print_ebcdic, ' ', sizeof(print_ebcdic)-1 ); /* set to spaces */
print_ebcdic[sizeof(print_ebcdic)-1] = '\0'; /* with null termination */
memset( print_line, 0, sizeof( print_line ) );
MSGBUF( print_line, "+%4.4X%c ", offset, bDir );
for( i = 0; i < 16; i++ )
{
c = *pAddr++;
if( offset < iLen )
{
MSGBUF(tmp, "%2.2X", c );
tmp[sizeof(tmp)-1] = '\0';
STRLCAT( print_line, tmp );
print_ebcdic[i] = print_ascii[i] = '.';
e = guest_to_host( c );
if( isprint( (unsigned char)e ) )
print_ebcdic[i] = e;
if( isprint( (unsigned char)c ) )
print_ascii[i] = c;
}
else
{
STRLCAT( print_line, " " );
}
offset++;
if( ( offset & 3 ) == 0 )
{
STRLCAT( print_line, " " );
}
}
if( pDEVBLK )
{
// HHC03981 "%1d:%04X %s: %s: %s %s %s"
WRMSG(HHC03981, "D", SSID_TO_LCSS(pDEVBLK->ssid), pDEVBLK->devnum, pDEVBLK->typname,
cWhat, print_line, print_ascii, print_ebcdic );
}
else
{
// HHC03982 "%s: %s %s %s"
WRMSG(HHC03982, "D", cWhat, print_line, print_ascii, print_ebcdic );
}
}
return;
} /* End function mpc_display_stuff() */
/*--------------------------------------------------------------------*/
/* mpc_display_th(): Display Transport Header (MPC_TH) */
/*--------------------------------------------------------------------*/
DLL_EXPORT void mpc_display_th( DEVBLK* pDEVBLK, MPC_TH* pMPC_TH, BYTE bDir )
{
U32 uOffRRH;
// Display the MPC_TH.
FETCH_FW( uOffRRH, pMPC_TH->offrrh );
mpc_display_stuff( pDEVBLK, "TH ", (BYTE*)pMPC_TH, uOffRRH, bDir );
return;
} /* End function mpc_display_th() */
/*--------------------------------------------------------------------*/
/* mpc_display_rrh(): Display Request/Response Header (MPC_RRH) */
/*--------------------------------------------------------------------*/
DLL_EXPORT void mpc_display_rrh( DEVBLK* pDEVBLK, MPC_RRH* pMPC_RRH, BYTE bDir )
{
U16 uOffPH;
// Display the MPC_RRH.
FETCH_HW( uOffPH, pMPC_RRH->offph );
mpc_display_stuff( pDEVBLK, "RRH", (BYTE*)pMPC_RRH, uOffPH, bDir );
return;
} /* End function mpc_display_rrh() */
/*--------------------------------------------------------------------*/
/* mpc_display_ph(): Display Protocol Data Unit Header (MPC_PH) */
/*--------------------------------------------------------------------*/
DLL_EXPORT void mpc_display_ph( DEVBLK* pDEVBLK, MPC_PH* pMPC_PH, BYTE bDir )
{
// Display the MPC_PH.
mpc_display_stuff( pDEVBLK, "PH ", (BYTE*)pMPC_PH, SIZE_PH, bDir );
return;
} /* End function mpc_display_ph() */
/*--------------------------------------------------------------------*/
/* mpc_display_rrh_and_puk(): */
/*--------------------------------------------------------------------*/
/* In all cases that have been seen, on both OSA and PTP, when */
/* MPC_RRH->proto == PROTOCOL_UNKNOWN (0x7E), the MPC_RRH is followed */
/* by a single MPC_PH, which is followed by a single MPC_PUK, which */
/* is followed by up to four MPC_PUSs. */
DLL_EXPORT void mpc_display_rrh_and_puk( DEVBLK* pDEVBLK, MPC_TH* pMPC_TH, MPC_RRH* pMPC_RRH, BYTE bDir )
{
MPC_PH* pMPC_PH;
MPC_PUK* pMPC_PUK;
MPC_PUS* pMPC_PUS;
int iTotLenPUS;
U32 uOffData;
U16 uTotLenPUS;
U16 uLenPUS;
U16 uLenPUK;
U16 uOffPH;
// Display the MPC_RRH.
FETCH_HW( uOffPH, pMPC_RRH->offph );
mpc_display_stuff( pDEVBLK, "RRH", (BYTE*)pMPC_RRH, uOffPH, bDir );
// Point to and display the MPC_PH.
pMPC_PH = (MPC_PH*)((BYTE*)pMPC_RRH + uOffPH);
mpc_display_stuff( pDEVBLK, "PH ", (BYTE*)pMPC_PH, SIZE_PH, bDir );
// Get the length of and point to the data referenced by the
// MPC_PH. The data contain a MPC_PUK and one or more MPC_PUSs.
FETCH_FW( uOffData, pMPC_PH->offdata );
pMPC_PUK = (MPC_PUK*)((BYTE*)pMPC_TH + uOffData);
// Display the MPC_PUK.
FETCH_HW( uLenPUK, pMPC_PUK->length );
mpc_display_stuff( pDEVBLK, "PUK", (BYTE*)pMPC_PUK, uLenPUK, bDir );
// Get the total length of the following MPC_PUSs, then point to
// the first MPC_PUS.
FETCH_HW( uTotLenPUS, pMPC_PUK->lenpus );
iTotLenPUS = uTotLenPUS;
pMPC_PUS = (MPC_PUS*)((BYTE*)pMPC_PUK + uLenPUK);
// Display all of the MPC_PUSs.
while( iTotLenPUS > 0 )
{
// Ensure there are at least the first 4-bytes of the MPC_PUS.
if( iTotLenPUS < 4 )
{
mpc_display_stuff( pDEVBLK, "???", (BYTE*)pMPC_PUS, iTotLenPUS, bDir );
break;
}
// Get the length of the MPC_PUS.
FETCH_HW( uLenPUS, pMPC_PUS->length );
if( uLenPUS == 0 ) /* Better safe than sorry */
{
mpc_display_stuff( pDEVBLK, "???", (BYTE*)pMPC_PUS, iTotLenPUS, bDir );
break;
}
// Ensure there is the whole of the MPC_PUS.
if( iTotLenPUS < uLenPUS )
{
mpc_display_stuff( pDEVBLK, "???", (BYTE*)pMPC_PUS, iTotLenPUS, bDir );
break;
}
// Display the MPC_PUS.
mpc_display_stuff( pDEVBLK, "PUS", (BYTE*)pMPC_PUS, uLenPUS, bDir );
// Point to the next MPC_PUS
pMPC_PUS = (MPC_PUS*)((BYTE*)pMPC_PUS + uLenPUS);
iTotLenPUS -= uLenPUS;
}
return;
} /* End function mpc_display_rrh_and_puk() */
/*--------------------------------------------------------------------*/
/* mpc_display_rrh_and_pix(): */
/*--------------------------------------------------------------------*/
/* In all cases that have been seen, only on PTP, when MPC_RRH->type */
/* == RRH_TYPE_IPA (0xC1) and MPC_RRH->proto == PROTOCOL_LAYER2 */
/* (0x08), the MPC_RRH is followed by a single MPC_PH, which is */
/* followed by a single MPC_PIX. */
DLL_EXPORT void mpc_display_rrh_and_pix( DEVBLK* pDEVBLK, MPC_TH* pMPC_TH, MPC_RRH* pMPC_RRH, BYTE bDir )
{
MPC_PH* pMPC_PH;
MPC_PIX* pMPC_PIX;
U32 uOffData;
U32 uLenData;
U16 uOffPH;
// Display the MPC_RRH.
FETCH_HW( uOffPH, pMPC_RRH->offph );
mpc_display_stuff( pDEVBLK, "RRH", (BYTE*)pMPC_RRH, uOffPH, bDir );
// Point to and display the MPC_PH.
pMPC_PH = (MPC_PH*)((BYTE*)pMPC_RRH + uOffPH);
mpc_display_stuff( pDEVBLK, "PH ", (BYTE*)pMPC_PH, SIZE_PH, bDir );
// Point to and display the MPC_PIX.
FETCH_F3( uLenData, pMPC_PH->lendata );
FETCH_FW( uOffData, pMPC_PH->offdata );
pMPC_PIX = (MPC_PIX*)((BYTE*)pMPC_TH + uOffData);
mpc_display_stuff( pDEVBLK, "PIX", (BYTE*)pMPC_PIX, uLenData, bDir );
return;
} /* End function mpc_display_rrh_and_pix() */
/*--------------------------------------------------------------------*/
/* mpc_display_rrh_and_ipa(): */
/*--------------------------------------------------------------------*/
DLL_EXPORT void mpc_display_rrh_and_ipa( DEVBLK* pDEVBLK, MPC_TH* pMPC_TH, MPC_RRH* pMPC_RRH, BYTE bDir )
{
MPC_PH* pMPC_PH;
MPC_IPA* pMPC_IPA;
BYTE* pMPC_IPA_CMD;
U32 uOffData;
U32 uLenData;
U16 uOffPH;
int iLenIPA;
int iLenCmd;
// Display the MPC_RRH.
FETCH_HW( uOffPH, pMPC_RRH->offph );
mpc_display_stuff( pDEVBLK, "RRH", (BYTE*)pMPC_RRH, uOffPH, bDir );
// Point to and display the MPC_PH.
pMPC_PH = (MPC_PH*)((BYTE*)pMPC_RRH + uOffPH);
mpc_display_stuff( pDEVBLK, "PH ", (BYTE*)pMPC_PH, SIZE_PH, bDir );
/* Point to and display the MPC_IPA (and commands, if any). */
FETCH_F3( uLenData, pMPC_PH->lendata );
FETCH_FW( uOffData, pMPC_PH->offdata );
if( uLenData > sizeof(MPC_IPA) )
{
iLenIPA = sizeof(MPC_IPA);
iLenCmd = uLenData - sizeof(MPC_IPA);
}
else
{
iLenIPA = uLenData;
iLenCmd = 0;
}
pMPC_IPA = (MPC_IPA*)((BYTE*)pMPC_TH + uOffData);
mpc_display_stuff( pDEVBLK, "IPA", (BYTE*)pMPC_IPA, iLenIPA, bDir );
if( iLenCmd )
{
pMPC_IPA_CMD = (BYTE*)pMPC_IPA + iLenIPA;
mpc_display_stuff( pDEVBLK, "Cmd", (BYTE*)pMPC_IPA_CMD, iLenCmd, bDir );
}
return;
} /* End function mpc_display_rrh_and_ipa() */
/*--------------------------------------------------------------------*/
/* mpc_display_rrh_and_pkt(): */
/*--------------------------------------------------------------------*/
DLL_EXPORT void mpc_display_rrh_and_pkt( DEVBLK* pDEVBLK, MPC_TH* pMPC_TH, MPC_RRH* pMPC_RRH, BYTE bDir, int iLimit )
{
MPC_PH* pMPC_PH;
U16 uNumPH;
U16 uOffPH;
int iForPH;
int iDone;
U32 uLenData;
U32 uOffData;
BYTE* pData;
/* Display the MPC_RRH.*/
FETCH_HW( uOffPH, pMPC_RRH->offph );
mpc_display_stuff( pDEVBLK, "RRH", (BYTE*)pMPC_RRH, uOffPH, bDir );
/* Display the MPC_PH(s). */
FETCH_HW( uNumPH, pMPC_RRH->numph );
pMPC_PH = (MPC_PH*)((BYTE*)pMPC_RRH + uOffPH);
for( iForPH = 1; iForPH <= uNumPH; iForPH++ )
{
mpc_display_stuff( pDEVBLK, "PH ", (BYTE*)pMPC_PH, SIZE_PH, bDir );
pMPC_PH = (MPC_PH*)((BYTE*)pMPC_PH + SIZE_PH);
}
/* Display the data referenced by the MPC_PH(s). */
/* if limit is negative or a silly number, don't display the */
/* data. If limit is zero, display all of the data, otherwise */
/* limit the length of the data displayed. */
iDone = 0;
if( iLimit >= 0 && iLimit <= 65535 )
{
pMPC_PH = (MPC_PH*)((BYTE*)pMPC_RRH + uOffPH);
for( iForPH = 1; iForPH <= uNumPH; iForPH++ )
{
FETCH_F3( uLenData, pMPC_PH->lendata );
FETCH_FW( uOffData, pMPC_PH->offdata );
pData = (BYTE*)pMPC_TH + uOffData;
if( iLimit > 0 )
{
if( iDone >= iLimit )
break;
if( (int)uLenData > ( iLimit - iDone ) )
uLenData = ( iLimit - iDone );
iDone += uLenData;
}
mpc_display_stuff( pDEVBLK, "Pkt", pData, uLenData, bDir );
pMPC_PH = (MPC_PH*)((BYTE*)pMPC_PH + SIZE_PH);
}
}
return;
} /* End function mpc_display_rrh_and_pkt() */
/*--------------------------------------------------------------------*/
/* mpc_display_rrh_and_pdu(): */
/*--------------------------------------------------------------------*/
DLL_EXPORT void mpc_display_rrh_and_pdu( DEVBLK* pDEVBLK, MPC_TH* pMPC_TH, MPC_RRH* pMPC_RRH, BYTE bDir, int iLimit )
{
MPC_PH* pMPC_PH;
U16 uNumPH;
U16 uOffPH;
int iForPH;
int iDone;
U32 uLenData;
U32 uOffData;
BYTE* pData;
/* Display the MPC_RRH.*/
FETCH_HW( uOffPH, pMPC_RRH->offph );
mpc_display_stuff( pDEVBLK, "RRH", (BYTE*)pMPC_RRH, uOffPH, bDir );
/* Display the MPC_PH(s). */
FETCH_HW( uNumPH, pMPC_RRH->numph );
pMPC_PH = (MPC_PH*)((BYTE*)pMPC_RRH + uOffPH);
for( iForPH = 1; iForPH <= uNumPH; iForPH++ )
{
mpc_display_stuff( pDEVBLK, "PH ", (BYTE*)pMPC_PH, SIZE_PH, bDir );
pMPC_PH = (MPC_PH*)((BYTE*)pMPC_PH + SIZE_PH);
}
/* Display the data referenced by the MPC_PH(s). */
/* if limit is negative or a silly number, don't display the */
/* data. If limit is zero, display all of the data, otherwise */
/* limit the length of the data displayed. */
iDone = 0;
if( iLimit >= 0 && iLimit <= 65535 )
{
pMPC_PH = (MPC_PH*)((BYTE*)pMPC_RRH + uOffPH);
for( iForPH = 1; iForPH <= uNumPH; iForPH++ )
{
FETCH_F3( uLenData, pMPC_PH->lendata );
FETCH_FW( uOffData, pMPC_PH->offdata );
pData = (BYTE*)pMPC_TH + uOffData;
if( iLimit > 0 )
{
if( iDone >= iLimit )
break;
if( (int)uLenData > ( iLimit - iDone ) )
uLenData = ( iLimit - iDone );
iDone += uLenData;
}
mpc_display_stuff( pDEVBLK, "PDU", pData, uLenData, bDir );
pMPC_PH = (MPC_PH*)((BYTE*)pMPC_PH + SIZE_PH);
}
}
return;
} /* End function mpc_display_rrh_and_pdu() */
/*--------------------------------------------------------------------*/
/* mpc_display_osa_iea(): */
/*--------------------------------------------------------------------*/
DLL_EXPORT void mpc_display_osa_iea( DEVBLK* pDEVBLK, MPC_IEA* pMPC_IEA, BYTE bDir, int iSize )
{
/* Display MPC_IEA. */
mpc_display_stuff( pDEVBLK, "IEA", (BYTE*)pMPC_IEA, iSize, bDir );
return;
} /* End function mpc_display_osa_iea() */
/*--------------------------------------------------------------------*/
/* mpc_display_osa_iear(): */
/*--------------------------------------------------------------------*/
DLL_EXPORT void mpc_display_osa_iear( DEVBLK* pDEVBLK, MPC_IEAR* pMPC_IEAR, BYTE bDir, int iSize )
{
/* Display MPC_IEAR. */
mpc_display_stuff( pDEVBLK, "IEAR", (BYTE*)pMPC_IEAR, iSize, bDir );
return;
} /* End function mpc_display_osa_iear() */
/*--------------------------------------------------------------------*/
/* mpc_display_osa_th_etc(): */
/*--------------------------------------------------------------------*/
DLL_EXPORT void mpc_display_osa_th_etc( DEVBLK* pDEVBLK, MPC_TH* pMPC_TH, BYTE bDir, int iLimit )
{
MPC_RRH* pMPC_RRH;
int iForRRH;
U32 uOffRRH;
U16 uNumRRH;
/* Display MPC_TH. */
mpc_display_th( pDEVBLK, pMPC_TH, bDir );
/* Get the number of MPC_RRHs and the displacement from */
/* the start of the MPC_TH to the first (or only) MPC_RRH. */
FETCH_HW( uNumRRH, pMPC_TH->numrrh );
FETCH_FW( uOffRRH, pMPC_TH->offrrh );
/* Process each of the MPC_RRHs. */
for( iForRRH = 1; iForRRH <= uNumRRH; iForRRH++ )
{
/* Point to the first or subsequent MPC_RRH. */
pMPC_RRH = (MPC_RRH*)((BYTE*)pMPC_TH + uOffRRH);
/* Display the MPC_RRH etc. */
if( pMPC_RRH->type == RRH_TYPE_CM ||
pMPC_RRH->type == RRH_TYPE_ULP )
{
/* Display MPC_RRH and following MPC_PUK etc. */
mpc_display_rrh_and_puk( pDEVBLK, pMPC_TH, pMPC_RRH, bDir );
}
else if( pMPC_RRH->type == RRH_TYPE_IPA )
{
/* Display MPC_RRH and following MPC_IPA etc. */
mpc_display_rrh_and_ipa( pDEVBLK, pMPC_TH, pMPC_RRH, bDir );
}
else
{
/* Display MPC_RRH and following PDU. */
mpc_display_rrh_and_pdu( pDEVBLK, pMPC_TH, pMPC_RRH, bDir, iLimit );
}
/* Get the displacement from the start of the MPC_TH to the */
/* next MPC_RRH. pMPC_RRH->offrrh will contain zero if this */
/* is the last MPC_RRH. */
FETCH_FW( uOffRRH, pMPC_RRH->offrrh );
}
return;
} /* End function mpc_display_osa_th_etc() */
/*--------------------------------------------------------------------*/
/* mpc_display_ptp_th_etc(): */
/*--------------------------------------------------------------------*/
DLL_EXPORT void mpc_display_ptp_th_etc( DEVBLK* pDEVBLK, MPC_TH* pMPC_TH, BYTE bDir, int iLimit )
{
MPC_RRH* pMPC_RRH;
int iForRRH;
U32 uOffRRH;
U16 uNumRRH;
/* Display MPC_TH. */
mpc_display_th( pDEVBLK, pMPC_TH, bDir );
/* Get the number of MPC_RRHs and the displacement from */
/* the start of the MPC_TH to the first (or only) MPC_RRH. */
FETCH_HW( uNumRRH, pMPC_TH->numrrh );
FETCH_FW( uOffRRH, pMPC_TH->offrrh );
/* Process each of the MPC_RRHs. */
for( iForRRH = 1; iForRRH <= uNumRRH; iForRRH++ )
{
/* Point to the first or subsequent MPC_RRH. */
pMPC_RRH = (MPC_RRH*)((BYTE*)pMPC_TH + uOffRRH);
/* Display the MPC_RRH etc. */
if( pMPC_RRH->proto == PROTOCOL_LAYER2 &&
pMPC_RRH->type == RRH_TYPE_CM )
{
/* Display MPC_RRH and following packet data. */
mpc_display_rrh_and_pkt( pDEVBLK, pMPC_TH, pMPC_RRH, bDir, iLimit );
}
else if( pMPC_RRH->proto == PROTOCOL_LAYER2 &&
pMPC_RRH->type == RRH_TYPE_IPA )
{
/* Display MPC_RRH and following MPC_PIX etc. */
mpc_display_rrh_and_pix( pDEVBLK, pMPC_TH, pMPC_RRH, bDir );
}
else if( pMPC_RRH->proto == PROTOCOL_UNKNOWN )
{
/* Display MPC_RRH and following MPC_PUK etc. */
mpc_display_rrh_and_puk( pDEVBLK, pMPC_TH, pMPC_RRH, bDir );
}
else
{
/* Display MPC_RRH */
mpc_display_rrh( pDEVBLK, pMPC_RRH, bDir );
}
/* Get the displacement from the start of the MPC_TH to the */
/* next MPC_RRH. pMPC_RRH->offrrh will contain zero if this */
/* is the last MPC_RRH. */
FETCH_FW( uOffRRH, pMPC_RRH->offrrh );
}
return;
} /* End function mpc_display_ptp_th_etc() */