diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/mvdm/vdmredir/vrdlcdbg.c | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/mvdm/vdmredir/vrdlcdbg.c')
-rw-r--r-- | private/mvdm/vdmredir/vrdlcdbg.c | 4024 |
1 files changed, 4024 insertions, 0 deletions
diff --git a/private/mvdm/vdmredir/vrdlcdbg.c b/private/mvdm/vdmredir/vrdlcdbg.c new file mode 100644 index 000000000..fa824c04b --- /dev/null +++ b/private/mvdm/vdmredir/vrdlcdbg.c @@ -0,0 +1,4024 @@ +/*++ + +Copyright (c) 1991 Microsoft Corporation + +Module Name: + + vrdlcdbg.c + +Abstract: + + Contains functions for dumping CCBs, parameter tables; diagnostic and + debugging functions for DOS DLC (CCB1) + + Contents: + DbgOut + DbgOutStr + DumpCcb + DumpDosDlcBufferPool + DumpDosDlcBufferChain + MapCcbRetcode + (DefaultParameterTableDump) + (DumpParameterTableHeader) + (DumpBufferFreeParms) + (DumpBufferGetParms) + (DumpDirCloseAdapterParms) + (DumpDirDefineMifEnvironmentParms) + (DumpDirInitializeParms) + (DumpDirModifyOpenParmsParms) + (DumpDirOpenAdapterParms) + (DumpDirReadLog) + (DumpDirRestoreOpenParmsParms) + (DumpDirSetFunctionalAddressParms) + (DumpDirSetGroupAddressParms) + (DumpDirSetUserAppendageParms) + (DumpDirStatusParms) + (DumpDirTimerCancelParms) + (DumpDirTimerCancelGroupParms) + (DumpDirTimerSetParms) + (DumpDlcCloseSapParms) + (DumpDlcCloseStationParms) + (DumpDlcConnectStationParms) + (DumpDlcFlowControlParms) + (MapFlowControl) + (DumpDlcModifyParms) + (DumpDlcOpenSapParms) + (MapOptionsPriority) + (DumpDlcOpenStationParms) + (DumpDlcReallocateParms) + (DumpDlcResetParms) + (DumpDlcStatisticsParms) + (DumpPdtTraceOffParms) + (DumpPdtTraceOnParms) + (DumpReadParms) + (MapReadEvent) + (MapDlcStatus) + (DumpReadCancelParms) + (DumpReceiveParms) + (DumpReceiveCancelParms) + (DumpReceiveModifyParms) + (DumpTransmitDirFrameParms) + (DumpTransmitIFrameParms) + (DumpTransmitTestCmdParms) + (DumpTransmitUiFrameParms) + (DumpTransmitXidCmdParms) + (DumpTransmitXidRespFinalParms) + (DumpTransmitXidRespNotFinalParms) + (DumpTransmitParms) + (DumpTransmitQueue) + DumpReceiveDataBuffer + (MapMessageType) + DumpData + IsCcbErrorCodeAllowable + IsCcbErrorCodeValid + IsCcbCommandValid + MapCcbCommandToName + DumpDosAdapter + (MapAdapterType) + +Author: + + Richard L Firth (rfirth) 30-Apr-1992 + +Revision History: + +--*/ + +#if DBG + +#include <stdio.h> +#include <stdarg.h> +#include <string.h> +#include <nt.h> +#include <ntrtl.h> // ASSERT, DbgPrint +#include <nturtl.h> +#include <windows.h> +#include <softpc.h> // x86 virtual machine definitions +#include <vrdlctab.h> +#include <vdmredir.h> +#include <smbgtpt.h> +#include <dlcapi.h> // Official DLC API definition +#include <ntdddlc.h> // IOCTL commands +#include <dlcio.h> // Internal IOCTL API interface structures +#include "vrdlc.h" +#include "vrdebug.h" +#include "vrdlcdbg.h" + +// +// defines +// + +// +// standard parameters to each table dump routine +// + +#define DUMP_TABLE_PARMS \ + IN PVOID Parameters, \ + IN BOOL IsDos, \ + IN BOOL IsInput, \ + IN WORD Segment, \ + IN WORD Offset + +// +// DumpData options +// + +#define DD_NO_ADDRESS 0x00000001 // don't display address of data +#define DD_LINE_BEFORE 0x00000002 // linefeed before first dumped line +#define DD_LINE_AFTER 0x00000004 // linefeed after last dumped line +#define DD_INDENT_ALL 0x00000008 // indent all lines +#define DD_NO_ASCII 0x00000010 // don't dump ASCII respresentation +#define DD_UPPER_CASE 0x00000020 // upper-case hex dump (F4 instead of f4) + +// +// misc. +// + +#define DEFAULT_FIELD_WIDTH 13 // amount of description before a number + +// +// local prototypes +// + +VOID +DbgOutStr( + IN LPSTR Str + ); + +PRIVATE +VOID +DefaultParameterTableDump( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpParameterTableHeader( + IN LPSTR CommandName, + IN PVOID Table, + IN BOOL IsDos, + IN WORD Segment, + IN WORD Offset + ); + +PRIVATE +VOID +DumpBufferFreeParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpBufferGetParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpDirCloseAdapterParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpDirDefineMifEnvironmentParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpDirInitializeParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpDirModifyOpenParmsParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpDirOpenAdapterParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpDirReadLog( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpDirRestoreOpenParmsParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpDirSetFunctionalAddressParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpDirSetGroupAddressParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpDirSetUserAppendageParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpDirStatusParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpDirTimerCancelParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpDirTimerCancelGroupParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpDirTimerSetParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpDlcCloseSapParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpDlcCloseStationParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpDlcConnectStationParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpDlcFlowControlParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +LPSTR +MapFlowControl( + BYTE FlowControl + ); + +PRIVATE +VOID +DumpDlcModifyParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpDlcOpenSapParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +LPSTR +MapOptionsPriority( + UCHAR OptionsPriority + ); + +PRIVATE +VOID +DumpDlcOpenStationParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpDlcReallocateParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpDlcResetParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpDlcStatisticsParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpPdtTraceOffParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpPdtTraceOnParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpReadParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +LPSTR +MapReadEvent( + UCHAR Event + ); + +PRIVATE +LPSTR +MapDlcStatus( + WORD Status + ); + +PRIVATE +VOID +DumpReadCancelParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpReceiveParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpReceiveCancelParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpReceiveModifyParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpTransmitDirFrameParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpTransmitIFrameParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpTransmitTestCmdParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpTransmitUiFrameParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpTransmitXidCmdParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpTransmitXidRespFinalParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpTransmitXidRespNotFinalParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpTransmitParms( + DUMP_TABLE_PARMS + ); + +PRIVATE +VOID +DumpTransmitQueue( + IN DOS_ADDRESS dpQueue + ); + +PRIVATE +LPSTR +MapMessageType( + UCHAR MessageType + ); + +VOID +DumpData( + IN LPSTR Title, + IN PBYTE Address, + IN DWORD Length, + IN DWORD Options, + IN DWORD Indent, + IN BOOL IsDos, + IN WORD Segment, + IN WORD Offset + ); + +PRIVATE +LPSTR +MapAdapterType( + IN ADAPTER_TYPE AdapterType + ); + +// +// explanations of error codes returned in CCB_RETCODE fields. Explanations +// taken more-or-less verbatim from IBM Local Area Network Technical Reference +// table B-1 ppB-2 to B-5. Includes all errors, even not relevant to CCB1 +// + +static LPSTR CcbRetcodeExplanations[] = { + "Success", + "Invalid command code", + "Duplicate command, one already outstanding", + "Adapter open, should be closed", + "Adapter closed, should be open", + "Required parameter missing", + "Invalid/incompatible option", + "Command cancelled - unrecoverable failure", + "Unauthorized access priority", + "Adapter not initialized, should be", + "Command cancelled by user request", + "Command cancelled, adapter closed while command in progress", + "Command completed Ok, adapter not open", + "Invalid error code 0x0D", + "Invalid error code 0x0E", + "Invalid error code 0x0F", + "Adapter open, NetBIOS not operational", + "Error in DIR.TIMER.SET or DIR.TIMER.CANCEL", + "Available work area exceeded", + "Invalid LOG.ID", + "Invalid shared RAM segment or size", + "Lost log data, buffer too small, log reset", + "Requested buffer size exceeds pool length", + "Command invalid, NetBIOS operational", + "Invalid SAP buffer length", + "Inadequate buffers available for request", + "USER_LENGTH value too large for buffer length", + "The CCB_PARM_TAB pointer is invalid", + "A pointer in the CCB parameter table is invalid", + "Invalid CCB_ADAPTER value", + "Invalid functional address", + "Invalid error code 0x1F", + "Lost data on receive, no buffers available", + "Lost data on receive, inadequate buffer space", + "Error on frame transmission, check TRANSMIT_FS data", + "Error on frame transmit or strip process", + "Unauthorized MAC frame", + "Maximum number of commands exceeded", + "Unrecognized command correlator", + "Link not transmitting I frames, state changed from link opened", + "Invalid transmit frame length", + "Invalid error code 0x29", + "Invalid error code 0x2a", + "Invalid error code 0x2b", + "Invalid error code 0x2c", + "Invalid error code 0x2d", + "Invalid error code 0x2e", + "Invalid error code 0x2f", + "Inadequate receive buffers for adapter to open", + "Invalid error code 0x31", + "Invalid NODE_ADDRESS", + "Invalid adapter receive buffer length defined", + "Invalid adapter transmit buffer length defined", + "Invalid error code 0x35", + "Invalid error code 0x36", + "Invalid error code 0x37", + "Invalid error code 0x38", + "Invalid error code 0x39", + "Invalid error code 0x3a", + "Invalid error code 0x3b", + "Invalid error code 0x3c", + "Invalid error code 0x3d", + "Invalid error code 0x3e", + "Invalid error code 0x3f", + "Invalid STATION_ID", + "Protocol error, link in invalid state for command", + "Parameter exceeded maximum allowed", + "Invalid SAP value or value already in use", + "Invalid routing information field", + "Requested group membership in non-existent group SAP", + "Resources not available", + "Sap cannot close unless all link stations are closed", + "Group SAP cannot close, individual SAPs not closed", + "Group SAP has reached maximum membership", + "Sequence error, incompatible command in progress", + "Station closed without remote acknowledgement", + "Sequence error, cannot close, DLC commands outstanding", + "Unsuccessful link station connection attempted", + "Member SAP not found in group SAP list", + "Invalid remote address, may not be a group address", + "Invalid pointer in CCB_POINTER field", + "Invalid error code 0x51", + "Invalid application program ID", + "Invalid application program key code", + "Invalid system key code", + "Buffer is smaller than buffer size given in DLC.OPEN.SAP", + "Adapter's system process is not installed", + "Inadequate stations available", + "Invalid CCB_PARAMETER_1 parameter", + "Inadequate queue elements to satisfy request", + "Initialization failure, cannot open adapter", + "Error detected in chained READ command", + "Direct stations not assigned to application program", + "Dd interface not installed", + "Requested adapter is not installed", + "Chained CCBs must all be for same adapter", + "Adapter initializing, command not accepted", + "Number of allowed application programs has been exceeded", + "Command cancelled by system action", + "Direct stations not available", + "Invalid DDNAME parameter", + "Inadequate GDT selectors to satisfy request", + "Invalid error code 0x66", + "Command cancelled, CCB resources purged", + "Application program ID not valid for interface", + "Segment associated with request cannot be locked" +}; + +#define NUMBER_OF_ERROR_MESSAGES ARRAY_ELEMENTS(CcbRetcodeExplanations) +#define LAST_DLC_ERROR_CODE LAST_ELEMENT(CcbRetcodeExplanations) + +VOID +DbgOut( + IN LPSTR Format, + IN ... + ) + +/*++ + +Routine Description: + + Sends formatted debug output to desired output device. If DEBUG_TO_FILE + was specified in VR environment flags, output goes to VRDEBUG.LOG in + current directory, else to standard debug output via DbgPrint + +Arguments: + + Format - printf-style format string + ... - variable args + +Return Value: + + None. + +--*/ + +{ + va_list list; + char buffer[2048]; + + va_start(list, Format); + vsprintf(buffer, Format, list); + va_end(list); + if (hVrDebugLog) { + fputs(buffer, hVrDebugLog); + } else { + DbgPrint(buffer); + } +} + +VOID +DbgOutStr( + IN LPSTR Str + ) + +/*++ + +Routine Description: + + Sends formatted debug output to desired output device. If DEBUG_TO_FILE + was specified in VR environment flags, output goes to VRDEBUG.LOG in + current directory, else to standard debug output via DbgPrint + +Arguments: + + Str - string to print + +Return Value: + + None. + +--*/ + +{ + if (hVrDebugLog) { + fputs(Str, hVrDebugLog); + } else { + DbgPrint(Str); + } +} + +VOID +DumpCcb( + IN PVOID Ccb, + IN BOOL DumpAll, + IN BOOL CcbIsInput, + IN BOOL IsDos, + IN WORD Segment OPTIONAL, + IN WORD Offset OPTIONAL + ) + +/*++ + +Routine Description: + + Dumps (to debug terminal) a CCB and any associated parameter table. Also + displays the symbolic CCB command and an error code description if the + CCB is being returned to the caller. Dumps in either DOS format (segmented + 16-bit pointers) or NT format (flat 32-bit pointers) + +Arguments: + + Ccb - flat 32-bit pointer to CCB1 or CCB2 to dump + DumpAll - if TRUE, dumps parameter tables and buffers, else just CCB + CcbIsInput - if TRUE, CCB is from user: don't display error code explanation + IsDos - if TRUE, CCB is DOS format + Segment - if IsDos is TRUE, segment of CCB in VDM + Offset - if IsDos is TRUE, offset of CCB in VDM + +Return Value: + + None. + +--*/ + +{ + PVOID parmtab = NULL; + LPSTR cmdname = "UNKNOWN CCB!"; + PLLC_CCB NtCcb = (PLLC_CCB)Ccb; + PLLC_DOS_CCB DosCcb = (PLLC_DOS_CCB)Ccb; + BOOL haveParms = FALSE; + VOID (*DumpParms)(PVOID, BOOL, BOOL, WORD, WORD) = DefaultParameterTableDump; + PVOID parameterTable = NULL; + WORD seg; + WORD off; + BOOL parmsInCcb = FALSE; + + switch (((PLLC_CCB)Ccb)->uchDlcCommand) { + case LLC_BUFFER_FREE: + cmdname = "BUFFER.FREE"; + haveParms = TRUE; + DumpParms = DumpBufferFreeParms; + break; + + case LLC_BUFFER_GET: + cmdname = "BUFFER.GET"; + haveParms = TRUE; + DumpParms = DumpBufferGetParms; + break; + + case LLC_DIR_CLOSE_ADAPTER: + cmdname = "DIR.CLOSE.ADAPTER"; + haveParms = TRUE; + DumpParms = DumpDirCloseAdapterParms; + parmsInCcb = TRUE; + break; + + case LLC_DIR_CLOSE_DIRECT: + cmdname = "DIR.CLOSE.DIRECT"; + break; + + case 0x2b: + + // + // not supported ! (yet?) + // + + cmdname = "DIR.DEFINE.MIF.ENVIRONMENT"; + haveParms = TRUE; + break; + + case LLC_DIR_INITIALIZE: + cmdname = "DIR.INITIALIZE"; + haveParms = TRUE; + DumpParms = DumpDirInitializeParms; + break; + + case LLC_DIR_INTERRUPT: + cmdname = "DIR.INTERRUPT"; + break; + + case LLC_DIR_MODIFY_OPEN_PARMS: + cmdname = "DIR.MODIFY.OPEN.PARMS"; + haveParms = TRUE; + break; + + case LLC_DIR_OPEN_ADAPTER: + cmdname = "DIR.OPEN.ADAPTER"; + haveParms = TRUE; + DumpParms = DumpDirOpenAdapterParms; + break; + + case LLC_DIR_OPEN_DIRECT: + + // + // not supported from DOS! + // + + cmdname = "DIR.OPEN.DIRECT"; + haveParms = TRUE; + break; + + case LLC_DIR_READ_LOG: + cmdname = "DIR.READ.LOG"; + haveParms = TRUE; + break; + + case LLC_DIR_RESTORE_OPEN_PARMS: + cmdname = "DIR.RESTORE.OPEN.PARMS"; + break; + + case LLC_DIR_SET_FUNCTIONAL_ADDRESS: + cmdname = "DIR.SET.FUNCTIONAL.ADDRESS"; + haveParms = TRUE; + DumpParms = DumpDirSetFunctionalAddressParms; + parmsInCcb = TRUE; + break; + + case LLC_DIR_SET_GROUP_ADDRESS: + cmdname = "DIR.SET.GROUP.ADDRESS"; + haveParms = TRUE; + DumpParms = DumpDirSetGroupAddressParms; + parmsInCcb = TRUE; + break; + + case LLC_DIR_SET_USER_APPENDAGE: + cmdname = "DIR.SET.USER.APPENDAGE"; + haveParms = TRUE; + DumpParms = DumpDirSetUserAppendageParms; + break; + + case LLC_DIR_STATUS: + cmdname = "DIR.STATUS"; + haveParms = TRUE; + DumpParms = DumpDirStatusParms; + break; + + case LLC_DIR_TIMER_CANCEL: + cmdname = "DIR.TIMER.CANCEL"; + haveParms = TRUE; + DumpParms = DumpDirTimerCancelParms; + parmsInCcb = TRUE; + break; + + case LLC_DIR_TIMER_CANCEL_GROUP: + cmdname = "DIR.TIMER.CANCEL.GROUP"; + haveParms = TRUE; + DumpParms = DumpDirTimerCancelGroupParms; + parmsInCcb = TRUE; + break; + + case LLC_DIR_TIMER_SET: + cmdname = "DIR.TIMER.SET"; + haveParms = TRUE; + DumpParms = DumpDirTimerSetParms; + parmsInCcb = TRUE; + break; + + case LLC_DLC_CLOSE_SAP: + cmdname = "DLC.CLOSE.SAP"; + haveParms = TRUE; + DumpParms = DumpDlcCloseSapParms; + parmsInCcb = TRUE; + break; + + case LLC_DLC_CLOSE_STATION: + cmdname = "DLC.CLOSE.STATION"; + haveParms = TRUE; + DumpParms = DumpDlcCloseStationParms; + parmsInCcb = TRUE; + break; + + case LLC_DLC_CONNECT_STATION: + cmdname = "DLC.CONNECT.STATION"; + haveParms = TRUE; + DumpParms = DumpDlcConnectStationParms; + break; + + case LLC_DLC_FLOW_CONTROL: + cmdname = "DLC.FLOW.CONTROL"; + haveParms = TRUE; + DumpParms = DumpDlcFlowControlParms; + parmsInCcb = TRUE; + break; + + case LLC_DLC_MODIFY: + cmdname = "DLC.MODIFY"; + haveParms = TRUE; + break; + + case LLC_DLC_OPEN_SAP: + cmdname = "DLC.OPEN.SAP"; + haveParms = TRUE; + DumpParms = DumpDlcOpenSapParms; + break; + + case LLC_DLC_OPEN_STATION: + cmdname = "DLC.OPEN.STATION"; + haveParms = TRUE; + DumpParms = DumpDlcOpenStationParms; + break; + + case LLC_DLC_REALLOCATE_STATIONS: + cmdname = "DLC.REALLOCATE"; + haveParms = TRUE; + break; + + case LLC_DLC_RESET: + cmdname = "DLC.RESET"; + haveParms = TRUE; + DumpParms = DumpDlcResetParms; + parmsInCcb = TRUE; + break; + + case LLC_DLC_SET_THRESHOLD: + cmdname = "DLC.SET.THRESHOLD"; + haveParms = TRUE; + break; + + case LLC_DLC_STATISTICS: + cmdname = "DLC.STATISTICS"; + haveParms = TRUE; + break; + + case 0x25: + + // + // not supported ! + // + + cmdname = "PDT.TRACE.OFF"; + break; + + case 0x24: + + // + // not supported ! + // + + cmdname = "PDT.TRACE.ON"; + break; + + case LLC_READ: + cmdname = "READ"; + haveParms = TRUE; + DumpParms = DumpReadParms; + break; + + case LLC_READ_CANCEL: + cmdname = "READ.CANCEL"; + break; + + case LLC_RECEIVE: + cmdname = "RECEIVE"; + haveParms = TRUE; + DumpParms = DumpReceiveParms; + break; + + case LLC_RECEIVE_CANCEL: + cmdname = "RECEIVE.CANCEL"; + haveParms = TRUE; + DumpParms = DumpReceiveCancelParms; + parmsInCcb = TRUE; + break; + + case LLC_RECEIVE_MODIFY: + cmdname = "RECEIVE.MODIFY"; + haveParms = TRUE; + DumpParms = DumpReceiveModifyParms; + break; + + case LLC_TRANSMIT_DIR_FRAME: + cmdname = "TRANSMIT.DIR.FRAME"; + haveParms = TRUE; + DumpParms = DumpTransmitDirFrameParms; + break; + + case LLC_TRANSMIT_I_FRAME: + cmdname = "TRANSMIT.I.FRAME"; + haveParms = TRUE; + DumpParms = DumpTransmitIFrameParms; + break; + + case LLC_TRANSMIT_TEST_CMD: + cmdname = "TRANSMIT.TEST.CMD"; + haveParms = TRUE; + DumpParms = DumpTransmitTestCmdParms; + break; + + case LLC_TRANSMIT_UI_FRAME: + cmdname = "TRANSMIT.UI.FRAME"; + haveParms = TRUE; + DumpParms = DumpTransmitUiFrameParms; + break; + + case LLC_TRANSMIT_XID_CMD: + cmdname = "TRANSMIT.XID.CMD"; + haveParms = TRUE; + DumpParms = DumpTransmitXidCmdParms; + break; + + case LLC_TRANSMIT_XID_RESP_FINAL: + cmdname = "TRANSMIT.XID.RESP.FINAL"; + haveParms = TRUE; + DumpParms = DumpTransmitXidRespFinalParms; + break; + + case LLC_TRANSMIT_XID_RESP_NOT_FINAL: + cmdname = "TRANSMIT.XID.RESP.NOT.FINAL"; + haveParms = TRUE; + DumpParms = DumpTransmitXidRespNotFinalParms; + break; + + } + + if (IsDos) { + seg = GET_SELECTOR(&DosCcb->u.pParms); + off = GET_OFFSET(&DosCcb->u.pParms); + parmtab = POINTER_FROM_WORDS(seg, off); + } else { + parmtab = NtCcb->u.pParameterTable; + } + + if (IsDos) { + PLLC_DOS_CCB DosCcb = (PLLC_DOS_CCB)Ccb; + + DBGPRINT( "\n" + "------------------------------------------------------------------------------" + "\n" + ); + + IF_DEBUG(TIME) { + SYSTEMTIME timestruct; + + GetLocalTime(×truct); + DBGPRINT( + "%02d:%02d:%02d.%03d\n", + timestruct.wHour, + timestruct.wMinute, + timestruct.wSecond, + timestruct.wMilliseconds + ); + } + + DBGPRINT( "%s DOS CCB @%04x:%04x:\n" + "adapter %02x\n" + "command %02x [%s]\n" + "retcode %02x [%s]\n" + "reserved %02x\n" + "next %04x:%04x\n" + "ANR %04x:%04x\n", + CcbIsInput ? "INPUT" : "OUTPUT", + Segment, + Offset, + DosCcb->uchAdapterNumber, + DosCcb->uchDlcCommand, + cmdname, + DosCcb->uchDlcStatus, + CcbIsInput ? "" : MapCcbRetcode(DosCcb->uchDlcStatus), + DosCcb->uchReserved1, + GET_SEGMENT(&DosCcb->pNext), + GET_OFFSET(&DosCcb->pNext), + GET_SEGMENT(&DosCcb->ulCompletionFlag), + GET_OFFSET(&DosCcb->ulCompletionFlag) + ); + if (haveParms) { + if (!parmsInCcb) { + DBGPRINT( + "parms %04x:%04x\n", + GET_SEGMENT(&DosCcb->u.pParms), + GET_OFFSET(&DosCcb->u.pParms) + ); + parameterTable = POINTER_FROM_WORDS(GET_SEGMENT(&DosCcb->u.pParms), + GET_OFFSET(&DosCcb->u.pParms) + ); + } else { + parameterTable = (PVOID)READ_DWORD(&DosCcb->u.ulParameter); + } + } + } else { + PLLC_CCB NtCcb = (PLLC_CCB)Ccb; + + DBGPRINT( "\n" + "------------------------------------------------------------------------------" + "\n" + ); + + IF_DEBUG(TIME) { + SYSTEMTIME timestruct; + + GetLocalTime(×truct); + DBGPRINT( + "%02d:%02d:%02d.%03d\n", + timestruct.wHour, + timestruct.wMinute, + timestruct.wSecond, + timestruct.wMilliseconds + ); + } + + DBGPRINT( "%s NT CCB @ %#8x\n" + "adapter %02x\n" + "command %02x [%s]\n" + "retcode %02x [%s]\n" + "reserved %02x\n" + "next %08x\n" + "ANR %08x\n", + CcbIsInput ? "INPUT" : "OUTPUT", + Ccb, + NtCcb->uchAdapterNumber, + NtCcb->uchDlcCommand, + cmdname, + NtCcb->uchDlcStatus, + CcbIsInput ? "" : MapCcbRetcode(NtCcb->uchDlcStatus), + NtCcb->uchReserved1, + NtCcb->pNext, + NtCcb->ulCompletionFlag + ); + if (haveParms) { + if (!parmsInCcb) { + DBGPRINT( + "parms %08x\n", + NtCcb->u.pParameterTable + ); + } + parameterTable = NtCcb->u.pParameterTable; + } + DBGPRINT( + "hEvent %08x\n" + "reserved %02x\n" + "readflag %02x\n" + "reserved %04x\n", + NtCcb->hCompletionEvent, + NtCcb->uchReserved2, + NtCcb->uchReadFlag, + NtCcb->usReserved3 + ); + } + if ((parameterTable && DumpAll) || parmsInCcb) { + DumpParms(parameterTable, IsDos, CcbIsInput, seg, off); + } +} + +VOID +DumpDosDlcBufferPool( + IN PDOS_DLC_BUFFER_POOL PoolDescriptor + ) + +/*++ + +Routine Description: + + Dumps a DOS DLC buffer pool so we can see that it looks ok + +Arguments: + + PoolDescriptor - pointer to DOS_DLC_BUFFER_POOL structure + +Return Value: + + None. + +--*/ + +{ + int count = PoolDescriptor->BufferCount; + + DBGPRINT( "DOS DLC Buffer Pool @%04x:%04x, BufferSize=%d, BufferCount=%d\n", + HIWORD(PoolDescriptor->dpBuffer), + LOWORD(PoolDescriptor->dpBuffer), + PoolDescriptor->BufferSize, + PoolDescriptor->BufferCount + ); + + DumpDosDlcBufferChain(PoolDescriptor->dpBuffer, PoolDescriptor->BufferCount); +} + +VOID +DumpDosDlcBufferChain( + IN DOS_ADDRESS DosAddress, + IN DWORD BufferCount + ) + +/*++ + +Routine Description: + + Dumps a chain of DOS buffers + +Arguments: + + DosAddress - address of buffer in VDM memory in DOS_ADDRESS format (16:16) + BufferCount - number of buffers to dump + +Return Value: + + None. + +--*/ + +{ + WORD seg = HIWORD(DosAddress); + WORD off = LOWORD(DosAddress); + LPVOID pointer = DOS_PTR_TO_FLAT(DosAddress); + int i; + + for (i = 1; BufferCount; --BufferCount, ++i) { + DBGPRINT("Buffer % 3d: %04x:%04x, Next Buffer @%04x:%04x\n", + i, + seg, off, + (DWORD)GET_SELECTOR(&((PLLC_DOS_BUFFER)pointer)->pNext), + (DWORD)GET_OFFSET(&((PLLC_DOS_BUFFER)pointer)->pNext) + ); + seg = GET_SELECTOR(&((PLLC_DOS_BUFFER)pointer)->pNext); + off = GET_OFFSET(&((PLLC_DOS_BUFFER)pointer)->pNext); + + IF_DEBUG(DUMP_FREE_BUF) { + + PLLC_DOS_BUFFER pBuf = (PLLC_DOS_BUFFER)pointer; + + DBGPRINT( + "next buffer %04x:%04x\n" + "frame length %04x\n" + "data length %04x\n" + "user offset %04x\n" + "user length %04x\n" + "station id %04x\n" + "options %02x\n" + "message type %02x\n" + "buffers left %04x\n" + "rcv FS %02x\n" + "adapter num %02x\n" + "\n", + GET_SEGMENT(&pBuf->Contiguous.pNextBuffer), + GET_OFFSET(&pBuf->Contiguous.pNextBuffer), + READ_WORD(&pBuf->Contiguous.cbFrame), + READ_WORD(&pBuf->Contiguous.cbBuffer), + READ_WORD(&pBuf->Contiguous.offUserData), + READ_WORD(&pBuf->Contiguous.cbUserData), + READ_WORD(&pBuf->Contiguous.usStationId), + pBuf->Contiguous.uchOptions, + pBuf->Contiguous.uchMsgType, + READ_WORD(&pBuf->Contiguous.cBuffersLeft), + pBuf->Contiguous.uchRcvFS, + pBuf->Contiguous.uchAdapterNumber + ); + } + + pointer = READ_FAR_POINTER(&((PLLC_DOS_BUFFER)pointer)->pNext); + } +} + +LPSTR +MapCcbRetcode( + IN BYTE Retcode + ) + +/*++ + +Routine Description: + + Returns string describing error code + +Arguments: + + Retcode - CCB_RETCODE + +Return Value: + + LPSTR + +--*/ + +{ + char errbuf[128]; + + if (Retcode == LLC_STATUS_PENDING) { + return "Command in progress"; + } else if (Retcode > NUMBER_OF_ERROR_MESSAGES) { + sprintf(errbuf, "*** Invalid error code 0x%2x ***", Retcode); + return errbuf; + } + return CcbRetcodeExplanations[Retcode]; +} + +PRIVATE +VOID +DefaultParameterTableDump( + DUMP_TABLE_PARMS + ) + +/*++ + +Routine Description: + + Displays default message for CCBs which have parameter tables that don't + have a dump routine yet + +Arguments: + + Parameters - pointer to parameter table + IsDos - if TRUE parameters in DOS (16:16) format + Segment - if IsDos is TRUE, segment of CCB in VDM + Offset - if IsDos is TRUE, offset of CCB in VDM + +Return Value: + + None. + +--*/ + +{ + DBGPRINT("Parameter table dump not implemented for this CCB\n"); +} + +PRIVATE +VOID +DumpParameterTableHeader( + IN LPSTR CommandName, + IN PVOID Table, + IN BOOL IsDos, + IN WORD Segment, + IN WORD Offset + ) + +/*++ + +Routine Description: + + Displays header for parameter table dump. Displays address in DOS or NT + format (32-bit flat or 16:16) + +Arguments: + + CommandName - name of command which owns parameter table + Table - flat 32-bit address of parameter table + IsDos - if TRUE, use Segment:Offset in display + Segment - if IsDos is TRUE, segment of parameter table in VDM + Offset - if IsDos is TRUE, offset of parameter table in VDM + +Return Value: + + None. + +--*/ + +{ + DBGPRINT( IsDos ? "\n%s parameter table @%04x:%04x\n" + : "\n%s parameter table @%08x\n", + CommandName, + IsDos ? (DWORD)Segment : (DWORD)Table, + IsDos ? (DWORD)Offset : 0 + ); +} + +PRIVATE +VOID +DumpBufferFreeParms( + DUMP_TABLE_PARMS + ) +{ + PLLC_BUFFER_FREE_PARMS parms = (PLLC_BUFFER_FREE_PARMS)Parameters; + + DumpParameterTableHeader("BUFFER.FREE", Parameters, IsDos, Segment, Offset); + + DBGPRINT( "station id %04x\n" + "buffers left %04x\n" + "reserved %02x %02x %02x %02x\n", + READ_WORD(&parms->usReserved1), + READ_WORD(&parms->cBuffersLeft), + ((PBYTE)&(parms->ulReserved))[0], + ((PBYTE)&(parms->ulReserved))[1], + ((PBYTE)&(parms->ulReserved))[2], + ((PBYTE)&(parms->ulReserved))[3] + ); + if (IsDos) { + DBGPRINT( + "first buffer %04x:%04x\n", + GET_SELECTOR(&parms->pFirstBuffer), + GET_OFFSET(&parms->pFirstBuffer) + ); + } else { + DBGPRINT( + "first buffer %08x\n", parms->pFirstBuffer); + } +} + +PRIVATE +VOID +DumpBufferGetParms( + DUMP_TABLE_PARMS + ) +{ + // + // Antti's definition different from that in manual, so use IBM def. + // + + typedef struct { + WORD StationId; + WORD BufferLeft; + BYTE BufferGet; + BYTE Reserved[3]; + DWORD FirstBuffer; + } CCB1_BUFFER_GET_PARMS, *PCCB1_BUFFER_GET_PARMS; + + PCCB1_BUFFER_GET_PARMS parms = (PCCB1_BUFFER_GET_PARMS)Parameters; + + DumpParameterTableHeader("BUFFER.GET", Parameters, IsDos, Segment, Offset); + + DBGPRINT( "station id %04x\n" + "buffers left %04x\n" + "buffers get %02x\n" + "reserved %02x %02x %02x\n", + READ_WORD(&parms->StationId), + READ_WORD(&parms->BufferLeft), + parms->BufferGet, + parms->Reserved[0], + parms->Reserved[1], + parms->Reserved[2] + ); + if (IsDos) { + DBGPRINT( + "first buffer %04x:%04x\n", + GET_SELECTOR(&parms->FirstBuffer), + GET_OFFSET(&parms->FirstBuffer) + ); + } else { + DBGPRINT( + "first buffer %08x\n", parms->FirstBuffer); + } +} + +PRIVATE +VOID +DumpDirCloseAdapterParms( + DUMP_TABLE_PARMS + ) +{ + UNREFERENCED_PARAMETER(IsDos); + UNREFERENCED_PARAMETER(Segment); + UNREFERENCED_PARAMETER(Offset); + + DBGPRINT( "lock code %04x\n", LOWORD(Parameters)); +} + +PRIVATE +VOID +DumpDirDefineMifEnvironmentParms( + DUMP_TABLE_PARMS + ) +{ +} + +PRIVATE +VOID +DumpDirInitializeParms( + DUMP_TABLE_PARMS + ) +{ + // + // once again, invent a structure to reflect the DOS CCB parameter table + // as defined in the IBM LAN tech ref + // + + typedef struct { + WORD BringUps; + WORD SharedRam; + BYTE Reserved[4]; + DWORD AdapterCheckAppendage; + DWORD NetworkStatusChangeAppendage; + DWORD IoErrorAppendage; + } CCB1_DIR_INITIALIZE_PARMS, *PCCB1_DIR_INITIALIZE_PARMS; + + PCCB1_DIR_INITIALIZE_PARMS parms = (PCCB1_DIR_INITIALIZE_PARMS)Parameters; + + DumpParameterTableHeader("DIR.INITIALIZE", Parameters, IsDos, Segment, Offset); + + DBGPRINT( "bring ups %04x\n" + "shared RAM %04x\n" + "reserved %02x %02x %02x %02x\n" + "adap. check %04x:%04x\n" + "n/w status %04x:%04x\n" + "pc error %04x:%04x\n", + READ_WORD(&parms->BringUps), + READ_WORD(&parms->SharedRam), + parms->Reserved[0], + parms->Reserved[1], + parms->Reserved[2], + parms->Reserved[3], + GET_SEGMENT(&parms->AdapterCheckAppendage), + GET_OFFSET(&parms->AdapterCheckAppendage), + GET_SEGMENT(&parms->NetworkStatusChangeAppendage), + GET_OFFSET(&parms->NetworkStatusChangeAppendage), + GET_SEGMENT(&parms->IoErrorAppendage), + GET_OFFSET(&parms->IoErrorAppendage) + ); +} + +PRIVATE +VOID +DumpDirModifyOpenParmsParms( + DUMP_TABLE_PARMS + ) +{ +} + +PRIVATE +VOID +DumpDirOpenAdapterParms( + DUMP_TABLE_PARMS + ) +{ + PLLC_DOS_DIR_OPEN_ADAPTER_PARMS dosParms = (PLLC_DOS_DIR_OPEN_ADAPTER_PARMS)Parameters; + PLLC_DIR_OPEN_ADAPTER_PARMS ntParms = (PLLC_DIR_OPEN_ADAPTER_PARMS)Parameters; + + DumpParameterTableHeader("DIR.OPEN.ADAPTER", Parameters, IsDos, Segment, Offset); + + if (IsDos) { + PADAPTER_PARMS pAdapterParms = READ_FAR_POINTER(&dosParms->pAdapterParms); + PDIRECT_PARMS pDirectParms = READ_FAR_POINTER(&dosParms->pDirectParms); + PDLC_PARMS pDlcParms = READ_FAR_POINTER(&dosParms->pDlcParms); + PNCB_PARMS pNcbParms = READ_FAR_POINTER(&dosParms->pNcbParms); + ULPBYTE pProductId; + DWORD i; + + DBGPRINT( + "adapter parms %04x:%04x\n" + "direct parms %04x:%04x\n" + "DLC parms %04x:%04x\n" + "NCB parms %04x:%04x\n", + GET_SEGMENT(&dosParms->pAdapterParms), + GET_OFFSET(&dosParms->pAdapterParms), + GET_SEGMENT(&dosParms->pDirectParms), + GET_OFFSET(&dosParms->pDirectParms), + GET_SEGMENT(&dosParms->pDlcParms), + GET_OFFSET(&dosParms->pDlcParms), + GET_SEGMENT(&dosParms->pNcbParms), + GET_OFFSET(&dosParms->pNcbParms) + ); + if (pAdapterParms) { + DBGPRINT( + "\n" + "ADAPTER_PARMS @%04x:%04x\n" + "open error %04x\n" + "open options %04x\n" + "node address %02x-%02x-%02x-%02x-%02x-%02x\n" + "group address %08x\n" + "func. address %08x\n" + "# rcv buffers %04x\n" + "rcv buf len %04x\n" + "DHB len %04x\n" + "# DHBs %02x\n" + "Reserved %02x\n" + "Open Lock %04x\n" + "Product ID %04x:%04x\n", + GET_SEGMENT(&dosParms->pAdapterParms), + GET_OFFSET(&dosParms->pAdapterParms), + READ_WORD(&pAdapterParms->OpenErrorCode), + READ_WORD(&pAdapterParms->OpenOptions), + READ_BYTE(&pAdapterParms->NodeAddress[0]), + READ_BYTE(&pAdapterParms->NodeAddress[1]), + READ_BYTE(&pAdapterParms->NodeAddress[2]), + READ_BYTE(&pAdapterParms->NodeAddress[3]), + READ_BYTE(&pAdapterParms->NodeAddress[4]), + READ_BYTE(&pAdapterParms->NodeAddress[5]), + READ_DWORD(&pAdapterParms->GroupAddress), + READ_DWORD(&pAdapterParms->FunctionalAddress), + READ_WORD(&pAdapterParms->NumberReceiveBuffers), + READ_WORD(&pAdapterParms->ReceiveBufferLength), + READ_WORD(&pAdapterParms->DataHoldBufferLength), + READ_BYTE(&pAdapterParms->NumberDataHoldBuffers), + READ_BYTE(&pAdapterParms->Reserved), + READ_WORD(&pAdapterParms->OpenLock), + GET_SEGMENT(&pAdapterParms->ProductId), + GET_OFFSET(&pAdapterParms->ProductId) + ); + pProductId = READ_FAR_POINTER(&pAdapterParms->ProductId); + if (pProductId) { + DBGPRINT("\nPRODUCT ID:\n"); + for (i=0; i<18; ++i) { + DBGPRINT("%02x ", *pProductId++); + } + DBGPRINT("\n"); + } + } + if (pDirectParms) { + DBGPRINT( + "\n" + "DIRECT_PARMS @%04x:%04x\n" + "dir buf size %04x\n" + "dir pool blx %04x\n" + "dir buf pool %04x:%04x\n" + "adap chk exit %04x:%04x\n" + "nw stat exit %04x:%04x\n" + "pc error exit %04x:%04x\n" + "adap wrk area %04x:%04x\n" + "adap wrk req. %04x\n" + "adap wrk act %04x\n", + GET_SEGMENT(&dosParms->pDirectParms), + GET_OFFSET(&dosParms->pDirectParms), + READ_WORD(&pDirectParms->DirectBufferSize), + READ_WORD(&pDirectParms->DirectPoolBlocks), + GET_SEGMENT(&pDirectParms->DirectBufferPool), + GET_OFFSET(&pDirectParms->DirectBufferPool), + GET_SEGMENT(&pDirectParms->AdapterCheckExit), + GET_OFFSET(&pDirectParms->AdapterCheckExit), + GET_SEGMENT(&pDirectParms->NetworkStatusExit), + GET_OFFSET(&pDirectParms->NetworkStatusExit), + GET_SEGMENT(&pDirectParms->PcErrorExit), + GET_OFFSET(&pDirectParms->PcErrorExit), + GET_SEGMENT(&pDirectParms->AdapterWorkArea), + GET_OFFSET(&pDirectParms->AdapterWorkArea), + READ_WORD(&pDirectParms->AdapterWorkAreaRequested), + READ_WORD(&pDirectParms->AdapterWorkAreaActual) + ); + } + if (pDlcParms) { + DBGPRINT( + "\n" + "DLC_PARMS @%04x:%04x\n" + "max SAPs %02x\n" + "max links %02x\n" + "max grp SAPs %02x\n" + "max grp memb %02x\n" + "T1 tick 1 %02x\n" + "T2 tick 1 %02x\n" + "Ti tick 1 %02x\n" + "T1 tick 2 %02x\n" + "T2 tick 2 %02x\n" + "Ti tick 2 %02x\n", + GET_SEGMENT(&dosParms->pDlcParms), + GET_OFFSET(&dosParms->pDlcParms), + READ_BYTE(&pDlcParms->MaxSaps), + READ_BYTE(&pDlcParms->MaxStations), + READ_BYTE(&pDlcParms->MaxGroupSaps), + READ_BYTE(&pDlcParms->MaxGroupMembers), + READ_BYTE(&pDlcParms->T1Tick1), + READ_BYTE(&pDlcParms->T2Tick1), + READ_BYTE(&pDlcParms->TiTick1), + READ_BYTE(&pDlcParms->T1Tick2), + READ_BYTE(&pDlcParms->T2Tick2), + READ_BYTE(&pDlcParms->TiTick2) + ); + } + if (pNcbParms) { + DBGPRINT( + "\n" + "NCB_PARMS @%04x:%04x???\n", + GET_SEGMENT(&dosParms->pNcbParms), + GET_OFFSET(&dosParms->pNcbParms) + + ); + } + } else { + PLLC_ADAPTER_OPEN_PARMS pAdapterParms = ntParms->pAdapterParms; + PLLC_EXTENDED_ADAPTER_PARMS pExtendedParms = ntParms->pExtendedParms; + PLLC_DLC_PARMS pDlcParms = ntParms->pDlcParms; + PVOID pNcbParms = ntParms->pReserved1; + + DBGPRINT( + "adapter parms %08x\n" + "direct parms %08x\n" + "DLC parms %08x\n" + "NCB parms %08x\n", + pAdapterParms, + pExtendedParms, + pDlcParms, + pNcbParms + ); + if (pAdapterParms) { + DBGPRINT( + "\n" + "ADAPTER_PARMS @%08x\n" + "open error %04x\n" + "open options %04x\n" + "node address %02x-%02x-%02x-%02x-%02x-%02x\n" + "group address %08x\n" + "func. address %08x\n" + "reserved 1 %04x\n" + "reserved 2 %04x\n" + "max frame len %04x\n" + "reserved 3[0] %04x\n" + "reserved 3[1] %04x\n" + "reserved 3[2] %04x\n" + "reserved 3[3] %04x\n" + "bring ups %04x\n" + "init warnings %04x\n" + "reserved 4[0] %04x\n" + "reserved 4[1] %04x\n" + "reserved 4[2] %04x\n", + pAdapterParms, + pAdapterParms->usOpenErrorCode, + pAdapterParms->usOpenOptions, + pAdapterParms->auchNodeAddress[0], + pAdapterParms->auchNodeAddress[1], + pAdapterParms->auchNodeAddress[2], + pAdapterParms->auchNodeAddress[3], + pAdapterParms->auchNodeAddress[4], + pAdapterParms->auchNodeAddress[5], + *(UNALIGNED DWORD *)&pAdapterParms->auchGroupAddress, + *(UNALIGNED DWORD *)&pAdapterParms->auchFunctionalAddress, + pAdapterParms->usReserved1, + pAdapterParms->usReserved2, + pAdapterParms->usMaxFrameSize, + pAdapterParms->usReserved3[0], + pAdapterParms->usReserved3[1], + pAdapterParms->usReserved3[2], + pAdapterParms->usReserved3[3], + pAdapterParms->usBringUps, + pAdapterParms->InitWarnings, + pAdapterParms->usReserved4[0], + pAdapterParms->usReserved4[1], + pAdapterParms->usReserved4[2] + ); + } + if (pExtendedParms) { + DBGPRINT( + "\n" + "EXTENDED PARMS @%08x\n" + "hBufferPool %08x\n" + "pSecurityDesc %08x\n" + "Ethernet Type %08x\n", + pExtendedParms, + pExtendedParms->hBufferPool, + pExtendedParms->pSecurityDescriptor, + pExtendedParms->LlcEthernetType + ); + } + if (pDlcParms) { + DBGPRINT( + "\n" + "DLC_PARMS @%04x:%04x\n" + "max SAPs %02x\n" + "max links %02x\n" + "max grp SAPs %02x\n" + "max grp memb %02x\n" + "T1 tick 1 %02x\n" + "T2 tick 1 %02x\n" + "Ti tick 1 %02x\n" + "T1 tick 2 %02x\n" + "T2 tick 2 %02x\n" + "Ti tick 2 %02x\n", + pDlcParms, + pDlcParms->uchDlcMaxSaps, + pDlcParms->uchDlcMaxStations, + pDlcParms->uchDlcMaxGroupSaps, + pDlcParms->uchDlcMaxGroupMembers, + pDlcParms->uchT1_TickOne, + pDlcParms->uchT2_TickOne, + pDlcParms->uchTi_TickOne, + pDlcParms->uchT1_TickTwo, + pDlcParms->uchT2_TickTwo, + pDlcParms->uchTi_TickTwo + ); + } + if (pNcbParms) { + DBGPRINT( + "\n" + "NCB_PARMS @%08x???\n", + pNcbParms + ); + } + } +} + +PRIVATE +VOID +DumpDirReadLog( + DUMP_TABLE_PARMS + ) +{ + DumpParameterTableHeader("DIR.READ.LOG", Parameters, IsDos, Segment, Offset); +} + +PRIVATE +VOID +DumpDirRestoreOpenParmsParms( + DUMP_TABLE_PARMS + ) +{ +} + +PRIVATE +VOID +DumpDirSetFunctionalAddressParms( + DUMP_TABLE_PARMS + ) +{ + DBGPRINT( "funct addr %08lx\n", Parameters); +} + +PRIVATE +VOID +DumpDirSetGroupAddressParms( + DUMP_TABLE_PARMS + ) +{ + DBGPRINT( "group addr %08lx\n", Parameters); +} + +PRIVATE +VOID +DumpDirSetUserAppendageParms( + DUMP_TABLE_PARMS + ) +{ + PLLC_DIR_SET_USER_APPENDAGE_PARMS parms = (PLLC_DIR_SET_USER_APPENDAGE_PARMS)Parameters; + + DumpParameterTableHeader("DIR.SET.USER.APPENDAGE", Parameters, IsDos, Segment, Offset); + + if (IsDos) { + DBGPRINT( "adapt check %04x:%04x\n" + "n/w status %04x:%04x\n" + "w/s error %04x:%04x\n", + GET_SEGMENT(&parms->dpAdapterCheckExit), + GET_OFFSET(&parms->dpAdapterCheckExit), + GET_SEGMENT(&parms->dpNetworkStatusExit), + GET_OFFSET(&parms->dpNetworkStatusExit), + GET_SEGMENT(&parms->dpPcErrorExit), + GET_OFFSET(&parms->dpPcErrorExit) + ); + } +} + +PRIVATE +VOID +DumpDirStatusParms( + DUMP_TABLE_PARMS + ) +{ + PDOS_DIR_STATUS_PARMS dosParms = (PDOS_DIR_STATUS_PARMS)Parameters; + + DumpParameterTableHeader("DIR.STATUS", Parameters, IsDos, Segment, Offset); + + if (IsDos) { + DBGPRINT( "perm addr %02x-%02x-%02x-%02x-%02x-%02x\n" + "local addr %02x-%02x-%02x-%02x-%02x-%02x\n" + "group addr %08lx\n" + "func addr %08lx\n" + "max SAPs %02x\n" + "open SAPs %02x\n" + "max links %02x\n" + "open links %02x\n" + "avail links %02x\n" + "adapt config %02x\n" + "ucode level %02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x\n" + "adap parms %04x:%04x\n" + "adap MAC %04x:%04x\n" + "timer tick %04x:%04x\n" + "last NW stat %04x\n" + "ext. status %04x:%04x\n", + dosParms->auchPermanentAddress[0], + dosParms->auchPermanentAddress[1], + dosParms->auchPermanentAddress[2], + dosParms->auchPermanentAddress[3], + dosParms->auchPermanentAddress[4], + dosParms->auchPermanentAddress[5], + dosParms->auchNodeAddress[0], + dosParms->auchNodeAddress[1], + dosParms->auchNodeAddress[2], + dosParms->auchNodeAddress[3], + dosParms->auchNodeAddress[4], + dosParms->auchNodeAddress[5], + READ_DWORD(&dosParms->auchGroupAddress), + READ_DWORD(&dosParms->auchFunctAddr), + dosParms->uchMaxSap, + dosParms->uchOpenSaps, + dosParms->uchMaxStations, + dosParms->uchOpenStation, + dosParms->uchAvailStations, + dosParms->uchAdapterConfig, + dosParms->auchMicroCodeLevel[0], + dosParms->auchMicroCodeLevel[1], + dosParms->auchMicroCodeLevel[2], + dosParms->auchMicroCodeLevel[3], + dosParms->auchMicroCodeLevel[4], + dosParms->auchMicroCodeLevel[5], + dosParms->auchMicroCodeLevel[6], + dosParms->auchMicroCodeLevel[7], + dosParms->auchMicroCodeLevel[8], + dosParms->auchMicroCodeLevel[9], + GET_SEGMENT(&dosParms->dpAdapterParmsAddr), + GET_OFFSET(&dosParms->dpAdapterParmsAddr), + GET_SEGMENT(&dosParms->dpAdapterMacAddr), + GET_OFFSET(&dosParms->dpAdapterMacAddr), + GET_SEGMENT(&dosParms->dpTimerTick), + GET_OFFSET(&dosParms->dpTimerTick), + READ_WORD(&dosParms->usLastNetworkStatus), + GET_SEGMENT(&dosParms->dpExtendedParms), + GET_OFFSET(&dosParms->dpExtendedParms) + ); + } else { + DBGPRINT("no dump for this table yet\n"); + } +} + +PRIVATE +VOID +DumpDirTimerCancelParms( + DUMP_TABLE_PARMS + ) +{ + if (IsDos) { + DBGPRINT( "cancel timer %04x:%04x\n", + HIWORD(Parameters), + LOWORD(Parameters) + ); + } +} + +PRIVATE +VOID +DumpDirTimerCancelGroupParms( + DUMP_TABLE_PARMS + ) +{ + if (IsDos) { + DBGPRINT( "cancel timer %04x:%04x\n", + HIWORD(Parameters), + LOWORD(Parameters) + ); + } +} + +PRIVATE +VOID +DumpDirTimerSetParms( + DUMP_TABLE_PARMS + ) +{ + if (IsDos) { + DBGPRINT( "timer value %04x\n", + LOWORD(Parameters) + ); + } +} + +PRIVATE +VOID +DumpDlcCloseSapParms( + DUMP_TABLE_PARMS + ) +{ + if (IsDos) { + DBGPRINT( "STATION_ID %04x\n" + "reserved %04x\n", + LOWORD(Parameters), + HIWORD(Parameters) + ); + } +} + +PRIVATE +VOID +DumpDlcCloseStationParms( + DUMP_TABLE_PARMS + ) +{ + if (IsDos) { + DBGPRINT( "STATION_ID %04x\n" + "reserved %02x %02x\n", + LOWORD(Parameters), + LOBYTE(HIWORD(Parameters)), + HIBYTE(HIWORD(Parameters)) + ); + } +} + +PRIVATE +VOID +DumpDlcConnectStationParms( + DUMP_TABLE_PARMS + ) +{ + LLC_DLC_CONNECT_PARMS UNALIGNED * parms = (PLLC_DLC_CONNECT_PARMS)Parameters; + ULPBYTE routing = NULL; + int i; + + DumpParameterTableHeader("DLC.CONNECT.STATION", Parameters, IsDos, Segment, Offset); + + DBGPRINT( "station id %04x\n" + "reserved %02x %02x\n", + READ_WORD(&parms->usStationId), + ((ULPBYTE)(&parms->usReserved))[0], + ((ULPBYTE)(&parms->usReserved))[1] + ); + if (IsDos) { + DBGPRINT( + "routing addr %04x:%04x\n", + GET_SEGMENT(&parms->pRoutingInfo), + GET_OFFSET(&parms->pRoutingInfo) + ); + routing = READ_FAR_POINTER(&parms->pRoutingInfo); + } else { + DBGPRINT( + "routing addr %08x\n", + parms->pRoutingInfo + ); + routing = parms->pRoutingInfo; + } + if (routing) { + DBGPRINT("ROUTING INFO: "); + for (i=0; i<18; ++i) { + DBGPRINT("%02x ", routing[i]); + } + DBGPRINT("\n"); + } +} + +PRIVATE +VOID +DumpDlcFlowControlParms( + DUMP_TABLE_PARMS + ) +{ + DBGPRINT( + "STATION_ID %04x\n" + "flow control %02x [%s]\n" + "reserved %02x\n", + LOWORD(Parameters), + LOBYTE(HIWORD(Parameters)), + MapFlowControl(LOBYTE(HIWORD(Parameters))), + HIBYTE(HIWORD(Parameters)) + ); +} + +PRIVATE LPSTR MapFlowControl(BYTE FlowControl) { + if (FlowControl & 0x80) { + if (FlowControl & 0x40) { + return "reset local_busy(buffer)"; + } else { + return "reset local_busy(user)"; + } + } else { + return "set local_busy(user)"; + } +} + +PRIVATE +VOID +DumpDlcModifyParms( + DUMP_TABLE_PARMS + ) +{ +} + +PRIVATE +VOID +DumpDlcOpenSapParms( + DUMP_TABLE_PARMS + ) +{ + PLLC_DLC_OPEN_SAP_PARMS parms = (PLLC_DLC_OPEN_SAP_PARMS)Parameters; + + DumpParameterTableHeader("DLC.OPEN.SAP", Parameters, IsDos, Segment, Offset); + + DBGPRINT( "station id %04x\n" + "user stat %04x\n" + "T1 %02x\n" + "T2 %02x\n" + "Ti %02x\n" + "max out %02x\n" + "max in %02x\n" + "max out inc %02x\n" + "max retry %02x\n" + "max members %02x\n" + "max I field %04x\n" + "SAP value %02x\n" + "options %02x [%s]\n" + "link count %02x\n" + "reserved %02x %02x\n" + "group count %02x\n", + READ_WORD(&parms->usStationId), + READ_WORD(&parms->usUserStatValue), + parms->uchT1, + parms->uchT2, + parms->uchTi, + parms->uchMaxOut, + parms->uchMaxIn, + parms->uchMaxOutIncr, + parms->uchMaxRetryCnt, + parms->uchMaxMembers, + READ_WORD(&parms->usMaxI_Field), + parms->uchSapValue, + parms->uchOptionsPriority, + MapOptionsPriority(parms->uchOptionsPriority), + parms->uchcStationCount, + parms->uchReserved2[0], + parms->uchReserved2[1], + parms->cGroupCount + ); + if (IsDos) { + DBGPRINT( + "group list %04x:%04x\n" + "dlc stat app %04x:%04x\n", + GET_SEGMENT(&parms->pGroupList), + GET_OFFSET(&parms->pGroupList), + GET_SEGMENT(&parms->DlcStatusFlags), + GET_OFFSET(&parms->DlcStatusFlags) + ); + + // + // some code here to dump group list + // + + } else { + DBGPRINT( + "group list %08x\n" + "dlc status %08x\n", + parms->pGroupList, + parms->DlcStatusFlags + ); + } + DBGPRINT( "buffer size %04x\n" + "pool length %04x\n", + READ_WORD(&parms->uchReserved3[0]), + READ_WORD(&parms->uchReserved3[2]) + ); + if (IsDos) { + DBGPRINT( + "buffer pool %04x:%04x\n", + READ_WORD(&parms->uchReserved3[6]), + READ_WORD(&parms->uchReserved3[4]) + ); + } else { + DBGPRINT( + "buffer pool %08x\n", + *(LPDWORD)&parms->uchReserved3[4] + ); + } +} + +PRIVATE LPSTR MapOptionsPriority(UCHAR OptionsPriority) { + static char buf[80]; + char* bufptr = buf; + + bufptr += sprintf(buf, "Access Priority=%d", (OptionsPriority & 0xe0) >> 5); + if (OptionsPriority & 8) { + bufptr += sprintf(bufptr, " XID handled by APP"); + } else { + bufptr += sprintf(bufptr, " XID handled by DLC"); + } + if (OptionsPriority & 4) { + bufptr += sprintf(bufptr, " Individual SAP"); + } + if (OptionsPriority & 2) { + bufptr += sprintf(bufptr, " Group SAP"); + } + if (OptionsPriority & 1) { + bufptr += sprintf(bufptr, " Group Member SAP"); + } + return buf; +} + +PRIVATE +VOID +DumpDlcOpenStationParms( + DUMP_TABLE_PARMS + ) +{ + PLLC_DLC_OPEN_STATION_PARMS parms = (PLLC_DLC_OPEN_STATION_PARMS)Parameters; + ULPBYTE dest = NULL; + int i; + + DumpParameterTableHeader("DLC.OPEN.STATION", Parameters, IsDos, Segment, Offset); + + DBGPRINT( "sap station %04x\n" + "link station %04x\n" + "T1 %02x\n" + "T2 %02x\n" + "Ti %02x\n" + "max out %02x\n" + "max in %02x\n" + "max out inc %02x\n" + "max retry %02x\n" + "remote SAP %02x\n" + "max I field %04x\n" + "access pri %02x\n", + READ_WORD(&parms->usSapStationId), + READ_WORD(&parms->usLinkStationId), + parms->uchT1, + parms->uchT2, + parms->uchTi, + parms->uchMaxOut, + parms->uchMaxIn, + parms->uchMaxOutIncr, + parms->uchMaxRetryCnt, + parms->uchRemoteSap, + READ_WORD(&parms->usMaxI_Field), + parms->uchAccessPriority + ); + if (IsDos) { + DBGPRINT( + "destination %04x:%04x\n", + GET_SEGMENT(&parms->pRemoteNodeAddress), + GET_OFFSET(&parms->pRemoteNodeAddress) + ); + dest = READ_FAR_POINTER(&parms->pRemoteNodeAddress); + } else { + DBGPRINT( + "destination %08x\n", + parms->pRemoteNodeAddress + ); + dest = parms->pRemoteNodeAddress; + } + if (dest) { + DBGPRINT("DESTINATION ADDRESS: "); + for (i=0; i<6; ++i) { + DBGPRINT("%02x ", dest[i]); + } + DBGPRINT("\n"); + } +} + +PRIVATE +VOID +DumpDlcReallocateParms( + DUMP_TABLE_PARMS + ) +{ +} + +PRIVATE +VOID +DumpDlcResetParms( + DUMP_TABLE_PARMS + ) +{ + DBGPRINT( "STATION_ID %04x\n" + "reserved %02x %02x\n", + LOWORD(Parameters), + LOBYTE(HIWORD(Parameters)), + HIBYTE(HIWORD(Parameters)) + ); +} + +PRIVATE +VOID +DumpDlcStatisticsParms( + DUMP_TABLE_PARMS + ) +{ +} + +PRIVATE +VOID +DumpPdtTraceOffParms( + DUMP_TABLE_PARMS + ) +{ +} + +PRIVATE +VOID +DumpPdtTraceOnParms( + DUMP_TABLE_PARMS + ) +{ +} + +PRIVATE +VOID +DumpReadParms( + DUMP_TABLE_PARMS + ) +{ + PLLC_READ_PARMS parms = (PLLC_READ_PARMS)Parameters; + + DumpParameterTableHeader("READ", Parameters, IsDos, Segment, Offset); + + // + // this parameter table not for DOS + // + + DBGPRINT( "station id %04x\n" + "option ind. %02x\n" + "event set %02x\n" + "event %02x [%s]\n" + "crit. subset %02x\n" + "notify flag %08x\n", + parms->usStationId, + parms->uchOptionIndicator, + parms->uchEventSet, + parms->uchEvent, + MapReadEvent(parms->uchEvent), + parms->uchCriticalSubset, + parms->ulNotificationFlag + ); + + // + // rest of table interpreted differently depending on whether status change + // + + if (parms->uchEvent & 0x38) { + DBGPRINT( + "station id %04x\n" + "status code %04x [%s]\n" + "FRMR data %02x %02x %02x %02x %02x\n" + "access pri. %02x\n" + "remote addr %02x-%02x-%02x-%02x-%02x-%02x\n" + "remote SAP %02x\n" + "reserved %02x\n" + "user stat %04x\n", + parms->Type.Status.usStationId, + parms->Type.Status.usDlcStatusCode, + MapDlcStatus(parms->Type.Status.usDlcStatusCode), + parms->Type.Status.uchFrmrData[0], + parms->Type.Status.uchFrmrData[1], + parms->Type.Status.uchFrmrData[2], + parms->Type.Status.uchFrmrData[3], + parms->Type.Status.uchFrmrData[4], + parms->Type.Status.uchAccessPritority, + parms->Type.Status.uchRemoteNodeAddress[0], + parms->Type.Status.uchRemoteNodeAddress[1], + parms->Type.Status.uchRemoteNodeAddress[2], + parms->Type.Status.uchRemoteNodeAddress[3], + parms->Type.Status.uchRemoteNodeAddress[4], + parms->Type.Status.uchRemoteNodeAddress[5], + parms->Type.Status.uchRemoteSap, + parms->Type.Status.uchReserved, + parms->Type.Status.usUserStatusValue + ); + } else { + DBGPRINT( + "CCB count %04x\n" + "CCB list %08x\n" + "buffer count %04x\n" + "buffer list %08x\n" + "frame count %04x\n" + "frame list %08x\n" + "error code %04x\n" + "error data %04x %04x %04x\n", + parms->Type.Event.usCcbCount, + parms->Type.Event.pCcbCompletionList, + parms->Type.Event.usBufferCount, + parms->Type.Event.pFirstBuffer, + parms->Type.Event.usReceivedFrameCount, + parms->Type.Event.pReceivedFrame, + parms->Type.Event.usEventErrorCode, + parms->Type.Event.usEventErrorData[0], + parms->Type.Event.usEventErrorData[1], + parms->Type.Event.usEventErrorData[2] + ); + + // + // address of CCB is in DOS memory + // + + if (parms->Type.Event.usCcbCount) { + DumpCcb(DOS_PTR_TO_FLAT(parms->Type.Event.pCcbCompletionList), + TRUE, // DumpAll + FALSE, // CcbIsInput + TRUE, // IsDos + HIWORD(parms->Type.Event.pCcbCompletionList), + LOWORD(parms->Type.Event.pCcbCompletionList) + ); + } + if (parms->Type.Event.usReceivedFrameCount) { + DumpReceiveDataBuffer(parms->Type.Event.pReceivedFrame, FALSE, 0, 0); + } + } +} + +PRIVATE LPSTR MapReadEvent(UCHAR Event) { + switch (Event) { + case 0x80: + return "Reserved Event!"; + + case 0x40: + return "System Action (non-critical)"; + + case 0x20: + return "Network Status (non-critical)"; + + case 0x10: + return "Critical Exception"; + + case 0x8: + return "DLC Status Change"; + + case 0x4: + return "Receive Data"; + + case 0x2: + return "Transmit Completion"; + + case 0x1: + return "Command Completion"; + } +} + +PRIVATE LPSTR MapDlcStatus(WORD Status) { + if (Status & 0x8000) { + return "Link lost"; + } else if (Status & 0x4000) { + return "DM/DISC Received -or- DISC ack'd"; + } else if (Status & 0x2000) { + return "FRMR Received"; + } else if (Status & 0x1000) { + return "FRMR Sent"; + } else if (Status & 0x0800) { + return "SABME Received for open link station"; + } else if (Status & 0x0400) { + return "SABME Received - link station opened"; + } else if (Status & 0x0200) { + return "REMOTE Busy Entered"; + } else if (Status & 0x0100) { + return "REMOTE Busy Left"; + } else if (Status & 0x0080) { + return "Ti EXPIRED"; + } else if (Status & 0x0040) { + return "DLC counter overflow - issue DLC.STATISTICS"; + } else if (Status & 0x0020) { + return "Access Priority lowered"; + } else if (Status & 0x001e) { + return "*** ERROR - INVALID STATUS ***"; + } else if (Status & 0x0001) { + return "Entered LOCAL Busy"; + } +} + +PRIVATE +VOID +DumpReadCancelParms( + DUMP_TABLE_PARMS + ) +{ +} + +PRIVATE +VOID +DumpReceiveParms( + DUMP_TABLE_PARMS + ) +{ + // + // the format of the recieve parameter table is different depending on + // whether this is a DOS command (CCB1) or NT (CCB2) + // + + PLLC_RECEIVE_PARMS ntParms = (PLLC_RECEIVE_PARMS)Parameters; + PLLC_DOS_RECEIVE_PARMS dosParms = (PLLC_DOS_RECEIVE_PARMS)Parameters; + PLLC_DOS_RECEIVE_PARMS_EX dosExParms = (PLLC_DOS_RECEIVE_PARMS_EX)Parameters; + PVOID Buffer; + + DumpParameterTableHeader("RECEIVE", Parameters, IsDos, Segment, Offset); + + // + // some common bits: use any structure pointer + // + + DBGPRINT( "station id %04x\n" + "user length %04x\n", + READ_WORD(&ntParms->usStationId), + READ_WORD(&ntParms->usUserLength) + ); + + // + // dump segmented pointers for DOS, flat for NT + // + + if (IsDos) { + DBGPRINT( + "receive exit %04x:%04x\n" + "first buffer %04x:%04x\n", + GET_SEGMENT(&dosParms->ulReceiveExit), + GET_OFFSET(&dosParms->ulReceiveExit), + GET_SEGMENT(&dosParms->pFirstBuffer), + GET_OFFSET(&dosParms->pFirstBuffer) + ); + Buffer = READ_FAR_POINTER(&dosParms->pFirstBuffer); + + // + // use Segment & Offset to address received data buffer + // + + Segment = GET_SEGMENT(&dosParms->pFirstBuffer); + Offset = GET_OFFSET(&dosParms->pFirstBuffer); + } else { + DBGPRINT( + "receive flag %08x\n" + "first buffer %08x\n", + ntParms->ulReceiveFlag, + ntParms->pFirstBuffer + ); + Buffer = ntParms->pFirstBuffer; + } + + // + // more common bits + // + + DBGPRINT( "options %02x\n", + ntParms->uchOptions + ); + if (!IsDos) { + DBGPRINT( + "reserved1 %02x %02x %02x\n" + "read options %02x\n" + "reserved2 %02x %02x %02x\n" + "original CCB %08x\n" + "orig. exit %08x\n", + ntParms->auchReserved1[0], + ntParms->auchReserved1[1], + ntParms->auchReserved1[2], + ntParms->uchRcvReadOption, + ((PLLC_DOS_RECEIVE_PARMS_EX)ntParms)->auchReserved2[0], + ((PLLC_DOS_RECEIVE_PARMS_EX)ntParms)->auchReserved2[1], + ((PLLC_DOS_RECEIVE_PARMS_EX)ntParms)->auchReserved2[2], + ((PLLC_DOS_RECEIVE_PARMS_EX)ntParms)->dpOriginalCcbAddress, + ((PLLC_DOS_RECEIVE_PARMS_EX)ntParms)->dpCompletionFlag + ); +/* } else { + + // + // we have no way of knowing from the general purpose parameters if this + // is the original DOS CCB1 RECEIVE parameter table, or the extended + // RECEIVE parameter table that we create. Dump the extended bits for + // DOS anyhow + // + + DBGPRINT( + "\nExtended RECEIVE parameters for table @%08x\n" + "reserved1 %02x %02x %02x\n" + "read options %02x\n" + "reserved2 %02x %02x %02x\n" + "original CCB %04x:%04x\n" + "orig. exit %04x:%04x\n", + Parameters, + dosExParms->auchReserved1[0], + dosExParms->auchReserved1[1], + dosExParms->auchReserved1[2], + dosExParms->uchRcvReadOption, + dosExParms->auchReserved2[0], + dosExParms->auchReserved2[1], + dosExParms->auchReserved2[2], + GET_SEGMENT(&dosExParms->dpOriginalCcbAddress), + GET_OFFSET(&dosExParms->dpOriginalCcbAddress), + GET_SEGMENT(&dosExParms->dpCompletionFlag), + GET_OFFSET(&dosExParms->dpCompletionFlag) + ); +*/ + } + + // + // only dump the buffer(s) if this is an output CCB dump + // + + if (Buffer && !IsInput) { + DumpReceiveDataBuffer(Buffer, IsDos, Segment, Offset); + } +} + +PRIVATE +VOID +DumpReceiveCancelParms( + DUMP_TABLE_PARMS + ) +{ + DBGPRINT("STATION_ID %04x\n", LOWORD(Parameters)); +} + +PRIVATE +VOID +DumpReceiveModifyParms( + DUMP_TABLE_PARMS + ) +{ + PLLC_DOS_RECEIVE_MODIFY_PARMS parms = (PLLC_DOS_RECEIVE_MODIFY_PARMS)Parameters; + PVOID Buffer; + + DumpParameterTableHeader("RECEIVE.MODIFY", Parameters, IsDos, Segment, Offset); + + DBGPRINT( "station id %04x\n" + "user length %04x\n" + "receive exit %04x:%04x\n" + "first buffer %04x:%04x\n" + "subroutine %04x:%04x\n", + READ_WORD(&parms->StationId), + READ_WORD(&parms->UserLength), + GET_SEGMENT(&parms->ReceivedDataExit), + GET_OFFSET(&parms->ReceivedDataExit), + GET_SEGMENT(&parms->FirstBuffer), + GET_OFFSET(&parms->FirstBuffer), + GET_SEGMENT(&parms->Subroutine), + GET_OFFSET(&parms->Subroutine) + ); + Buffer = READ_FAR_POINTER(&parms->FirstBuffer); + if (Buffer) { + DumpReceiveDataBuffer(Buffer, IsDos, Segment, Offset); + } +} + +PRIVATE +VOID +DumpTransmitDirFrameParms( + DUMP_TABLE_PARMS + ) +{ + DumpParameterTableHeader("TRANSMIT.DIR.FRAME", Parameters, IsDos, Segment, Offset); + DumpTransmitParms(Parameters, IsDos, IsInput, Segment, Offset); +} + +PRIVATE +VOID +DumpTransmitIFrameParms( + DUMP_TABLE_PARMS + ) +{ + DumpParameterTableHeader("TRANSMIT.I.FRAME", Parameters, IsDos, Segment, Offset); + DumpTransmitParms(Parameters, IsDos, IsInput, Segment, Offset); +} + +PRIVATE +VOID +DumpTransmitTestCmdParms( + DUMP_TABLE_PARMS + ) +{ + DumpParameterTableHeader("TRANSMIT.TEST.CMD", Parameters, IsDos, Segment, Offset); + DumpTransmitParms(Parameters, IsDos, IsInput, Segment, Offset); +} + +PRIVATE +VOID +DumpTransmitUiFrameParms( + DUMP_TABLE_PARMS + ) +{ + DumpParameterTableHeader("TRANSMIT.UI.FRAME", Parameters, IsDos, Segment, Offset); + DumpTransmitParms(Parameters, IsDos, IsInput, Segment, Offset); +} + +PRIVATE +VOID +DumpTransmitXidCmdParms( + DUMP_TABLE_PARMS + ) +{ + DumpParameterTableHeader("TRANSMIT.XID.CMD", Parameters, IsDos, Segment, Offset); + DumpTransmitParms(Parameters, IsDos, IsInput, Segment, Offset); +} + +PRIVATE +VOID +DumpTransmitXidRespFinalParms( + DUMP_TABLE_PARMS + ) +{ + DumpParameterTableHeader("TRANSMIT.XID.RESP.FINAL", Parameters, IsDos, Segment, Offset); + DumpTransmitParms(Parameters, IsDos, IsInput, Segment, Offset); +} + +PRIVATE +VOID +DumpTransmitXidRespNotFinalParms( + DUMP_TABLE_PARMS + ) +{ + DumpParameterTableHeader("TRANSMIT.XID.RESP.NOT.FINAL", Parameters, IsDos, Segment, Offset); + DumpTransmitParms(Parameters, IsDos, IsInput, Segment, Offset); +} + +PRIVATE +VOID +DumpTransmitParms( + DUMP_TABLE_PARMS + ) +{ + PLLC_TRANSMIT_PARMS ntParms = (PLLC_TRANSMIT_PARMS)Parameters; + PLLC_DOS_TRANSMIT_PARMS dosParms = (PLLC_DOS_TRANSMIT_PARMS)Parameters; + + DBGPRINT( "station id %04x\n" + "frame status %02x\n" + "remote SAP %02x\n", + READ_WORD(&dosParms->usStationId), + dosParms->uchTransmitFs, + dosParms->uchRemoteSap + ); + + if (IsDos) { + DBGPRINT( + "xmit q1 %04x:%04x\n" + "xmit q2 %04x:%04x\n" + "buf. len. 1 %04x\n" + "buf. len. 2 %04x\n" + "buffer 1 %04x:%04x\n" + "buffer 2 %04x:%04x\n", + GET_SEGMENT(&dosParms->pXmitQueue1), + GET_OFFSET(&dosParms->pXmitQueue1), + GET_SEGMENT(&dosParms->pXmitQueue2), + GET_OFFSET(&dosParms->pXmitQueue2), + READ_WORD(&dosParms->cbBuffer1), + READ_WORD(&dosParms->cbBuffer2), + GET_SEGMENT(&dosParms->pBuffer1), + GET_OFFSET(&dosParms->pBuffer1), + GET_SEGMENT(&dosParms->pBuffer2), + GET_OFFSET(&dosParms->pBuffer2) + ); + IF_DEBUG(DLC_TX_DATA) { + if (READ_DWORD(&dosParms->pXmitQueue1)) { + DBGPRINT("\nXMIT_QUEUE_ONE:\n"); + DumpTransmitQueue(READ_DWORD(&dosParms->pXmitQueue1)); + } + if (READ_DWORD(&dosParms->pXmitQueue2)) { + DBGPRINT("\nXMIT_QUEUE_TWO:\n"); + DumpTransmitQueue(READ_DWORD(&dosParms->pXmitQueue2)); + } + if (dosParms->cbBuffer1) { + DBGPRINT("\nBUFFER1:\n"); + DumpData(NULL, + NULL, + dosParms->cbBuffer1, + DD_UPPER_CASE, + 0, + TRUE, + GET_SEGMENT(&dosParms->pBuffer1), + GET_OFFSET(&dosParms->pBuffer1) + ); + } + if (dosParms->cbBuffer2) { + DBGPRINT("\nBUFFER2:\n"); + DumpData(NULL, + NULL, + dosParms->cbBuffer2, + DD_UPPER_CASE, + 0, + TRUE, + GET_SEGMENT(&dosParms->pBuffer2), + GET_OFFSET(&dosParms->pBuffer2) + ); + } + } + } else { + DBGPRINT( + "xmit q1 %08x\n" + "xmit q2 %08x\n" + "buf. len. 1 %02x\n" + "buf. len. 2 %02x\n" + "buffer 1 %08x\n" + "buffer 2 %08x\n" + "xmt read opt %02x\n", + ntParms->pXmitQueue1, + ntParms->pXmitQueue2, + ntParms->cbBuffer1, + ntParms->cbBuffer2, + ntParms->pBuffer1, + ntParms->pBuffer2, + ntParms->uchXmitReadOption + ); + } +} + +PRIVATE +VOID +DumpTransmitQueue( + IN DOS_ADDRESS dpQueue + ) +{ + PLLC_XMIT_BUFFER pTxBuffer; + WORD userLength; + WORD dataLength; + + while (dpQueue) { + pTxBuffer = (PLLC_XMIT_BUFFER)DOS_PTR_TO_FLAT(dpQueue); + dataLength = READ_WORD(&pTxBuffer->cbBuffer); + userLength = READ_WORD(&pTxBuffer->cbUserData); + DBGPRINT( + "\n" + "Transmit Buffer @%04x:%04x\n" + "next buffer %04x:%04x\n" + "reserved %02x %02x\n" + "data length %04x\n" + "user data %04x\n" + "user length %04x\n", + HIWORD(dpQueue), + LOWORD(dpQueue), + GET_SEGMENT(&pTxBuffer->pNext), + GET_OFFSET(&pTxBuffer->pNext), + ((LPBYTE)(&pTxBuffer->usReserved1))[0], + ((LPBYTE)(&pTxBuffer->usReserved1))[1], + dataLength, + READ_WORD(&pTxBuffer->usReserved2), + userLength + ); + DumpData("user space", + (PBYTE)(&pTxBuffer->auchData), + userLength, + DD_NO_ADDRESS | DD_UPPER_CASE | DD_INDENT_ALL, + DEFAULT_FIELD_WIDTH, + FALSE, // not displaying seg:off, so no need for these 3 + 0, + 0 + ); + DumpData("xmit data", + (PBYTE)(&pTxBuffer->auchData) + userLength, + dataLength, + DD_NO_ADDRESS | DD_UPPER_CASE | DD_INDENT_ALL, + DEFAULT_FIELD_WIDTH, + FALSE, // not displaying seg:off, so no need for these 3 + 0, + 0 + ); + dpQueue = READ_DWORD(&pTxBuffer->pNext); + } +} + +VOID +DumpReceiveDataBuffer( + IN PVOID Buffer, + IN BOOL IsDos, + IN WORD Segment, + IN WORD Offset + ) +{ + if (IsDos) { + + PLLC_DOS_BUFFER pBuf = (PLLC_DOS_BUFFER)Buffer; + BOOL contiguous = pBuf->Contiguous.uchOptions & 0xc0; + WORD userLength = READ_WORD(&pBuf->Next.cbUserData); + WORD dataLength = READ_WORD(&pBuf->Next.cbBuffer); + WORD userOffset = READ_WORD(&pBuf->Next.offUserData); + + // + // Buffer 1: [not] contiguous MAC/DATA + // + + DBGPRINT( + "\n" + "%sContiguous MAC/DATA frame @%04x:%04x\n" + "next buffer %04x:%04x\n" + "frame length %04x\n" + "data length %04x\n" + "user offset %04x\n" + "user length %04x\n" + "station id %04x\n" + "options %02x\n" + "message type %02x [%s]\n" + "buffers left %04x\n" + "rcv FS %02x\n" + "adapter num %02x\n", + contiguous ? "" : "Not", + Segment, + Offset, + GET_SEGMENT(&pBuf->Contiguous.pNextBuffer), + GET_OFFSET(&pBuf->Contiguous.pNextBuffer), + READ_WORD(&pBuf->Contiguous.cbFrame), + READ_WORD(&pBuf->Contiguous.cbBuffer), + READ_WORD(&pBuf->Contiguous.offUserData), + READ_WORD(&pBuf->Contiguous.cbUserData), + READ_WORD(&pBuf->Contiguous.usStationId), + pBuf->Contiguous.uchOptions, + pBuf->Contiguous.uchMsgType, + MapMessageType(pBuf->Contiguous.uchMsgType), + READ_WORD(&pBuf->Contiguous.cBuffersLeft), + pBuf->Contiguous.uchRcvFS, + pBuf->Contiguous.uchAdapterNumber + ); + if (!contiguous) { + + DWORD cbLanHeader = (DWORD)pBuf->NotContiguous.cbLanHeader; + DWORD cbDlcHeader = (DWORD)pBuf->NotContiguous.cbDlcHeader; + + DBGPRINT( + "LAN hdr len %02x\n" + "DLC hdr len %02x\n", + cbLanHeader, + cbDlcHeader + ); + DumpData("LAN header", + NULL, + (DWORD)cbLanHeader, + DD_NO_ADDRESS | DD_NO_ASCII | DD_UPPER_CASE | DD_INDENT_ALL, + DEFAULT_FIELD_WIDTH, + TRUE, + Segment, + Offset + (WORD)&((PLLC_DOS_BUFFER)0)->NotContiguous.auchLanHeader + ); + DumpData("DLC header", + NULL, + cbDlcHeader, + DD_NO_ADDRESS | DD_NO_ASCII | DD_UPPER_CASE | DD_INDENT_ALL, + DEFAULT_FIELD_WIDTH, + TRUE, + Segment, + Offset + (WORD)&((PLLC_DOS_BUFFER)0)->NotContiguous.auchDlcHeader + ); + IF_DEBUG(DLC_RX_DATA) { + if (userLength) { + DumpData("user space", + NULL, + userLength, + DD_NO_ADDRESS | DD_UPPER_CASE | DD_INDENT_ALL, + DEFAULT_FIELD_WIDTH, + TRUE, + Segment, + //Offset + userOffset + userOffset + ); + } else { + DBGPRINT( + "user space\n" + ); + } + if (dataLength) { + DumpData("rcvd data", + NULL, + dataLength, + DD_NO_ADDRESS | DD_UPPER_CASE | DD_INDENT_ALL, + DEFAULT_FIELD_WIDTH, + TRUE, + Segment, + //Offset + userOffset + userLength + userOffset + userLength + ); + } else { + DBGPRINT( + "rcvd data\n" + ); + } + } + } else { + + // + // data length is size of frame in contiguous buffer? + // + + dataLength = READ_WORD(&pBuf->Contiguous.cbBuffer); + + IF_DEBUG(DLC_RX_DATA) { + if (userLength) { + DumpData("user space", + NULL, + userLength, + DD_NO_ADDRESS | DD_UPPER_CASE | DD_INDENT_ALL, + DEFAULT_FIELD_WIDTH, + TRUE, + Segment, + //Offset + userOffset + userOffset + ); + } else { + DBGPRINT( + "user space\n" + ); + } + if (dataLength) { + DumpData("rcvd data", + NULL, + dataLength, + DD_NO_ADDRESS | DD_UPPER_CASE | DD_INDENT_ALL, + DEFAULT_FIELD_WIDTH, + TRUE, + Segment, + //Offset + userOffset + userLength + userOffset + userLength + ); + } else { + DBGPRINT( + "rcvd data\n" + ); + } + } + } + + // + // dump second & subsequent buffers + // + + Segment = GET_SEGMENT(&pBuf->pNext); + Offset = GET_OFFSET(&pBuf->pNext); + + for ( + pBuf = (PLLC_DOS_BUFFER)READ_FAR_POINTER(&pBuf->pNext); + pBuf; + pBuf = (PLLC_DOS_BUFFER)READ_FAR_POINTER(&pBuf->pNext) + ) { + + userLength = READ_WORD(&pBuf->Next.cbUserData); + dataLength = READ_WORD(&pBuf->Next.cbBuffer); + + DBGPRINT( + "\n" + "Buffer 2/Subsequent @%04x:%04x\n" + "next buffer %04x:%04x\n" + "frame length %04x\n" + "data length %04x\n" + "user offset %04x\n" + "user length %04x\n", + Segment, + Offset, + GET_SEGMENT(&pBuf->pNext), + GET_OFFSET(&pBuf->pNext), + READ_WORD(&pBuf->Next.cbFrame), + dataLength, + READ_WORD(&pBuf->Next.offUserData), + userLength + ); + IF_DEBUG(DLC_RX_DATA) { + if (userLength) { + DumpData("user space", + NULL, + userLength, + DD_NO_ADDRESS | DD_UPPER_CASE | DD_INDENT_ALL, + DEFAULT_FIELD_WIDTH, + TRUE, + Segment, + //Offset + READ_WORD(&pBuf->Next.offUserData) + READ_WORD(&pBuf->Next.offUserData) + ); + } else { + DBGPRINT( + "user space\n" + ); + } + + // + // there must be received data + // + + DumpData("rcvd data", + NULL, + dataLength, + DD_NO_ADDRESS | DD_UPPER_CASE | DD_INDENT_ALL, + DEFAULT_FIELD_WIDTH, + TRUE, + Segment, + //Offset + READ_WORD(&pBuf->Next.offUserData) + userLength + READ_WORD(&pBuf->Next.offUserData) + userLength + ); + } + Segment = GET_SEGMENT(&pBuf->pNext); + Offset = GET_OFFSET(&pBuf->pNext); + } + } else { + + PLLC_BUFFER pBuf = (PLLC_BUFFER)Buffer; + BOOL contiguous = pBuf->Contiguous.uchOptions & 0xc0; + WORD userLength = pBuf->Next.cbUserData; + WORD dataLength = pBuf->Next.cbBuffer; + WORD userOffset = pBuf->Next.offUserData; + + // + // Buffer 1: [not] contiguous MAC/DATA + // + + DBGPRINT( + "\n" + "%sContiguous MAC/DATA frame @%08x\n" + "next buffer %08x\n" + "frame length %04x\n" + "data length %04x\n" + "user offset %04x\n" + "user length %04x\n" + "station id %04x\n" + "options %02x\n" + "message type %02x [%s]\n" + "buffers left %04x\n" + "rcv FS %02x\n" + "adapter num %02x\n", + contiguous ? "" : "Not", + pBuf, + pBuf->Contiguous.pNextBuffer, + pBuf->Contiguous.cbFrame, + pBuf->Contiguous.cbBuffer, + pBuf->Contiguous.offUserData, + pBuf->Contiguous.cbUserData, + pBuf->Contiguous.usStationId, + pBuf->Contiguous.uchOptions, + pBuf->Contiguous.uchMsgType, + MapMessageType(pBuf->Contiguous.uchMsgType), + pBuf->Contiguous.cBuffersLeft, + pBuf->Contiguous.uchRcvFS, + pBuf->Contiguous.uchAdapterNumber + ); + if (!contiguous) { + DWORD cbLanHeader = (DWORD)pBuf->NotContiguous.cbLanHeader; + DWORD cbDlcHeader = (DWORD)pBuf->NotContiguous.cbDlcHeader; + + DBGPRINT( + "next frame %08x\n" + "LAN hdr len %02x\n" + "DLC hdr len %02x\n", + pBuf->NotContiguous.pNextFrame, + cbLanHeader, + cbDlcHeader + ); + DumpData("LAN header", + pBuf->NotContiguous.auchLanHeader, + cbLanHeader, + DD_NO_ADDRESS | DD_NO_ASCII | DD_UPPER_CASE | DD_INDENT_ALL, + DEFAULT_FIELD_WIDTH, + FALSE, + 0, + 0 + ); + DumpData("DLC header", + pBuf->NotContiguous.auchDlcHeader, + cbDlcHeader, + DD_NO_ADDRESS | DD_NO_ASCII | DD_UPPER_CASE | DD_INDENT_ALL, + DEFAULT_FIELD_WIDTH, + FALSE, + 0, + 0 + ); + IF_DEBUG(DLC_RX_DATA) { + if (userLength) { + DumpData("user space ", + (PBYTE)pBuf + userOffset, + userLength, + DD_NO_ADDRESS | DD_UPPER_CASE | DD_INDENT_ALL, + DEFAULT_FIELD_WIDTH, + FALSE, + 0, + 0 + ); + } else { + DBGPRINT( + "user space\n" + ); + } + if (dataLength) { + DumpData("rcvd data", + (PBYTE)pBuf + userOffset + userLength, + dataLength, + DD_NO_ADDRESS | DD_UPPER_CASE | DD_INDENT_ALL, + DEFAULT_FIELD_WIDTH, + FALSE, + 0, + 0 + ); + } else { + DBGPRINT( + "rcvd data\n" + ); + } + } + } else { + + // + // data length is size of frame in contiguous buffer? + // + + dataLength = pBuf->Contiguous.cbFrame; + + DBGPRINT( + "next frame %08x\n", + pBuf->NotContiguous.pNextFrame + ); + IF_DEBUG(DLC_RX_DATA) { + if (userLength) { + DumpData("user space", + (PBYTE)pBuf + userOffset, + userLength, + DD_NO_ADDRESS | DD_UPPER_CASE | DD_INDENT_ALL, + DEFAULT_FIELD_WIDTH, + FALSE, + 0, + 0 + ); + } else { + DBGPRINT( + "user space\n" + ); + } + if (dataLength) { + DumpData("rcvd data", + (PBYTE)pBuf + userOffset + userLength, + dataLength, + DD_NO_ADDRESS | DD_UPPER_CASE | DD_INDENT_ALL, + DEFAULT_FIELD_WIDTH, + FALSE, + 0, + 0 + ); + } else { + DBGPRINT( + "rcvd data\n" + ); + } + } + } + + // + // dump second & subsequent buffers + // + + for (pBuf = pBuf->pNext; pBuf; pBuf = pBuf->pNext) { + userLength = pBuf->Next.cbUserData; + dataLength = pBuf->Next.cbBuffer; + DBGPRINT( + "\n" + "Buffer 2/Subsequent @%08x\n" + "next buffer %08x\n" + "frame length %04x\n" + "data length %04x\n" + "user offset %04x\n" + "user length %04x\n", + pBuf, + pBuf->pNext, + pBuf->Next.cbFrame, + dataLength, + pBuf->Next.offUserData, + userLength + ); + IF_DEBUG(DLC_RX_DATA) { + if (userLength) { + DumpData("user space", + (PBYTE)&pBuf + pBuf->Next.offUserData, + userLength, + DD_NO_ADDRESS | DD_UPPER_CASE | DD_INDENT_ALL, + DEFAULT_FIELD_WIDTH, + FALSE, + 0, + 0 + ); + } else { + DBGPRINT( + "user space\n" + ); + } + + // + // there must be received data + // + + DumpData("rcvd data", + (PBYTE)pBuf + pBuf->Next.offUserData + userLength, + dataLength, + DD_NO_ADDRESS | DD_UPPER_CASE | DD_INDENT_ALL, + DEFAULT_FIELD_WIDTH, + FALSE, + 0, + 0 + ); + } + } + } +} + +PRIVATE LPSTR MapMessageType(UCHAR MessageType) { + switch (MessageType) { + case 0x02: + return "MAC Frame (Direct Station on Token Ring only)"; + + case 0x04: + return "I-Frame"; + + case 0x06: + return "UI-Frame"; + + case 0x08: + return "XID Command (POLL)"; + + case 0x0a: + return "XID Command (not POLL)"; + + case 0x0c: + return "XID Response (FINAL)"; + + case 0x0e: + return "XID Response (not FINAL)"; + + case 0x10: + return "TEST Response (FINAL)"; + + case 0x12: + return "TEST Response (not FINAL)"; + + case 0x14: + return "OTHER - non-MAC frame (Direct Station only)"; + + default: + return "*** BAD FRAME TYPE ***"; + } +} + +VOID +DumpData( + IN LPSTR Title, + IN PBYTE Address, + IN DWORD Length, + IN DWORD Options, + IN DWORD Indent, + IN BOOL IsDos, + IN WORD Segment, + IN WORD Offset + ) +{ + char dumpBuf[128]; + char* bufptr; + int i, n, iterations; + char* hexptr; + + if (IsDos) { + Address = LPBYTE_FROM_WORDS(Segment, Offset); + } + + // + // the usual dump style: 16 columns of hex bytes, followed by 16 columns + // of corresponding ASCII characters, or '.' where the character is < 0x20 + // (space) or > 0x7f (del?) + // + + if (Options & DD_LINE_BEFORE) { + DbgOutStr("\n"); + } + iterations = 0; + while (Length) { + bufptr = dumpBuf; + if (Title && !iterations) { + strcpy(bufptr, Title); + bufptr = strchr(bufptr, 0); + } + if (Indent && ((Options & DD_INDENT_ALL) || iterations)) { + + int indentLen = (!iterations && Title) + ? (Indent - strlen(Title) < 0) + ? 1 + : Indent - strlen(Title) + : Indent; + + RtlFillMemory(bufptr, indentLen, ' '); + bufptr += indentLen; + } + if (!(Options & DD_NO_ADDRESS)) { + if (IsDos) { + bufptr += sprintf(bufptr, "%04x:%04x ", Segment, Offset); + } else { + bufptr += sprintf(bufptr, "%08x: ", Address); + } + } + n = (Length < 16) ? Length : 16; + hexptr = bufptr; + for (i = 0; i < n; ++i) { + bufptr += sprintf(bufptr, "%02x", Address[i]); + *bufptr++ = (i == 7) ? '-' : ' '; + } + if (Options & DD_UPPER_CASE) { + _strupr(hexptr); + } + if (!(Options & DD_NO_ASCII)) { + if (n < 16) { + for (i = 0; i < 16-n; ++i) { + bufptr += sprintf(bufptr, " "); + } + } + bufptr += sprintf(bufptr, " "); + for (i = 0; i < n; ++i) { + *bufptr++ = (Address[i] < 0x20 || Address[i] > 0x7f) ? '.' : Address[i]; + } + } + *bufptr++ = '\n'; + *bufptr = 0; + DbgOutStr(dumpBuf); + Length -= n; + Address += n; + ++iterations; + + // + // take care of segment wrap for DOS addresses + // + + if (IsDos) { + + DWORD x = (DWORD)Offset + n; + + Offset = (WORD)x; + if (HIWORD(x)) { + Segment += 0x1000; + } + } + } + if (Options & DD_LINE_AFTER) { + DbgOutStr("\n"); + } +} + +// +// CCB1 error checking +// + +#define BITS_PER_BYTE 8 +#define CCB1_ERROR_SPREAD ((MAX_CCB1_ERROR + BITS_PER_BYTE) & ~(BITS_PER_BYTE-1)) + +// +// Ccb1ErrorTable - for each command described in IBM Lan Tech. Ref. (including +// those not applicable to CCB1), we keep a list of the permissable error codes +// which are taken from the "Return Codes for CCB1 Commands" table on pp B-5 +// and B-6 +// The error list is an 80-bit bitmap in which an ON bit indicates that the +// error number corresponding to the bit's position is allowable for the CCB1 +// command corresponding to the list's index in the table +// + +typedef struct { + BOOL ValidForCcb1; + BYTE ErrorList[CCB1_ERROR_SPREAD/BITS_PER_BYTE]; + char* CommandName; +} CCB1_ERROR_TABLE; + +#define MAX_INCLUSIVE_CCB1_COMMAND LLC_MAX_DLC_COMMAND + +CCB1_ERROR_TABLE Ccb1ErrorTable[MAX_INCLUSIVE_CCB1_COMMAND + 1] = { + +// DIR.INTERRUPT (0x00) + { + TRUE, + {0x83, 0x02, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "DIR.INTERRUPT" + }, + +// DIR.MODIFY.OPEN.PARMS (0x01) + { + TRUE, + {0x97, 0x02, 0x40, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "DIR.MODIFY.OPEN.PARMS" + }, + +// DIR.RESTORE.OPEN.PARMS (0x02) + { + TRUE, + {0xd3, 0x02, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "DIR.RESTORE.OPEN.PARMS" + }, + +// DIR.OPEN.ADAPTER (0x03) + { + TRUE, + {0xaf, 0x02, 0x45, 0x79, 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00}, + "DIR.OPEN.ADAPTER" + }, + +// DIR.CLOSE.ADAPTER (0x04) + { + TRUE, + {0xb3, 0x02, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "DIR.CLOSE.ADAPTER" + }, + +// non-existent command (0x05) + { + FALSE, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "NON-EXISTENT COMMAND (0x05)" + }, + +// DIR.SET.GROUP.ADDRESS (0x06) + { + TRUE, + {0x93, 0x0a, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "DIR.SET.GROUP.ADDRESS" + }, + +// DIR.SET.FUNCTIONAL.ADDRESS (0x07) + { + TRUE, + {0x93, 0x0a, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "DIR.SET.FUNCTIONAL.ADDRESS" + }, + +// DIR.READ.LOG (0x08) + { + TRUE, + {0x93, 0x0a, 0x28, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "DIR.READ.LOG" + }, + +// non-existent command (0x09) + { + FALSE, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "NON-EXISTENT COMMAND (0x09)" + }, + +// TRANSMIT.DIR.FRAME (0x0a) + { + TRUE, + {0x93, 0x0f, 0x00, 0x28, 0xbc, 0x01, 0x00, 0x00, 0x13, 0x04}, + "TRANSMIT.DIR.FRAME" + }, + +// TRANSMIT.I.FRAME (0x0b) + { + TRUE, + {0x93, 0x0f, 0x00, 0x28, 0xbc, 0x01, 0x00, 0x00, 0x13, 0x04}, + "TRANSMIT.I.FRAME" + }, + +// non-existent command (0x0c) + { + FALSE, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "NON-EXISTENT COMMAND (0x0c)" + }, + +// TRANSMIT.UI.FRAME (0x0d) + { + TRUE, + {0x93, 0x0f, 0x00, 0x28, 0xbc, 0x01, 0x00, 0x00, 0x13, 0x04}, + "TRANSMIT.UI.FRAME" + }, + +// TRANSMIT.XID.CMD (0x0e) + { + TRUE, + {0x93, 0x0f, 0x00, 0x28, 0xbc, 0x01, 0x00, 0x00, 0x13, 0x04}, + "TRANSMIT.XID.CMD" + }, + +// TRANSMIT.XID.RESP.FINAL (0x0f) + { + TRUE, + {0x93, 0x0f, 0x00, 0x28, 0xbc, 0x01, 0x00, 0x00, 0x13, 0x04}, + "TRANSMIT.XID.RESP.FINAL" + }, + +// TRANSMIT.XID.RESP.NOT.FINAL (0x10) + { + TRUE, + {0x93, 0x0f, 0x00, 0x28, 0xbc, 0x01, 0x00, 0x00, 0x13, 0x04}, + "TRANSMIT.XID.RESP.NOT.FINAL" + }, + +// TRANSMIT.TEST.CMD (0x11) + { + TRUE, + {0x93, 0x0f, 0x00, 0x28, 0xbc, 0x01, 0x00, 0x00, 0x13, 0x04}, + "TRANSMIT.TEST.CMD" + }, + +// non-existent command (0x12) + { + FALSE, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "NON-EXISTENT COMMAND (0x12)" + }, + +// non-existent command (0x13) + { + FALSE, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "NON-EXISTENT COMMAND (0x13)" + }, + +// DLC.RESET (0x14) + { + TRUE, + {0x93, 0x0a, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00}, + "DLC.RESET" + }, + +// DLC.OPEN.SAP (0x15) + { + TRUE, + {0xd3, 0x0b, 0x40, 0x39, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x02}, + "DLC.OPEN.SAP" + }, + +// DLC.CLOSE.SAP (0x16) + { + TRUE, + {0x93, 0x0a, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x81, 0x11}, + "DLC.CLOSE.SAP" + }, + +// DLC.REALLOCATE (0x17) + { + TRUE, + {0x93, 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00}, + "DLC.REALLOCATE" + }, + +// non-existent command (0x18) + { + FALSE, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "NON-EXISTENT COMMAND (0x18)" + }, + +// DLC.OPEN.STATION (0x19) + { + TRUE, + {0xb3, 0x0b, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x4d, 0x80}, + "DLC.OPEN.STATION" + }, + +// DLC.CLOSE.STATION (0x1a) + { + TRUE, + {0x93, 0x0a, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x81, 0x18}, + "DLC.CLOSE.STATION" + }, + +// DLC.CONNECT.STATION (0x1b) + { + TRUE, + {0x97, 0x0a, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x13, 0x24}, + "DLC.CONNECT.STATION" + }, + +// DLC.MODIFY (0x1c) + { + TRUE, + {0x93, 0x0b, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x25, 0x42}, + "DLC.MODIFY" + }, + +// DLC.FLOW.CONTROL (0x1d) + { + TRUE, + {0x93, 0x0a, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00}, + "DLC.FLOW.CONTROL" + }, + +// DLC.STATISTICS (0x1e) + { + TRUE, + {0x93, 0x0a, 0x20, 0x28, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00}, + "DLC.STATISTICS" + }, + +// non-existent command (0x1f) + { + FALSE, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "NON-EXISTENT COMMAND (0x1f)" + }, + +// DIR.INITIALIZE (0x20) + { + TRUE, + {0x87, 0x00, 0x10, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "DIR.INITIALIZE" + }, + +// DIR.STATUS (0x21) + { + TRUE, + {0x03, 0x12, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "DIR.STATUS" + }, + +// DIR.TIMER.SET (0x22) + { + TRUE, + {0x83, 0x0e, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "DIR.TIMER.SET" + }, + +// DIR.TIMER.CANCEL (0x23) + { + TRUE, + {0x03, 0x02, 0x02, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "DIR.TIMER.CANCEL" + }, + +// PDT.TRACE.ON (0x24) + { + TRUE, + {0x45, 0x04, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "PDT.TRACE.ON" + }, + +// PDT.TRACE.OFF (0x25) + { + TRUE, + {0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "PDT.TRACE.OFF" + }, + +// BUFFER.GET (0x26) + { + TRUE, + {0x13, 0x02, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00}, + "BUFFER.GET" + }, + +// BUFFER.FREE (0x27) + { + TRUE, + {0x13, 0x02, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00}, + "BUFFER.FREE" + }, + +// RECEIVE (0x28) + { + TRUE, + {0x97, 0x0e, 0x00, 0x3c, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00}, + "RECEIVE" + }, + +// RECEIVE.CANCEL (0x29) + { + TRUE, + {0x13, 0x02, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00}, + "RECEIVE.CANCEL" + }, + +// RECEIVE.MODIFY (0x2a) + { + TRUE, + {0x97, 0x0e, 0x00, 0x3c, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00}, + "RECEIVE.MODIFY" + }, + +// DIR.DEFINE.MIF.ENVIRONMENT (0x2b) + { + TRUE, + {0x03, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "DIR.DEFINE.MIF.ENVIRONMENT" + }, + +// DIR.TIMER.CANCEL.GROUP (0x2c) + { + TRUE, + {0x03, 0x02, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "DIR.TIMER.CANCEL.GROUP" + }, + +// DIR.SET.USER.APPENDAGE (0x2d) + { + TRUE, + {0x93, 0x02, 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "DIR.SET.USER.APPENDAGE" + }, + +// non-existent command (0x2e) + { + FALSE, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "NON-EXISTENT COMMAND (0x2e)" + }, + +// non-existent command (0x2f) + { + FALSE, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "NON-EXISTENT COMMAND (0x2f)" + }, + +// non-existent command (0x30) + { + FALSE, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "NON-EXISTENT COMMAND (0x30)" + }, + +// READ (0x31) + { + FALSE, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "READ" + }, + +// READ.CANCEL (0x32) + { + FALSE, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "READ.CANCEL" + }, + +// DLC.SET.THRESHOLD (0x33) + { + FALSE, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "DLC.SET.THRESHOLD" + }, + +// DIR.CLOSE.DIRECT (0x34) + { + FALSE, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "DIR.CLOSE.DIRECT" + }, + +// DIR.OPEN.DIRECT (0x35) + { + FALSE, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "DIR.OPEN.DIRECT" + }, + +// PURGE.RESOURCES (0x36) + { + FALSE, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "PURGE.RESOURCES" + }, + +// LLC_MAX_DLC_COMMAND (0x37) ? + { + FALSE, + {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, + "NON-EXISTENT-COMMAND (0x37)" + } +}; + +BOOL +IsCcbErrorCodeAllowable( + IN BYTE CcbCommand, + IN BYTE CcbErrorCode + ) + +/*++ + +Routine Description: + + Check whether an error code is allowable for a particular CCB(1) command + code. Perform range check on the error code before using as index into + allowable error table + +Arguments: + + CcbCommand - Command code + CcbErrorCode - Return code + +Return Value: + + BOOL + TRUE - CcbErrorCode is valid for CcbCommand + FALSE - CcbErrorCode should not be returned for CcbCommand + OR CcbErrorCode is invalid (out of range) +--*/ + +{ + if (CcbErrorCode == CCB_COMMAND_IN_PROGRESS) { + return TRUE; + } + if (CcbErrorCode > MAX_CCB1_ERROR) + return FALSE; + return Ccb1ErrorTable[CcbCommand].ErrorList[CcbErrorCode/8] & (1 << (CcbErrorCode % 8)); +} + +BOOL +IsCcbErrorCodeValid( + IN BYTE CcbErrorCode + ) + +/*++ + +Routine Description: + + Check if a return code from a CCB(1) is an allowable return code, + irrespective of command type + +Arguments: + + CcbErrorCode - return code to check + +Return Value: + + BOOL + TRUE - CcbErrorCode is in range + FALSE - CcbErrorCode is not in range + +--*/ + +{ + return (CcbErrorCode == CCB_COMMAND_IN_PROGRESS) // 0xff + + // 0x00 - 0x0c + || ((CcbErrorCode >= CCB_SUCCESS) && (CcbErrorCode <= CCB_SUCCESS_ADAPTER_NOT_OPEN)) + + // 0x10 - 0x1e + || ((CcbErrorCode >= CCB_NETBIOS_FAILURE) && (CcbErrorCode <= CCB_INVALID_FUNCTION_ADDRESS)) + + // 0x20 - 0x28 + || ((CcbErrorCode >= CCB_DATA_LOST_NO_BUFFERS) && (CcbErrorCode <= CCB_INVALID_FRAME_LENGTH)) + + // 0x30 + || (CcbErrorCode == CCB_NOT_ENOUGH_BUFFERS_OPEN) + + // 0x32 - 0x34 + || ((CcbErrorCode >= CCB_INVALID_NODE_ADDRESS) && (CcbErrorCode <= CCB_INVALID_TRANSMIT_LENGTH)) + + // 0x40 - 0x4f + || ((CcbErrorCode >= CCB_INVALID_STATION_ID) && (CcbErrorCode <= CCB_INVALID_REMOTE_ADDRESS)) + ; +} + +BOOL +IsCcbCommandValid( + IN BYTE CcbCommand + ) + +/*++ + +Routine Description: + + Check if CCB command code is one of the allowable codes for a DOS CCB + (CCB1) + +Arguments: + + CcbCommand - command code to check + +Return Value: + + BOOL + TRUE - CcbCommand is recognized + FALSE - CcbCommand is not recognized + +--*/ + +{ + return ((CcbCommand >= LLC_DIR_INTERRUPT) && (CcbCommand <= LLC_DIR_CLOSE_ADAPTER)) + || ((CcbCommand >= LLC_DIR_SET_GROUP_ADDRESS) && (CcbCommand <= LLC_DIR_SET_FUNCTIONAL_ADDRESS)) + || ((CcbCommand >= LLC_TRANSMIT_DIR_FRAME) && (CcbCommand <= LLC_TRANSMIT_I_FRAME)) + || ((CcbCommand >= LLC_TRANSMIT_UI_FRAME) && (CcbCommand <= LLC_TRANSMIT_TEST_CMD)) + || ((CcbCommand >= LLC_DLC_RESET) && (CcbCommand <= LLC_DLC_REALLOCATE_STATIONS)) + || ((CcbCommand >= LLC_DLC_OPEN_STATION) && (CcbCommand <= LLC_DLC_STATISTICS)) + || ((CcbCommand >= LLC_DIR_INITIALIZE) && (CcbCommand <= LLC_DIR_SET_USER_APPENDAGE)) + ; +} + +LPSTR +MapCcbCommandToName( + IN BYTE CcbCommand + ) + +/*++ + +Routine Description: + + Return the name of a CCB command, given its value + +Arguments: + + CcbCommand - command code to map + +Return Value: + + char* pointer to ASCIZ name of command (in IBM format X.Y.Z) + +--*/ + +{ + return Ccb1ErrorTable[CcbCommand].CommandName; +} + +VOID +DumpDosAdapter( + IN DOS_ADAPTER* pDosAdapter + ) +{ + DBGPRINT( "DOS_ADAPTER @ %08x\n" + "AdapterType. . . . . . . . . %s\n" + "IsOpen . . . . . . . . . . . %d\n" + "DirectStationOpen. . . . . . %d\n" + "DirectReceive. . . . . . . . %d\n" + "WaitingRestore . . . . . . . %d\n" + "BufferFree . . . . . . . . . %d\n" + "BufferPool . . . . . . . . . %08x\n" + "CurrentExceptionHandlers . . %08x %08x %08x\n" + "PreviousExceptionHandlers. . %08x %08x %08x\n" + "DlcStatusChangeAppendage . . \n" + "LastNetworkStatusChange. . . %04x\n" + "UserStatusValue. . . . . . . \n" + "AdapterParms:\n" + " OpenErrorCode . . . . . . %04x\n" + " OpenOptions . . . . . . . %04x\n" + " NodeAddress . . . . . . . %02x-%02x-%02x-%02x-%02x-%02x\n" + " GroupAddress. . . . . . . %08x\n" + " FunctionalAddress . . . . %08x\n" + " NumberReceiveBuffers. . . %04x\n" + " ReceiveBufferLength . . . %04x\n" + " DataHoldBufferLength. . . %04x\n" + " NumberDataHoldBuffers . . %02x\n" + " Reserved. . . . . . . . . %02x\n" + " OpenLock. . . . . . . . . %04x\n" + " ProductId . . . . . . . . %08x\n" + "DlcSpecified . . . . . . . . %d\n" + "DlcParms:\n" + " MaxSaps . . . . . . . . . %02x\n" + " MaxStations . . . . . . . %02x\n" + " MaxGroupSaps. . . . . . . %02x\n" + " MaxGroupMembers . . . . . %02x\n" + " T1Tick1 . . . . . . . . . %02x\n" + " T2Tick1 . . . . . . . . . %02x\n" + " TiTick1 . . . . . . . . . %02x\n" + " T1Tick2 . . . . . . . . . %02x\n" + " T2Tick2 . . . . . . . . . %02x\n" + " TiTick2 . . . . . . . . . %02x\n" + "AdapterCloseCcb. . . . . . . \n" + "DirectCloseCcb . . . . . . . \n" + "ReadCcb. . . . . . . . . . . \n" + "EventQueueCritSec. . . . . . \n" + "EventQueueHead . . . . . . . \n" + "EventQueueTail . . . . . . . \n" + "QueueElements. . . . . . . . \n" + "LocalBusyCritSec . . . . . . \n" + "DeferredReceives . . . . . . \n" + "FirstIndex . . . . . . . . . \n" + "LastIndex. . . . . . . . . . \n" + "LocalBusyInfo. . . . . . . . \n", + MapAdapterType(pDosAdapter->AdapterType), + pDosAdapter->IsOpen, + pDosAdapter->DirectStationOpen, + pDosAdapter->DirectReceive, + pDosAdapter->WaitingRestore, + pDosAdapter->BufferFree, + pDosAdapter->BufferPool, + pDosAdapter->CurrentExceptionHandlers[0], + pDosAdapter->CurrentExceptionHandlers[1], + pDosAdapter->CurrentExceptionHandlers[2], + pDosAdapter->PreviousExceptionHandlers[0], + pDosAdapter->PreviousExceptionHandlers[1], + pDosAdapter->PreviousExceptionHandlers[2], + pDosAdapter->LastNetworkStatusChange, + pDosAdapter->AdapterParms.OpenErrorCode, + pDosAdapter->AdapterParms.OpenOptions, + pDosAdapter->AdapterParms.NodeAddress[0], + pDosAdapter->AdapterParms.NodeAddress[1], + pDosAdapter->AdapterParms.NodeAddress[2], + pDosAdapter->AdapterParms.NodeAddress[3], + pDosAdapter->AdapterParms.NodeAddress[4], + pDosAdapter->AdapterParms.NodeAddress[5], + pDosAdapter->AdapterParms.GroupAddress, + pDosAdapter->AdapterParms.FunctionalAddress, + pDosAdapter->AdapterParms.NumberReceiveBuffers, + pDosAdapter->AdapterParms.ReceiveBufferLength, + pDosAdapter->AdapterParms.DataHoldBufferLength, + pDosAdapter->AdapterParms.NumberDataHoldBuffers, + pDosAdapter->AdapterParms.Reserved, + pDosAdapter->AdapterParms.OpenLock, + pDosAdapter->AdapterParms.ProductId, + pDosAdapter->DlcSpecified, + pDosAdapter->DlcParms.MaxSaps, + pDosAdapter->DlcParms.MaxStations, + pDosAdapter->DlcParms.MaxGroupSaps, + pDosAdapter->DlcParms.MaxGroupMembers, + pDosAdapter->DlcParms.T1Tick1, + pDosAdapter->DlcParms.T2Tick1, + pDosAdapter->DlcParms.TiTick1, + pDosAdapter->DlcParms.T1Tick2, + pDosAdapter->DlcParms.T2Tick2, + pDosAdapter->DlcParms.TiTick2 + ); +} + +PRIVATE +LPSTR +MapAdapterType( + IN ADAPTER_TYPE AdapterType + ) +{ + switch (AdapterType) { + case TokenRing: + return "Token Ring"; + + case Ethernet: + return "Ethernet"; + + case PcNetwork: + return "PC Network"; + + case UnknownAdapter: + return "Unknown Adapter"; + } + return "*** REALLY UNKNOWN ADAPTER! ***"; +} + +#endif |