1359 lines
44 KiB
C
1359 lines
44 KiB
C
|
/*++
|
||
|
|
||
|
Copyright (c) 1991 Microsoft Corporation
|
||
|
Copyright (c) 1991 Nokia Data Systems
|
||
|
|
||
|
Module Name:
|
||
|
|
||
|
vrdlc.h
|
||
|
|
||
|
Abstract:
|
||
|
|
||
|
This module is the only header file of Windows/Nt VDM DLC
|
||
|
interface module.
|
||
|
|
||
|
ALL STRUCTURES IN THIS FILE WHICH REFERENCE STRUCTURES IN DOS MEMORY
|
||
|
ARE BYTE PACKED
|
||
|
|
||
|
Author:
|
||
|
|
||
|
Antti Saarenheimo (o-anttis) 26-01-1992
|
||
|
|
||
|
Revision History:
|
||
|
|
||
|
--*/
|
||
|
|
||
|
//
|
||
|
// constants
|
||
|
//
|
||
|
|
||
|
#define DOS_DLC_MAX_SAPS 128
|
||
|
#define DOS_DLC_MAX_LINKS 255
|
||
|
#define DOS_DLC_MAX_EVENTS 64
|
||
|
|
||
|
#define LLC_DIR_MODIFY_OPEN_PARMS 0x01
|
||
|
#define LLC_DIR_RESTORE_OPEN_PARMS 0x02
|
||
|
#define LLC_DIR_SET_USER_APPENDAGE 0x2d
|
||
|
#define LLC_DOS_SPECIAL_COMMAND ((ULONG)(-1))
|
||
|
#define LLC_BREAK 0x20
|
||
|
|
||
|
#define DOS_DLC_STATUS_NO_INDICATION 0x81
|
||
|
|
||
|
#define LLC_SET_LOCAL_BUSY_BUFFER 0x20
|
||
|
|
||
|
//
|
||
|
// VRDLC_COMMAND_COMPLETION - this value is placed in the CCB_CMD_CMPL field
|
||
|
// of every CCB2 that we issue that is NOT for the VDM. This value is used to
|
||
|
// filter out command completions for commands that are generated by the DOS
|
||
|
// DLC Emulator. This stops us passing command completions through to the
|
||
|
// VDM that are not intended for it!
|
||
|
//
|
||
|
|
||
|
#define VRDLC_COMMAND_COMPLETION ((ULONG)(-2))
|
||
|
|
||
|
//
|
||
|
// buffer pool sizes
|
||
|
//
|
||
|
|
||
|
#define DOS_DLC_BUFFER_POOL_SIZE 0x00010000 // 64K
|
||
|
#define DOS_DLC_MIN_FREE_THRESHOLD 0x00002000 // 8K
|
||
|
|
||
|
//
|
||
|
// flags for CopyFrame
|
||
|
//
|
||
|
|
||
|
#define CF_CONTIGUOUS 0x00000001 // frame is contiguous
|
||
|
#define CF_BREAK 0x00000002 // options specified Break
|
||
|
#define CF_PARTIAL 0x00000004 // receiving partial frame
|
||
|
|
||
|
//
|
||
|
// default values for DOS parameter tables (DD_ = DOS DEFAULT). These replace
|
||
|
// the various parameters which can be specified as 0. They may be different
|
||
|
// to the corresponding defaults applicable to NT DLC, so we fill them in
|
||
|
// specifically
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// defaults for BUFFER.GET:
|
||
|
//
|
||
|
|
||
|
#define DD_BUFFER_GET 1
|
||
|
|
||
|
//
|
||
|
// defaults for DIR.INITIALIZE:
|
||
|
//
|
||
|
|
||
|
#define DD_SRAM_ADDRESS_0 0xd800
|
||
|
#define DD_SRAM_ADDRESS_1 0xd400
|
||
|
|
||
|
//
|
||
|
// defaults for DIR.OPEN.ADAPTER, ADAPTER_PARMS:
|
||
|
//
|
||
|
|
||
|
#define DD_NUMBER_RCV_BUFFERS 8
|
||
|
#define DD_RCV_BUFFER_LENGTH 112
|
||
|
#define DD_DHB_BUFFER_LENGTH 600
|
||
|
#define DD_DATA_HOLD_BUFFERS 1
|
||
|
|
||
|
//
|
||
|
// defaults for DIR.OPEN.ADAPTER, DIRECT_PARMS:
|
||
|
//
|
||
|
|
||
|
#define DD_DIR_BUF_SIZE 160
|
||
|
#define DD_DIR_POOL_BLOCKS 256
|
||
|
|
||
|
//
|
||
|
// defaults for DIR.OPEN.ADAPTER, DLC_PARMS:
|
||
|
//
|
||
|
|
||
|
#define DD_DLC_MAX_SAP 2
|
||
|
#define DD_DLC_MAX_STATIONS 6
|
||
|
#define DD_DLC_MAX_GSAP 0
|
||
|
#define DD_DLC_T1_TICK_ONE 5
|
||
|
#define DD_DLC_T2_TICK_ONE 1
|
||
|
#define DD_DLC_Ti_TICK_ONE 25
|
||
|
#define DD_DLC_T1_TICK_TWO 25
|
||
|
#define DD_DLC_T2_TICK_TWO 10
|
||
|
#define DD_DLC_Ti_TICK_TWO 125
|
||
|
|
||
|
//
|
||
|
// defaults for DLC.OPEN.SAP:
|
||
|
//
|
||
|
|
||
|
#define DD_MAXOUT 2
|
||
|
#define DD_MAXIN 1
|
||
|
#define DD_MAX_RETRY_COUNT 8
|
||
|
#define DD_MAX_I_FIELD 600
|
||
|
#define DD_DLC_BUF_SIZE 160
|
||
|
#define DD_DLC_POOL_LEN 256
|
||
|
|
||
|
//
|
||
|
// macros
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// DOS_PTR_TO_FLAT - given a DOS 16:16 pointer stored implicitly as a DWORD
|
||
|
//
|
||
|
|
||
|
#define DOS_PTR_TO_FLAT(a) (PVOID)GetVDMAddr(HIWORD(a), LOWORD(a))
|
||
|
|
||
|
//
|
||
|
// NEW_DOS_ADDRESS - generate a new DOS_ADDRESS, given a base DOS_ADDRESS and
|
||
|
// a new pointer which is some number of bytes plus the base DOS_ADDRESS
|
||
|
// converted to a flat pointer. For example, a DOS_ADDRESS of 1234:0000 becomes
|
||
|
// (on x86) a flat pointer of 0x12340. We generate a new pointer 0x12380 and
|
||
|
// want to convert this address back to a DOS_ADDRESS. So we use this macro.
|
||
|
// Offset-wrap and segment update is automatically handled
|
||
|
//
|
||
|
|
||
|
#define NEW_DOS_ADDRESS(b, p) ((b) + ((DWORD)(p) - (DWORD)DOS_PTR_TO_FLAT(b)))
|
||
|
|
||
|
//
|
||
|
// POOL_INDEX_FROM_SAP - get the index in aBufferPools for a given SAP/adapter
|
||
|
// combination. There are a maximum 127 SAPs per adapter, and 2 adapters which
|
||
|
// are available to DOS
|
||
|
//
|
||
|
|
||
|
#define POOL_INDEX_FROM_SAP(Sap, Adapter) ((Sap & 0xfe) | Adapter)
|
||
|
|
||
|
//
|
||
|
// POOL_INDEX_FROM_ID - given a station ID (high byte = SAP, low byte = link
|
||
|
// station), get the index to the SAP's buffer pool in aBufferPools
|
||
|
//
|
||
|
|
||
|
#define POOL_INDEX_FROM_ID(Id, Adapter) POOL_INDEX_FROM_SAP(HIBYTE(Id), Adapter)
|
||
|
|
||
|
//
|
||
|
// GET_POOL_INDEX - the original pool index macro
|
||
|
//
|
||
|
|
||
|
#define GET_POOL_INDEX(Adapter, usStationId) POOL_INDEX_FROM_ID(usStationId, Adapter)
|
||
|
|
||
|
//
|
||
|
// macros which initialize CCBs and call AcsLan
|
||
|
//
|
||
|
|
||
|
#define DlcFlowControl(Adapter, StationId, Options)\
|
||
|
LlcCommand(Adapter, LLC_DLC_FLOW_CONTROL, ((DWORD)Options << 16) + StationId)
|
||
|
|
||
|
#define DosDlcFlowControl(Adapter, StationId, Options)\
|
||
|
LlcCommand(Adapter, LLC_DOS_DLC_FLOW_CONTROL, ((DWORD)Options << 16) + StationId)
|
||
|
|
||
|
#define InitializeCcb(pCcb, AdapterNumber, Command, pParameter) \
|
||
|
RtlZeroMemory((pCcb), sizeof(*(pCcb)));\
|
||
|
RtlZeroMemory((pParameter), sizeof(*(pParameter)));\
|
||
|
(pCcb)->uchAdapterNumber = (UCHAR)AdapterNumber;\
|
||
|
(pCcb)->uchDlcCommand = (UCHAR)Command;\
|
||
|
(pCcb)->u.pParameterTable = (PLLC_PARMS)(pParameter)
|
||
|
|
||
|
#define InitializeCcb2(pCcb, AdapterNumber, Command) \
|
||
|
RtlZeroMemory((pCcb), sizeof(*(pCcb)));\
|
||
|
(pCcb)->uchAdapterNumber = (UCHAR)AdapterNumber;\
|
||
|
(pCcb)->uchDlcCommand = (UCHAR)Command;
|
||
|
|
||
|
#define ReceiveCancel(AdapterNumber, pCcb) \
|
||
|
LlcCommand(AdapterNumber, LLC_RECEIVE_CANCEL, (DWORD)pCcb)
|
||
|
|
||
|
//
|
||
|
// DLC_ERROR_STATUS - after calling AcsLan, if an error was returned by AcsLan
|
||
|
// then return that, else get the return code out of the CCB and return that
|
||
|
//
|
||
|
|
||
|
#define DLC_ERROR_STATUS(AcslanStatus, uchDlcStatus) \
|
||
|
(DWORD)((AcslanStatus == 0) ? (DWORD)uchDlcStatus : (DWORD)AcslanStatus)
|
||
|
|
||
|
//
|
||
|
// VRDLC_ALLOC - standard allocation strategy in VDM REDIR DLC functions
|
||
|
//
|
||
|
|
||
|
#define VRDLC_ALLOC(Bytes) LocalAlloc(LMEM_FIXED, Bytes)
|
||
|
|
||
|
//
|
||
|
// VRDLC_FREE - companion to VRDLC_ALLOC - standard allocation free strategy
|
||
|
//
|
||
|
|
||
|
#define VRDLC_FREE(Pointer) LocalFree((HLOCAL)Pointer)
|
||
|
|
||
|
//
|
||
|
// SAP_ID - get the SAP from a station ID word. Used as array index 0..127
|
||
|
// (corresponding to SAP 0..254 step 2)
|
||
|
//
|
||
|
|
||
|
#define SAP_ID(stationId) (HIBYTE(stationId) >> 1)
|
||
|
|
||
|
//
|
||
|
// LINK_ID - get the link station ID from a station ID word. Used as array index
|
||
|
// 0..254 (corresponding to link station 1..255)
|
||
|
//
|
||
|
|
||
|
#define LINK_ID(stationId) (LOBYTE(stationId) - 1)
|
||
|
//
|
||
|
// types
|
||
|
//
|
||
|
|
||
|
union _LLC_DOS_PARMS;
|
||
|
typedef union _LLC_DOS_PARMS LLC_DOS_PARMS, *PLLC_DOS_PARMS;
|
||
|
typedef DWORD DOS_ADDRESS;
|
||
|
typedef DOS_ADDRESS DPLLC_DOS_BUFFER;
|
||
|
|
||
|
//
|
||
|
// LLC_DOS_BUFFER - this is a union of all the DOS DLC data buffers. There are
|
||
|
// basically 3 kinds: Buffer 1, the first buffer in a chain which contains net
|
||
|
// address info, this can be in contigous or non-contiguous form, and Buffer 2
|
||
|
// format which is the 2nd and subsequent buffers in a chain. DLC uses the
|
||
|
// buffers for received data. Transmit data (passed from the app to DLC) can
|
||
|
// use a buffer (or chain of buffers) from the pool or can source its own
|
||
|
// buffer. The latter is preferred since taking buffers which DLC would use
|
||
|
// for receiving data can leave DLC in the local busy state (ie no receive
|
||
|
// buffers)
|
||
|
//
|
||
|
|
||
|
#include <packon.h>
|
||
|
|
||
|
typedef union _LLC_DOS_BUFFER {
|
||
|
|
||
|
//
|
||
|
// pNext is just a pointer so we can follow the chain
|
||
|
//
|
||
|
|
||
|
union _LLC_DOS_BUFFER * pNext;
|
||
|
|
||
|
//
|
||
|
// NextDosBuffer is the Buffer 2 structure defined in the IBM Lan Tech.
|
||
|
// Ref. pg 2-45
|
||
|
//
|
||
|
|
||
|
struct _NextDosBuffer {
|
||
|
union _LLC_DOS_BUFFER * pNextBuffer;// next frame segment
|
||
|
WORD cbFrame; // length of the whole rcvd frame
|
||
|
WORD cbBuffer; // length of this segment
|
||
|
WORD offUserData; // offset of data from descr header
|
||
|
WORD cbUserData; // length of the data
|
||
|
} Next;
|
||
|
|
||
|
//
|
||
|
// NotContiguous is the Not contiguous MAC/Data Buffer 1 structure defined
|
||
|
// in IBM Lan Tech. Ref. pg 2-42
|
||
|
//
|
||
|
|
||
|
struct _DosDlcNotContiguousFirstBuffer {
|
||
|
union _LLC_DOS_BUFFER * pNextBuffer; // next frame segment
|
||
|
WORD cbFrame; // length of entire frame
|
||
|
WORD cbBuffer; // length of this buffer
|
||
|
WORD offUserData; // user data in this struct
|
||
|
WORD cbUserData; // length of user data
|
||
|
WORD usStationId; // ssnn station id
|
||
|
UCHAR uchOptions; // option byte from RECEIVE param tbl
|
||
|
UCHAR uchMsgType; // the message type
|
||
|
WORD cBuffersLeft; // number of basic buffer units left
|
||
|
UCHAR uchRcvFS; // the received frame status
|
||
|
UCHAR uchAdapterNumber; // current adapter number
|
||
|
UCHAR cbLanHeader; // length of the LAN header
|
||
|
UCHAR cbDlcHeader; // length of the DLC header
|
||
|
UCHAR auchLanHeader[32];// LAN header of the received frame
|
||
|
UCHAR auchDlcHeader[4]; // DLC header of the received frame
|
||
|
} NotContiguous;
|
||
|
|
||
|
//
|
||
|
// Contiguous is the Contiguous MAC/Data Buffer 1 structure defined
|
||
|
// in IBM Lan Tech. Ref. pg 2-43
|
||
|
//
|
||
|
|
||
|
struct _DosDlcContiguousFirstBuffer {
|
||
|
union _LLC_DOS_BUFFER * pNextBuffer; // next frame segment
|
||
|
WORD cbFrame; // length of entire frame
|
||
|
WORD cbBuffer; // length of this buffer
|
||
|
WORD offUserData; // user data in this struct
|
||
|
WORD cbUserData; // length of user data
|
||
|
WORD usStationId; // ssnn station id
|
||
|
UCHAR uchOptions; // option byte from RECEIVE param tbl
|
||
|
UCHAR uchMsgType; // the message type
|
||
|
WORD cBuffersLeft; // number of basic buffer units left
|
||
|
UCHAR uchRcvFS; // the received frame status
|
||
|
UCHAR uchAdapterNumber;
|
||
|
} Contiguous;
|
||
|
} LLC_DOS_BUFFER, *PLLC_DOS_BUFFER;
|
||
|
|
||
|
#include <packoff.h>
|
||
|
|
||
|
//
|
||
|
// DOS_DLC_BUFFER_POOL - there is one of these per each SAP per adapter (max.
|
||
|
// 127 SAPs per adapter * max. 2 adapters = 256), kept in an array. This
|
||
|
// structure maintains basic information about the DOS buffer pool - its
|
||
|
// starting address (dpBuffer) in DOS 16:16 format, the size of an individual
|
||
|
// buffer in the pool (BufferSize) and the number of buffers in the pool
|
||
|
// (BufferCount). A buffer must be an integral multiple of 16 bytes, a minimum
|
||
|
// length of 80 bytes and not exceeding 64K-16 (0xfff0 = 65520)
|
||
|
//
|
||
|
|
||
|
typedef struct _DOS_DLC_BUFFER_POOL {
|
||
|
DOS_ADDRESS dpBuffer;
|
||
|
WORD BufferSize;
|
||
|
WORD BufferCount;
|
||
|
WORD MaximumBufferCount;
|
||
|
} DOS_DLC_BUFFER_POOL, *PDOS_DLC_BUFFER_POOL;
|
||
|
|
||
|
//
|
||
|
// DOS DLC CCB aka CCB1 - see definition in IBM Lan Tech. Ref. pg 2-6
|
||
|
//
|
||
|
|
||
|
#include <packon.h>
|
||
|
|
||
|
typedef struct _LLC_DOS_CCB {
|
||
|
UCHAR uchAdapterNumber; // Adapter 0 or 1
|
||
|
UCHAR uchDlcCommand; // DLC command
|
||
|
UCHAR uchDlcStatus; // DLC command completion code
|
||
|
UCHAR uchReserved1; // reserved for DLC DLL
|
||
|
struct _LLC_DOS_CCB *pNext; // queued another CCB
|
||
|
DWORD ulCompletionFlag; // used in command completion
|
||
|
union {
|
||
|
PLLC_DOS_PARMS pParms; // pointer to the parameter table
|
||
|
struct {
|
||
|
WORD usStationId; // Station id
|
||
|
WORD usParameter; // optional parameter
|
||
|
} dlc;
|
||
|
struct {
|
||
|
WORD usParameter0; // first optional parameter
|
||
|
WORD usParameter1; // second optional parameter
|
||
|
} dir;
|
||
|
UCHAR auchBuffer[4]; // group/functional address
|
||
|
DWORD ulParameter;
|
||
|
} u;
|
||
|
} LLC_DOS_CCB, *PLLC_DOS_CCB;
|
||
|
|
||
|
//
|
||
|
// additional parameter tables not defined in (sdk\inc\) DLCAPI.H (or where
|
||
|
// CCB1 parameter tables different from those defined in DLCAPI.H)
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// LLC_DOS_DIR_INITIALIZE_PARMS - CCB1 DIR.INITIALIZE parameter table
|
||
|
//
|
||
|
|
||
|
typedef struct {
|
||
|
WORD BringUps;
|
||
|
WORD SharedRamAddress;
|
||
|
WORD Reserved;
|
||
|
DWORD AdapterCheckExit;
|
||
|
DWORD NetworkStatusExit;
|
||
|
DWORD PcErrorExit;
|
||
|
} LLC_DOS_DIR_INITIALIZE_PARMS, *PLLC_DOS_DIR_INITIALIZE_PARMS;
|
||
|
|
||
|
//
|
||
|
// ADAPTER_PARMS, DIRECT_PARMS, DLC_PARMS and NCB_PARMS - these are the
|
||
|
// parameter tables which are passed in to DIR.OPEN.ADAPTER
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// ADAPTER_PARMS - parameters returned from the adapter support s/w
|
||
|
//
|
||
|
|
||
|
typedef struct _ADAPTER_PARMS {
|
||
|
WORD OpenErrorCode; // error detected opening adapter
|
||
|
WORD OpenOptions; // options for Token Ring only:
|
||
|
|
||
|
//
|
||
|
// OpenOptions Bit Meanings
|
||
|
//
|
||
|
// This has been paraphrased from the IBM Lan Tech. Ref. p3-22. I don't
|
||
|
// understand most of it, but I think I made it easier to read than the
|
||
|
// IBM technicalese. Note: ONLY MEANINGFUL TO TOKEN RING ADAPTER
|
||
|
//
|
||
|
// Bit 15: Wrap Interface
|
||
|
// The adapter doesn't attach to the network; instead, all
|
||
|
// transmitted data is reflected back as received data
|
||
|
//
|
||
|
// Bit 14: Disable Hard Error
|
||
|
// Stops network status change involving "Hard Error" and
|
||
|
// "Transmit Beacon" bits from generating interrupt
|
||
|
//
|
||
|
// Bit 13: Disable Soft Errors
|
||
|
// Stops network status change involving "Soft Error" bit
|
||
|
// generating interrupt
|
||
|
//
|
||
|
// Bit 12: Pass Adapter MAC Frames
|
||
|
// Unsupported MAC frames are passed to the direct station.
|
||
|
// If OFF, these frames are ignored
|
||
|
//
|
||
|
// Bit 11: Pass Attention MAC Frames
|
||
|
// Passes attention MAC frames which are not the same as the last
|
||
|
// received Attention MAC Frame to the direct station. If OFF,
|
||
|
// these frames are not passed to the direct station (ie App)
|
||
|
//
|
||
|
// Bit 10: Reserved
|
||
|
// Should be zero, but not checked by adapter
|
||
|
//
|
||
|
// Bit 9: Pass Parameter Table
|
||
|
// If the adapter is already open, returns options specified
|
||
|
//
|
||
|
// Bit 8: Contender
|
||
|
// If ON, this adapter will participate in monitor contention
|
||
|
// (claim token), should the need arise. If OFF, and it is
|
||
|
// another adapter decides it is necessary to claim the token,
|
||
|
// this adapter will not participate
|
||
|
//
|
||
|
// If this adapter decides it is necessary to determine a new
|
||
|
// active monitor, this adapter will initiate monitor contention
|
||
|
// processing IRRESPECTIVE OF THE VALUE OF THIS BIT
|
||
|
//
|
||
|
// Bit 7: Pass Beacon MAC Frames
|
||
|
// Pass to direct station first Beacon MAC frame and all subsequent
|
||
|
// Beacon MAC frames having a change in source address or beacon type
|
||
|
//
|
||
|
// Bit 6: Reserved
|
||
|
// Should be zero, but not checked by adapter
|
||
|
//
|
||
|
// Bit 5: Remote Program Load
|
||
|
// Only implemented on 16/4 adapters. Prevents adapter becoming
|
||
|
// a monitor during open process. If ON, will cause this adapter
|
||
|
// to fail the open if there are no other active adapters on the
|
||
|
// ring when it tries to insert itself
|
||
|
//
|
||
|
// Bit 4: Token Release
|
||
|
// Only implemented on 16/4 adapters and only available when
|
||
|
// operating at 16 Mbps. OFF: use early token release (default).
|
||
|
// ON: selects no early token release for adapter a 16 Mbps
|
||
|
//
|
||
|
// Bit 3: Reserved \
|
||
|
// Bit 2: Reserved > Should be 0, but are not checked by adapter
|
||
|
// Bit 1: Reserved /
|
||
|
// Bit 0: Reserved /
|
||
|
//
|
||
|
|
||
|
BYTE NodeAddress[6]; // this adapter's address
|
||
|
DWORD GroupAddress; // group address to set
|
||
|
DWORD FunctionalAddress; // functional address to set
|
||
|
WORD NumberReceiveBuffers; // number of receive buffers
|
||
|
WORD ReceiveBufferLength; // size of receive buffer
|
||
|
WORD DataHoldBufferLength; // size of transmit data hold buffer
|
||
|
BYTE NumberDataHoldBuffers; // returned: only by Token Ring
|
||
|
BYTE Reserved;
|
||
|
WORD OpenLock; // Protection code to control closing adapter
|
||
|
// This is NOT RETURNED when OpenOptions.9
|
||
|
// is set (Pass parameter table)
|
||
|
DWORD ProductId; // 18-byte product ID
|
||
|
// This is NOT RETURNED when OpenOptions.9
|
||
|
// is set (Pass parameter table)
|
||
|
//
|
||
|
// according to table 3-9 in IBM LAN Tech. Ref. (p3-25) the ProductId field
|
||
|
// should point at an 18-byte buffer formatted like so:
|
||
|
//
|
||
|
// Byte 0 0x01 indicates workstation
|
||
|
// Byte 1 0x10
|
||
|
// Byte 2-5 last 4 digits from workstation serial number in EBCDIC
|
||
|
// Byte 6-17 0x00
|
||
|
//
|
||
|
} ADAPTER_PARMS, *PADAPTER_PARMS;
|
||
|
|
||
|
//
|
||
|
// DIRECT_PARMS - input parameters defining Direct Station for adapter
|
||
|
//
|
||
|
|
||
|
typedef struct _DIRECT_PARMS {
|
||
|
|
||
|
//
|
||
|
// the direct buffer size is min. 80 bytes, and must be integral multiple
|
||
|
// of 16-bytes. If 0, default of 160 is used
|
||
|
//
|
||
|
|
||
|
WORD DirectBufferSize; // size of buffers in direct buffer pool
|
||
|
|
||
|
|
||
|
//
|
||
|
// direct pool blocks - number of 16-byte blocks in direct station buffer
|
||
|
// pool. If 0, default of 256 is used (= 4096 byte buffer pool)
|
||
|
//
|
||
|
|
||
|
WORD DirectPoolBlocks; // size of buffer in 16-byte blocks
|
||
|
|
||
|
|
||
|
//
|
||
|
// direct buffer pool - segment address in workstation memory where direct
|
||
|
// station buffer pool is created. Spec. doesn't say what happens if there
|
||
|
// is a non-zero (or any, for that matter) offset. If 0, the application
|
||
|
// must build the direct station buffer pool, in which case DirectBufferSize
|
||
|
// must indicate the size of each buffer
|
||
|
//
|
||
|
|
||
|
DWORD DirectBufferPool; // start address of direct buffer pool
|
||
|
|
||
|
|
||
|
//
|
||
|
// adapter check exit - vectors to this address when the adapter detects
|
||
|
// an internal error. If 0, the value specified in DIR.INITIALIZE is used
|
||
|
//
|
||
|
|
||
|
DWORD AdapterCheckExit; // I/O appendage exit: adapter check
|
||
|
|
||
|
|
||
|
//
|
||
|
// network status exit - vectors to this address when the network status
|
||
|
// changes (whatever that means). If 0, the value specified by
|
||
|
// DIR.INITIALIZE is used
|
||
|
//
|
||
|
|
||
|
DWORD NetworkStatusExit; // I/O appendage exit: network status change
|
||
|
|
||
|
|
||
|
//
|
||
|
// PC error exit - vectors to this address when the adapter s/w detects an
|
||
|
// error in the workstation (!). If 0, the value specified by DIR.INITIALIZE
|
||
|
// is used
|
||
|
//
|
||
|
|
||
|
DWORD PcErrorExit; // I/O appendage exit: error in workstation
|
||
|
|
||
|
|
||
|
//
|
||
|
// adapter work area - segment of area of w/s memory which is to be used
|
||
|
// by the adapter. Ignored if AdapterWorkAreaRequested is 0
|
||
|
//
|
||
|
|
||
|
DWORD AdapterWorkArea; // TR: adapter work are
|
||
|
|
||
|
|
||
|
//
|
||
|
// adapter work area length (requested) - the size of the workspace area,
|
||
|
// the segment of which is specified in AdapterWorkArea. Size is calculated
|
||
|
// thus: Number of SAPs x 36 + Number of stations (links) x 6 + 48
|
||
|
//
|
||
|
|
||
|
WORD AdapterWorkAreaRequested; // TR: work area length requested
|
||
|
|
||
|
|
||
|
//
|
||
|
// adapter work area length (actual) - this value is returned by the
|
||
|
// adapter. It is the amount of the work area used by the adapter (in bytes).
|
||
|
// If this is greater than AdapterWorkAreaRequested then an error is returned
|
||
|
// (0x12)
|
||
|
|
||
|
WORD AdapterWorkAreaActual; // TR: actual work area length taken
|
||
|
|
||
|
} DIRECT_PARMS, *PDIRECT_PARMS;
|
||
|
|
||
|
//
|
||
|
// DLC_PARMS - returned values defining DLC limits
|
||
|
//
|
||
|
|
||
|
typedef struct _DLC_PARMS {
|
||
|
|
||
|
//
|
||
|
// maximum number of concurrently opened SAPs: limited by available
|
||
|
// adapter memory and/or workspace memory. Maximum is 127 (126 if NetBIOS
|
||
|
// is specified). If 0, the default 2 is used
|
||
|
//
|
||
|
|
||
|
BYTE MaxSaps; // maximum number of SAPs
|
||
|
|
||
|
|
||
|
//
|
||
|
// maximum number of concurrently opened link stations: limited by
|
||
|
// available adapter and/or work area memory in workstation. Maximum is 255
|
||
|
// for Token Ring, Ethernet or PC Network. If 0, the default of 6 is used
|
||
|
//
|
||
|
|
||
|
BYTE MaxStations; // maximum number of link stations
|
||
|
|
||
|
|
||
|
//
|
||
|
// maximum number of group SAPs concurrently opened. If 0, no group SAPs
|
||
|
// can be opened. Maximum value is 126 for Token Ring, 125 for PC Network
|
||
|
// and Ethernet
|
||
|
//
|
||
|
|
||
|
BYTE MaxGroupSaps; // maximum number of group SAPs
|
||
|
|
||
|
|
||
|
//
|
||
|
// maximum number of SAPs assigned to a group. Maximum is 127 for Token
|
||
|
// Ring, 126 for PC Network and Ethernet
|
||
|
//
|
||
|
|
||
|
BYTE MaxGroupMembers; // maximum members per group SAP
|
||
|
|
||
|
|
||
|
//
|
||
|
// Timers. There are 3 timers: T1 is the Response Timer; T2 is the Inactivity
|
||
|
// Timer; and Ti is the Receiver Acknowledgement Timer.
|
||
|
//
|
||
|
// Timers are set to a multiple of 40ms. They count down and interrupt the
|
||
|
// adapter when they reach 0. Timer values can be between 1 and 10. If it
|
||
|
// is between 1 and 5, the short timer tick (TICK_ONE) is used and is
|
||
|
// referred to as group 1. If the number is between 6 and 10, the long timer
|
||
|
// tick (TICK_TWO) is used and is referred to as group 2. The timer value is
|
||
|
// the number (6 to 10) minus 5 multiplied by the long tick value.
|
||
|
//
|
||
|
|
||
|
//
|
||
|
// Tick1 - number of 40 ms ticks for short DLC timer. Defaults (if 0):
|
||
|
// T1 5 (200ms-400ms)
|
||
|
// T2 1 (40ms-80ms)
|
||
|
// Ti 25 (1s-2s)
|
||
|
//
|
||
|
|
||
|
BYTE T1Tick1; // Timer 1 short timer
|
||
|
BYTE T2Tick1; // Timer 2 short timer
|
||
|
BYTE TiTick1; // Timer i short timer
|
||
|
|
||
|
|
||
|
//
|
||
|
// Tick2 - number of 40 ms ticks for long DLC timer. Default (if 0):
|
||
|
// T1 25 (1s-2s)
|
||
|
// T2 10 (400ms-800ms)
|
||
|
// Ti 125 (5s-10s)
|
||
|
//
|
||
|
|
||
|
BYTE T1Tick2; // Timer 1 long timer
|
||
|
BYTE T2Tick2; // Timer 2 long timer
|
||
|
BYTE TiTick2; // Timer i long timer
|
||
|
} DLC_PARMS, *PDLC_PARMS;
|
||
|
|
||
|
//
|
||
|
// NCB_PARMS - we are not interested in running DOS NETBIOS over DOS DLC (are we?)
|
||
|
//
|
||
|
|
||
|
typedef struct _NCB_PARMS {
|
||
|
BYTE Reserved1[4]; // adapter work area
|
||
|
BYTE TimerT1;
|
||
|
BYTE TimerT2;
|
||
|
BYTE TimerTi;
|
||
|
BYTE MaxOut;
|
||
|
BYTE MaxIn;
|
||
|
BYTE MaxOutIncr;
|
||
|
BYTE MaxRetry;
|
||
|
BYTE Reserved2[4];
|
||
|
BYTE NcbAccessPri;
|
||
|
BYTE MaxStations;
|
||
|
BYTE Reserved3[19];
|
||
|
BYTE MaxNames;
|
||
|
BYTE MaxNcbs;
|
||
|
BYTE MaxSessions;
|
||
|
BYTE Reserved4[2];
|
||
|
BYTE Options;
|
||
|
WORD PoolLength;
|
||
|
DWORD PoolAddress;
|
||
|
BYTE TxTimeout;
|
||
|
BYTE TxCount;
|
||
|
} NCB_PARMS, *PNCB_PARMS;
|
||
|
|
||
|
//
|
||
|
// LLC_DOS_DIR_OPEN_ADAPTER_PARMS is the CCB1 DIR.OPEN.ADAPTER parameter table
|
||
|
//
|
||
|
|
||
|
typedef struct _LLC_DOS_DIR_OPEN_ADAPTER_PARMS {
|
||
|
PADAPTER_PARMS pAdapterParms;
|
||
|
PDIRECT_PARMS pDirectParms;
|
||
|
PDLC_PARMS pDlcParms;
|
||
|
PNCB_PARMS pNcbParms;
|
||
|
} LLC_DOS_DIR_OPEN_ADAPTER_PARMS, *PLLC_DOS_DIR_OPEN_ADAPTER_PARMS;
|
||
|
|
||
|
//
|
||
|
// LLC_DOS_RECEIVE_PARMS is the CCB1 RECEIVE parameter table
|
||
|
//
|
||
|
|
||
|
typedef struct _LLC_DOS_RECEIVE_PARMS {
|
||
|
WORD usStationId; // SAP, link station or direct id
|
||
|
WORD usUserLength; // length of user data in buffer header
|
||
|
DWORD ulReceiveExit; // the received data handler
|
||
|
PLLC_BUFFER pFirstBuffer; // first buffer in the pool
|
||
|
UCHAR uchOptions; // defines how the frame is received
|
||
|
} LLC_DOS_RECEIVE_PARMS, *PLLC_DOS_RECEIVE_PARMS;
|
||
|
|
||
|
//
|
||
|
// LLC_DOS_RECEIVE_PARMS_EX is an extended version of the LLC_DOS_RECEIVE_PARMS
|
||
|
// parameter table. We keep extra information - the DOS address of the original
|
||
|
// CCB and the original RECEIVE_DATA completion exit routine
|
||
|
//
|
||
|
|
||
|
typedef struct _LLC_DOS_RECEIVE_PARMS_EX {
|
||
|
WORD usStationId; // SAP, link station or direct id
|
||
|
WORD usUserLength; // length of user data in buffer header
|
||
|
DWORD ulReceiveExit; // the received data handler
|
||
|
PLLC_BUFFER pFirstBuffer; // first buffer in the pool
|
||
|
UCHAR uchOptions; // defines how the frame is received
|
||
|
UCHAR auchReserved1[3]; //
|
||
|
UCHAR uchRcvReadOption; // defines if rcv frames are chained
|
||
|
UCHAR auchReserved2[3]; // align dpOriginalCcbAddress on DWORD
|
||
|
DOS_ADDRESS dpOriginalCcbAddress; // dos address of orginal ccb
|
||
|
DOS_ADDRESS dpCompletionFlag; // orginal completion flag
|
||
|
} LLC_DOS_RECEIVE_PARMS_EX, *PLLC_DOS_RECEIVE_PARMS_EX;
|
||
|
|
||
|
//
|
||
|
// LLC_DOS_RECEIVE_MODIFY_PARMS is the parameter table for RECEIVE.MODIFY which
|
||
|
// we don't seem to support in NT native DLC
|
||
|
//
|
||
|
|
||
|
typedef struct {
|
||
|
WORD StationId; // SAP & link station Id
|
||
|
WORD UserLength; // length of user area in buffer
|
||
|
DWORD ReceivedDataExit; // address of routine to call with data
|
||
|
DWORD FirstBuffer; // pointer to first buffer from pool
|
||
|
DWORD Subroutine; // address of routine to call to get app buffer
|
||
|
} LLC_DOS_RECEIVE_MODIFY_PARMS, *PLLC_DOS_RECEIVE_MODIFY_PARMS;
|
||
|
|
||
|
//
|
||
|
// LLC_DOS_TRANSMIT_PARMS this structure is identical to LLC_TRANSMIT_PARMS
|
||
|
// except that there is no XMIT_READ_OPTION byte on the end, and the types of
|
||
|
// the fields are different, although the sizes are the same: eg. DOS_ADDRESS
|
||
|
// instead of PVOID or PLLC_XMIT_BUFFER
|
||
|
//
|
||
|
|
||
|
typedef struct _LLC_DOS_TRANSMIT_PARMS {
|
||
|
WORD usStationId; // SAP and link station ID
|
||
|
BYTE uchTransmitFs; // returned: Frame Status
|
||
|
BYTE uchRemoteSap; // remote SAP we're talking to
|
||
|
DOS_ADDRESS pXmitQueue1; // address of 1st buffer queue. Not pooled
|
||
|
DOS_ADDRESS pXmitQueue2; // address of 2nd buffer queue. Pooled
|
||
|
WORD cbBuffer1; // length of data in pBuffer1
|
||
|
WORD cbBuffer2; // length of data in pBuffer2
|
||
|
DOS_ADDRESS pBuffer1; // address of 1st data buffer
|
||
|
DOS_ADDRESS pBuffer2; // address of 2nd data buffer
|
||
|
} LLC_DOS_TRANSMIT_PARMS, *PLLC_DOS_TRANSMIT_PARMS;
|
||
|
|
||
|
typedef struct _LLC_MODIFY_OPEN_PARMS {
|
||
|
WORD usBufferSize; // block size of dlc buffers (>=80)
|
||
|
WORD cPoolBlocks; // number of 16 bytes blocks in buffer
|
||
|
DOS_ADDRESS dpPoolAddress;
|
||
|
DOS_ADDRESS dpAdapterCheckExit;
|
||
|
DOS_ADDRESS dpNetworkStatusExit;
|
||
|
DOS_ADDRESS dpPcErrorExit;
|
||
|
WORD usOpenOption;
|
||
|
} LLC_MODIFY_OPEN_PARMS, *PLLC_MODIFY_OPEN_PARMS;
|
||
|
|
||
|
typedef struct _DOS_DLC_DIRECT_PARMS {
|
||
|
WORD usBufferSize; // block size of dlc buffers (>=80)
|
||
|
WORD cPoolBlocks; // number of 16 bytes blocks in buffer
|
||
|
DOS_ADDRESS dpPoolAddress; //
|
||
|
DOS_ADDRESS dpAdapterCheckExit;
|
||
|
DOS_ADDRESS dpNetworkStatusExit;
|
||
|
DOS_ADDRESS dpPcErrorExit;
|
||
|
DWORD ulReserved1;
|
||
|
WORD usReserved2;
|
||
|
WORD usReserved3;
|
||
|
} DOS_DLC_DIRECT_PARMS, *PDOS_DLC_DIRECT_PARMS;
|
||
|
|
||
|
typedef struct _DOS_DLC_OPEN_SAP_PARMS {
|
||
|
WORD usStationId; // SAP or link station id
|
||
|
WORD usUserStatValue; // reserved for user
|
||
|
UCHAR uchT1; // response timer
|
||
|
UCHAR uchT2; // aknowledgment timer
|
||
|
UCHAR uchTi; // inactivity timer
|
||
|
UCHAR uchMaxOut; // max tramists without ack
|
||
|
UCHAR uchMaxIn; // max receives without ack
|
||
|
UCHAR uchMaxOutIncr; // dynamic window increment value
|
||
|
UCHAR uchMaxRetryCnt; // N2 value (retries)
|
||
|
UCHAR uchMaxMembers; // maximum members for group SAP
|
||
|
WORD usMaxI_Field; // maximum length of the Info field
|
||
|
UCHAR uchSapValue; // SAP value to be assigned
|
||
|
UCHAR uchOptionsPriority; // SAP options and access priority
|
||
|
UCHAR uchcStationCount; // maximum number of link stations in sap
|
||
|
UCHAR uchReserved2[2]; //
|
||
|
UCHAR cGroupCount; // number of group SAPs of this SAP
|
||
|
PUCHAR pGroupList; // offset to the group list
|
||
|
DWORD DlcStatusFlags; // User notify flag for DLC status changes
|
||
|
WORD usBufferSize; // size of individual buffer in bytes
|
||
|
WORD cPoolBlocks; // number of 16-byte blocks in pool
|
||
|
DOS_ADDRESS dpPoolAddress; // address of Buffer Pool (may be 0)
|
||
|
} DOS_DLC_OPEN_SAP_PARMS, *PDOS_DLC_OPEN_SAP_PARMS;
|
||
|
|
||
|
typedef struct _DOS_DIR_STATUS_PARMS {
|
||
|
UCHAR auchPermanentAddress[6];// permanent encoded address
|
||
|
UCHAR auchNodeAddress[6]; // adapter's network address
|
||
|
UCHAR auchGroupAddress[4]; // adapter's group address
|
||
|
UCHAR auchFunctAddr[4]; // adapter's functional address
|
||
|
UCHAR uchMaxSap; // maximum allowable SAP
|
||
|
UCHAR uchOpenSaps; // number of currently open saps
|
||
|
UCHAR uchMaxStations; // max number of stations (always 253)
|
||
|
UCHAR uchOpenStation; // number of open stations (only up to 253)
|
||
|
UCHAR uchAvailStations; // number of available stations (always 253)
|
||
|
UCHAR uchAdapterConfig; // adapter configuration flags
|
||
|
UCHAR auchMicroCodeLevel[10]; // microcode level
|
||
|
DOS_ADDRESS dpAdapterParmsAddr; // shared RAM address of adapter parms
|
||
|
DOS_ADDRESS dpAdapterMacAddr; // shared RAM address of adapter MAC buffer
|
||
|
DOS_ADDRESS dpTimerTick; // address of DLC timer tick counter
|
||
|
USHORT usLastNetworkStatus; // most recent network status issued
|
||
|
DOS_ADDRESS dpExtendedParms; // address of extended status table
|
||
|
} DOS_DIR_STATUS_PARMS, *PDOS_DIR_STATUS_PARMS;
|
||
|
|
||
|
typedef struct {
|
||
|
DOS_ADDRESS dpAdapterCheckExit; // adapter check appendage
|
||
|
DOS_ADDRESS dpNetworkStatusExit; // network status change appendage
|
||
|
DOS_ADDRESS dpPcErrorExit; // workstation error appendage
|
||
|
} LLC_DIR_SET_USER_APPENDAGE_PARMS, *PLLC_DIR_SET_USER_APPENDAGE_PARMS;
|
||
|
|
||
|
#include <packoff.h>
|
||
|
|
||
|
union _LLC_DOS_PARMS {
|
||
|
LLC_BUFFER_FREE_PARMS BufferFree;
|
||
|
LLC_BUFFER_GET_PARMS BufferGet;
|
||
|
LLC_DLC_CONNECT_PARMS DlcConnectStation;
|
||
|
LLC_DLC_MODIFY_PARMS DlcModify;
|
||
|
LLC_DLC_OPEN_SAP_PARMS DlcOpenSap;
|
||
|
LLC_DLC_OPEN_STATION_PARMS DlcOpenStation;
|
||
|
LLC_DLC_REALLOCATE_PARMS DlcReallocate;
|
||
|
LLC_DLC_SET_THRESHOLD_PARMS DlcSetThreshold;
|
||
|
LLC_DLC_STATISTICS_PARMS DlcStatistics;
|
||
|
LLC_DIR_INITIALIZE_PARMS DirInitialize;
|
||
|
LLC_MODIFY_OPEN_PARMS DirModifyOpenParms;
|
||
|
LLC_DIR_OPEN_ADAPTER_PARMS DirOpenAdapter;
|
||
|
LLC_DIR_OPEN_DIRECT_PARMS DirOpenDirect;
|
||
|
LLC_DIR_READ_LOG_PARMS DirReadLog;
|
||
|
LLC_DIR_SET_EFLAG_PARMS DirSetExceptionFlags;
|
||
|
LLC_DIR_SET_USER_APPENDAGE_PARMS DirSetUserAppendage;
|
||
|
LLC_DIR_STATUS_PARMS DirStatus;
|
||
|
DOS_DIR_STATUS_PARMS DosDirStatus;
|
||
|
LLC_READ_PARMS Read;
|
||
|
LLC_DOS_RECEIVE_PARMS_EX Receive;
|
||
|
LLC_DOS_RECEIVE_PARMS DosReceive;
|
||
|
LLC_TRANSMIT_PARMS Transmit;
|
||
|
LLC_TRANSMIT2_COMMAND Transmit2;
|
||
|
LLC_TRACE_INITIALIZE_PARMS TraceInitialize;
|
||
|
DOS_DLC_OPEN_SAP_PARMS DosDlcOpenSap;
|
||
|
};
|
||
|
|
||
|
//
|
||
|
// ADAPTER_TYPE - what type of network adapter we have - Token Ring, Ethernet
|
||
|
// or (less likely) PC network
|
||
|
//
|
||
|
|
||
|
typedef enum {
|
||
|
TokenRing,
|
||
|
Ethernet,
|
||
|
PcNetwork,
|
||
|
UnknownAdapter
|
||
|
} ADAPTER_TYPE;
|
||
|
|
||
|
//
|
||
|
// LOCAL_BUSY_STATE - a link station can be in 1 of 3 emulated local-busy
|
||
|
// (buffer) states:
|
||
|
//
|
||
|
// NOT_BUSY
|
||
|
// the station doesn't have any backed-up I-frames pending
|
||
|
//
|
||
|
// BUSY
|
||
|
// the station is in emulated local-busy(buffer) state and a
|
||
|
// DLC.FLOW.CONTROL(local-busy(buffer), set) has been sent to
|
||
|
// the DLC device driver
|
||
|
//
|
||
|
// BUSY_BUFFER
|
||
|
// to get out of BUSY state into CLEARING, we need at least one buffer and
|
||
|
// a DLC.FLOW.CONTROL from the app. Because apps can issue DLC.FLOW.CONTROL
|
||
|
// and BUFFER.FREE in the wrong order, we need an AND of these 2 commands
|
||
|
// to get going again. So we have this intermediate state where we are
|
||
|
// awaiting either command to restart I-Frame reception
|
||
|
//
|
||
|
// BUSY_FLOW
|
||
|
// Together with BUSY_BUFFER, used to create a hysteresis whereby we can't
|
||
|
// reach CLEARING from BUSY without getting both a DLC.FLOW.CONTROL and
|
||
|
// BUFFER.FREE
|
||
|
//
|
||
|
// CLEARING
|
||
|
// the VDM app has cleared the emulated local-busy state, but
|
||
|
// the DLC device driver is still in local-busy (buffer) state.
|
||
|
// When the last deferred I-Frame is indicated to the VDM app,
|
||
|
// the NT device driver local-busy(buffer) state will be reset
|
||
|
// and normal service will resume
|
||
|
//
|
||
|
//
|
||
|
// State transitions:
|
||
|
//
|
||
|
// NOT_BUSY -> BUSY
|
||
|
// occurs when we discover there aren't enough DOS buffers to
|
||
|
// receive an I-Frame. This transition is distinguished by the
|
||
|
// following actions:
|
||
|
//
|
||
|
// 1. DLC.FLOW.CONTROL(local-busy(buffer), set) is indicated to
|
||
|
// the DLC device driver
|
||
|
// 2. the received I-Frame is dequeued from the event queue for
|
||
|
// this adapter and queued on the LocalBusyInfo.Queue
|
||
|
// 3. a local-busy(buffer) DLC status change event is indicated to
|
||
|
// the DOS DLC app
|
||
|
//
|
||
|
// BUSY -> BUSY_FLOW/BUSY_BUFFER
|
||
|
// occurs when either a DLC.FLOW.CONTROL or BUFFER.FREE (resp) is issued
|
||
|
//
|
||
|
// BUSY_FLOW/BUSY_BUFFER -> CLEARING
|
||
|
// occurs when the DOS DLC app indicates we can continue receiving.
|
||
|
// This is done when the other (DLC.FLOW.CONTROL or BUFFER.FREE) required
|
||
|
// command is issued
|
||
|
// This transition is distinguished by the following actions:
|
||
|
//
|
||
|
// 1. DOS DLC app issues DLC.FLOW.CONTROL(local-busy(buffer), reset)
|
||
|
// 2. DOS DLC app *may* issue BUFFER.FREE to return receive
|
||
|
// buffers to the SAP pool
|
||
|
//
|
||
|
// CLEARING -> NOT_BUSY
|
||
|
// occurs when we indicate the last deferred receive to the DOS DLC
|
||
|
// app. At this point we can do the following:
|
||
|
//
|
||
|
// 1. issue DLC.FLOW.CONTROL(local-busy(buffer), reset) to the
|
||
|
// device driver
|
||
|
//
|
||
|
// CLEARING -> BUSY
|
||
|
// occurs when, during indicating deferred received I-Frames to the DOS
|
||
|
// DLC app, we once again run out of buffers. Again, we indicate a DLC
|
||
|
// status change of local-busy(buffer) to the DOS DLC app, but WE DO NOT
|
||
|
// indicate local-busy(buffer) to the DLC device driver (it is still in
|
||
|
// local-busy(buffer) state)
|
||
|
//
|
||
|
|
||
|
typedef enum {
|
||
|
NOT_BUSY = 0,
|
||
|
CLEARING,
|
||
|
BUSY,
|
||
|
BUSY_BUFFER,
|
||
|
BUSY_FLOW
|
||
|
} LOCAL_BUSY_STATE;
|
||
|
|
||
|
//
|
||
|
// LOCAL_BUSY_INFO - this structure maintains a local-busy(buffer) state
|
||
|
// indicator and a pointer to a queue of deferred received I-Frames per link
|
||
|
// station per adapter
|
||
|
//
|
||
|
|
||
|
typedef struct {
|
||
|
|
||
|
//
|
||
|
// State maintains the tri-state of the link station w.r.t. received I-Frames
|
||
|
//
|
||
|
// NOT_BUSY
|
||
|
// nothing queued on Queue, get next completed event from event Q
|
||
|
//
|
||
|
// BUSY
|
||
|
// local-busy(buffer) state has been set in DLC driver,
|
||
|
// awaiting buffers & flow control command from DOS DLC app
|
||
|
//
|
||
|
// CLEARING
|
||
|
// DOS DLC app has submitted DLC.FLOW.CONTROL(local_busy(buffer), reset)
|
||
|
// command, we are now trying to indicate deferred received I-Frames to
|
||
|
// DOS DLC app, pending enough DOS receive buffers
|
||
|
//
|
||
|
|
||
|
LOCAL_BUSY_STATE State;
|
||
|
|
||
|
//
|
||
|
// Queue - when in BUSY and CLEARING states, maintains a linked list of
|
||
|
// completed NT READ CCBs containing received I-Frames
|
||
|
//
|
||
|
|
||
|
PLLC_CCB Queue;
|
||
|
|
||
|
#if DBG
|
||
|
|
||
|
//
|
||
|
// track queue depth for each link station in debug version
|
||
|
//
|
||
|
|
||
|
DWORD Depth;
|
||
|
#endif
|
||
|
|
||
|
} LOCAL_BUSY_INFO;
|
||
|
|
||
|
//
|
||
|
// MAX_I_FRAME_DEPTH - we don't expect the queue of deferred I-Frames to grow
|
||
|
// beyond this small number. The deferred I-Frame queue is a buffer between
|
||
|
// running out of receive buffers & restarting I-Frame reception
|
||
|
//
|
||
|
|
||
|
#define MAX_I_FRAME_DEPTH 64 // !
|
||
|
|
||
|
//
|
||
|
// DOS_ADAPTER - there is one of these for each DOS adapter (i.e. 2 max.). The
|
||
|
// structure contains information about the virtual state of each DOS adapter.
|
||
|
// We record such information as the parameters used to open the adapter, the
|
||
|
// exit addresses and the direct station information
|
||
|
//
|
||
|
|
||
|
typedef struct {
|
||
|
|
||
|
//
|
||
|
// AdapterType - tells us what type (class?) of adapter we are using. We
|
||
|
// mainly use this to differentiate the types of values we return based
|
||
|
// on whether this is a Token Ring adapter. We get the information from
|
||
|
// the NT DIR.STATUS command
|
||
|
//
|
||
|
|
||
|
ADAPTER_TYPE AdapterType;
|
||
|
|
||
|
//
|
||
|
// IsOpen will be TRUE when this adapter has been successfully opened
|
||
|
//
|
||
|
|
||
|
BOOLEAN IsOpen;
|
||
|
|
||
|
//
|
||
|
// DirectStationOpen is TRUE when the direct station has been initialized
|
||
|
// for this adapter. This is required because the direct station is opened
|
||
|
// separately from the adapter in NT, but DOS expects both to be opened
|
||
|
// simultaneously. Hence, we only issue a DIR.OPEN.DIRECT when the DOS app
|
||
|
// issues a request for the direct station
|
||
|
//
|
||
|
|
||
|
BOOLEAN DirectStationOpen;
|
||
|
|
||
|
//
|
||
|
// if DirectReceive is TRUE then there is a receive outstanding on the
|
||
|
// direct station for this adapter
|
||
|
//
|
||
|
|
||
|
BOOLEAN DirectReceive;
|
||
|
|
||
|
//
|
||
|
// if WaitingRestore is TRUE then we must get a DIR.RESTORE.OPEN.PARMS
|
||
|
// before we can accept the next DIR.MODIFY.OPEN.PARMS
|
||
|
//
|
||
|
|
||
|
BOOLEAN WaitingRestore;
|
||
|
|
||
|
//
|
||
|
// BufferFree is TRUE when a BUFFER_FREE has been successfully issued for
|
||
|
// any station ID belonging to this adapter
|
||
|
//
|
||
|
|
||
|
BOOLEAN BufferFree;
|
||
|
|
||
|
//
|
||
|
// BufferPool is the buffer pool for this adapter's direct station
|
||
|
//
|
||
|
|
||
|
PVOID BufferPool;
|
||
|
|
||
|
//
|
||
|
// CurrentExceptionHandlers and PreviousExceptionHandlers are the addresses
|
||
|
// of exception 'exit' routines in DOS memory which are called asynchronously
|
||
|
// if one of the special exceptions occurs. These are mapped to exception
|
||
|
// flags in NT DLC and are presented as such in the READ CCB (ulCompletionFlag)
|
||
|
//
|
||
|
// exception handlers are always presented in the following order:
|
||
|
//
|
||
|
// Adapter Check Exit
|
||
|
// Network Status Exit
|
||
|
// PC Error Exit
|
||
|
//
|
||
|
|
||
|
DWORD CurrentExceptionHandlers[3];
|
||
|
DWORD PreviousExceptionHandlers[3];
|
||
|
|
||
|
//
|
||
|
// DlcStatusChangeAppendage - this appendage pointer is supplied in DLC.OPEN.SAP
|
||
|
// - one for each SAP. We need to keep them here because the emulator can
|
||
|
// generate its own DLC status change call-backs (local-busy(buffer))
|
||
|
//
|
||
|
|
||
|
DWORD DlcStatusChangeAppendage[DOS_DLC_MAX_SAPS];
|
||
|
|
||
|
//
|
||
|
// LastNetworkStatusChange is the last network status change we recorded.
|
||
|
// This is reported in DIR.STATUS
|
||
|
//
|
||
|
|
||
|
WORD LastNetworkStatusChange;
|
||
|
|
||
|
//
|
||
|
// UserStatusValue - we have to record the USER_STAT_VALUE from each
|
||
|
// successful DLC.OPEN.SAP. This is returned to the DLC status change
|
||
|
// appendage. We need this info for when we generate our own status change
|
||
|
// event (ie when we detect emulated local busy (buffer) state)
|
||
|
//
|
||
|
|
||
|
WORD UserStatusValue[DOS_DLC_MAX_SAPS];
|
||
|
|
||
|
//
|
||
|
// AdapterParms are the actual adapter parameters that this adapter was
|
||
|
// opened with - either specified in the DIR.OPEN.ADAPTER from the DOS
|
||
|
// app, or those which we use internally when we automatically open the
|
||
|
// adapter
|
||
|
//
|
||
|
|
||
|
ADAPTER_PARMS AdapterParms;
|
||
|
|
||
|
//
|
||
|
// DlcSpecified will be TRUE if the DLC_PARMS table was given when the
|
||
|
// adapter was opened (either by DIR.OPEN.ADAPTER from DOS app, or by
|
||
|
// DIR.OPEN.ADAPTER from automatic open)
|
||
|
//
|
||
|
|
||
|
BOOLEAN DlcSpecified;
|
||
|
|
||
|
//
|
||
|
// DlcParms - the DLC parameters specified in the open
|
||
|
//
|
||
|
|
||
|
DLC_PARMS DlcParms;
|
||
|
|
||
|
//
|
||
|
// AdapterCloseCcb - used in asynchronous adapter close when close is
|
||
|
// initiated by emulator
|
||
|
//
|
||
|
|
||
|
LLC_CCB AdapterCloseCcb;
|
||
|
|
||
|
//
|
||
|
// DirectCloseCcb - used in asynchronous direct station close when close is
|
||
|
// initiated by emulator
|
||
|
//
|
||
|
|
||
|
LLC_CCB DirectCloseCcb;
|
||
|
|
||
|
//
|
||
|
// ReadCcb - pointer to current READ CCB for this adapter
|
||
|
//
|
||
|
|
||
|
PLLC_CCB ReadCcb;
|
||
|
|
||
|
//
|
||
|
// EventQueueCritSec - must hold this while accessing EventQueue
|
||
|
//
|
||
|
|
||
|
CRITICAL_SECTION EventQueueCritSec;
|
||
|
|
||
|
//
|
||
|
// EventQueue - linked list of pending completed READ CCBs. These are linked
|
||
|
// by pNext field which is not normally used by READ CCB. The event queue is
|
||
|
// a serialized list of asynchronous events which have occurred for this
|
||
|
// adapter. Events are command completions, transmit completions, received
|
||
|
// data frames and status changes
|
||
|
//
|
||
|
|
||
|
PLLC_CCB EventQueueHead; // pointer to READ CCB at head of queue
|
||
|
PLLC_CCB EventQueueTail; // " " " " " end " "
|
||
|
DWORD QueueElements; // count of elements currently on EventQueue
|
||
|
|
||
|
//
|
||
|
// LocalBusyCritSec - must hold this while accessing DeferredReceives or
|
||
|
// LocalBusyInfo array
|
||
|
//
|
||
|
|
||
|
CRITICAL_SECTION LocalBusyCritSec;
|
||
|
|
||
|
//
|
||
|
// DeferredReceives - reference count of number of link stations for this
|
||
|
// adapter which are in local busy (buffer) state. Accessed while holding
|
||
|
// LocalBusyCritSec. Serves as a boolean: check for !0 to discover if there
|
||
|
// are deferred receives before checking all of LocalBusyInfo
|
||
|
//
|
||
|
|
||
|
DWORD DeferredReceives;
|
||
|
|
||
|
//
|
||
|
// FirstIndex and LastIndex - the start & stop points for searches through
|
||
|
// LocalBusyInfo. These are used in an attempt to improve searching, since
|
||
|
// for the vast majority of time, very few of the 255 possible slots in
|
||
|
// LocalBusyInfo will be used
|
||
|
//
|
||
|
// NOTE: these are array indicies, NOT link station ids (index = id - 1)
|
||
|
//
|
||
|
|
||
|
DWORD FirstIndex;
|
||
|
DWORD LastIndex;
|
||
|
|
||
|
//
|
||
|
// LocalBusyInfo - when a link station is in emulated local busy (buffer)
|
||
|
// state, we dequeue any completed received I-Frames from the event queue
|
||
|
// and link them onto the LocalBusyInfo list. For each adapter, there are
|
||
|
// 255 lists - one per link station (there are 255 possible link stations
|
||
|
// per adapter). The deferred receives are a list of completed NT READ CCBs
|
||
|
// linked by CCB.pNext field. The lists serve as a buffer between realizing
|
||
|
// we are out of buffers and the DLC device driver receiving the
|
||
|
// DLC.FLOW.CONTROL(set, buffer) command. The lists are not expected to
|
||
|
// grow very long
|
||
|
//
|
||
|
// This array combines the state of each link station for this adapter w.r.t.
|
||
|
// local-busy(buffer) and maintains the list of deferred I-Frames.
|
||
|
//
|
||
|
// The array is accessed both by the main VDM thread and the EventHandlerThread
|
||
|
// and so must only be accessed when holding LocalBusyCritSec
|
||
|
//
|
||
|
// Since there are 255 possible link stations per adapter and since the
|
||
|
// Direct Station doesn't support link stations, link station 01 uses slot
|
||
|
// 0, etc.
|
||
|
//
|
||
|
|
||
|
LOCAL_BUSY_INFO LocalBusyInfo[DOS_DLC_MAX_LINKS];
|
||
|
|
||
|
} DOS_ADAPTER, *PDOS_ADAPTER;
|
||
|
|
||
|
#define NO_LINKS_BUSY ((DWORD)0x7fffffff)
|
||
|
|
||
|
//
|
||
|
// DOS DLC prototypes and externals
|
||
|
//
|
||
|
|
||
|
extern PLLC_BUFFER aOverflowedData[];
|
||
|
extern DWORD OpenedAdapters;
|
||
|
extern DOS_ADDRESS dpVdmWindow;
|
||
|
|
||
|
//
|
||
|
// vrdlc5c.c
|
||
|
//
|
||
|
|
||
|
VOID
|
||
|
VrDlc5cHandler(
|
||
|
VOID
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
CompleteCcbProcessing(
|
||
|
IN LLC_STATUS Status,
|
||
|
IN LLC_DOS_CCB UNALIGNED * pCcb,
|
||
|
IN PLLC_PARMS pNtParms
|
||
|
);
|
||
|
|
||
|
LLC_STATUS
|
||
|
LlcCommand(
|
||
|
IN UCHAR AdapterNumber,
|
||
|
IN UCHAR Command,
|
||
|
IN DWORD Parameter
|
||
|
);
|
||
|
|
||
|
LLC_STATUS
|
||
|
BufferFree(
|
||
|
IN UCHAR AdapterNumber,
|
||
|
IN PVOID pFirstBuffer,
|
||
|
OUT LPWORD pusBuffersLeft
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
VrVdmWindowInit(
|
||
|
VOID
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
TerminateDlcEmulation(
|
||
|
VOID
|
||
|
);
|
||
|
|
||
|
//
|
||
|
// vrdlcbuf.c
|
||
|
//
|
||
|
|
||
|
VOID
|
||
|
InitializeBufferPools(
|
||
|
VOID
|
||
|
);
|
||
|
|
||
|
LLC_STATUS
|
||
|
CreateBufferPool(
|
||
|
IN DWORD PoolIndex,
|
||
|
IN DOS_ADDRESS dpBuffer,
|
||
|
IN WORD BufferCount,
|
||
|
IN WORD BufferSize
|
||
|
);
|
||
|
|
||
|
VOID
|
||
|
DeleteBufferPool(
|
||
|
IN DWORD PoolIndex
|
||
|
);
|
||
|
|
||
|
LLC_STATUS
|
||
|
GetBuffers(
|
||
|
IN DWORD PoolIndex,
|
||
|
IN WORD BuffersToGet,
|
||
|
IN DPLLC_DOS_BUFFER *pdpBuffer,
|
||
|
OUT LPWORD pusBuffersLeft,
|
||
|
IN BOOLEAN PartialList,
|
||
|
OUT PWORD BuffersGot OPTIONAL
|
||
|
);
|
||
|
|
||
|
LLC_STATUS
|
||
|
FreeBuffers(
|
||
|
IN DWORD PoolIndex,
|
||
|
IN DPLLC_DOS_BUFFER dpBuffer,
|
||
|
OUT LPWORD pusBuffersLeft
|
||
|
);
|
||
|
|
||
|
WORD
|
||
|
CalculateBufferRequirement(
|
||
|
IN UCHAR Adapter,
|
||
|
IN WORD StationId,
|
||
|
IN PLLC_BUFFER pFrame,
|
||
|
IN LLC_DOS_PARMS UNALIGNED * pDosParms,
|
||
|
OUT PWORD BufferSize
|
||
|
);
|
||
|
|
||
|
LLC_STATUS
|
||
|
CopyFrame(
|
||
|
IN PLLC_BUFFER pFrame,
|
||
|
IN DPLLC_DOS_BUFFER DosBuffers,
|
||
|
IN WORD UserLength,
|
||
|
IN WORD BufferSize,
|
||
|
IN DWORD Flags
|
||
|
);
|
||
|
|
||
|
BOOLEAN
|
||
|
AllBuffersInPool(
|
||
|
IN DWORD PoolIndex
|
||
|
);
|
||
|
|
||
|
//
|
||
|
// vrdlcpst.c
|
||
|
//
|
||
|
|
||
|
VOID
|
||
|
VrDlcInitialize(
|
||
|
VOID
|
||
|
);
|
||
|
|
||
|
BOOLEAN
|
||
|
VrDlcHwInterrupt(
|
||
|
VOID
|
||
|
);
|
||
|
|
||
|
BOOLEAN
|
||
|
ResetEmulatedLocalBusyState(
|
||
|
IN BYTE AdapterNumber,
|
||
|
IN WORD StationId,
|
||
|
IN BYTE DlcCommand
|
||
|
);
|
||
|
|
||
|
BOOLEAN
|
||
|
InitializeEventHandler(
|
||
|
VOID
|
||
|
);
|
||
|
|
||
|
PLLC_CCB
|
||
|
InitiateRead(
|
||
|
IN DWORD AdapterNumber,
|
||
|
OUT LLC_STATUS* ErrorStatus
|
||
|
);
|