SIMPLEX.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:51k
源码类别:

Windows编程

开发平台:

Visual C++

  1. /*++
  2. Copyright (c) 1994-1997  Microsoft Corporation
  3. Module Name:
  4.     simplex.c
  5. Abstract:
  6.     Simple single-threaded DLC test/example program. Need 2 instances of this
  7.     app - 1 to send and 1 to receive (i.e. the typical DLC situation hence
  8.     simplex, or half-duplex in old money). By default, both sides use SAP 4
  9.     Receiver is started:
  10.         simplex
  11.     Transmitter is started e.g.
  12.         simplex /t02608c4c970e
  13.     in this example the node address is in canonical form (ethernet format) as
  14.     displayed by "net config wksta", e.g., not the non-canonical (token-ring
  15.     format) that the DLC API expects. If this test app is being run over
  16.     token ring then you would supply the non-canonical address, as used by
  17.     token ring, e.g.
  18.         simplex /t10005a7b08b4
  19.     Command line options are:
  20.         /a# - use adapter #
  21.         /b# - change the buffer pool size from the default 20K to #
  22.         /o  - options:
  23.             /or# - set receive READ option
  24.             /ot# - set transmit READ option
  25.         /r# - send to remote SAP # (transmitter only)
  26.         /s# - open local SAP #
  27.         /t# - send to station address # (transmitter only)
  28.         /z# - transmit packets of size #, else send random sized packets
  29.               (transmitter only)
  30.     Contents:
  31.         main
  32.         usage
  33.         get_funky_number
  34.         is_radical_digit
  35.         char_to_number
  36.         handle_ctrl_c
  37.         terminate
  38.         xtou
  39.         open_adapter
  40.         adapter_status
  41.         close_adapter
  42.         create_buffer
  43.         open_sap
  44.         open_station
  45.         connect_station
  46.         flow_control
  47.         get_buffer
  48.         free_buffer
  49.         post_receive
  50.         post_read
  51.         tx_i_frame
  52.         slush
  53.         do_transmit
  54.         do_receive
  55.         check_keyboard
  56.         dispatch_read_events
  57.         handle_status_change
  58.         handle_receive_data
  59.         handle_transmit_complete
  60.         handle_command_complete
  61.         twiddle_bits
  62.         swap_bits
  63.         my_malloc
  64.         my_calloc
  65.         my_free
  66.         nice_num
  67. Author:
  68.     Richard L Firth (rfirth) 6-Mar-1994
  69. Environment:
  70.     Win32 app (console)
  71. Revision History:
  72. John Lee (johnlee) 22-Feb-1996
  73. --*/
  74. #include <stdio.h>
  75. #include <stdlib.h>
  76. #include <string.h>
  77. #include <memory.h>
  78. #include <conio.h>
  79. #include <signal.h>
  80. #undef tolower
  81. #include <windows.h>
  82. #include <dlcapi.h>
  83. #include "dlcdebug.h"
  84. #ifndef _CRTAPI1
  85. #define _CRTAPI1
  86. #endif
  87. #define SIMPLEX_VERSION "1.11"
  88. #define RECEIVE_MODE    0
  89. #define TRANSMIT_MODE   1
  90. #define DLCBUFSIZE  20000
  91. #define SAP_NUMBER  4
  92. #define RECEIVE_COMPLETE_FLAG   0x50204030
  93. #define RECEIVE_DATA_FLAG       0x50204040
  94. #define TRANSMIT_COMPLETE_FLAG  0x50404030
  95. #define TX_STATE_OPENING    1
  96. #define TX_STATE_OPENED     2
  97. #define TX_STATE_TRANSMITTING   3
  98. #define TX_STATE_BUSY       4
  99. #define RX_STATE_LISTENING  1
  100. #define RX_STATE_RECEIVING  2
  101. #define RX_STATE_BLOCKED    3
  102. #define MAX_OUTSTANDING_TRANSMIT_THRESHOLD  100
  103. #define MIN_OUTSTANDING_TRANSMIT_THRESHOLD  10
  104. #define IS_ARG(c)   (((c) == '-') || ((c) == '/'))
  105. #define ZAP(thing)  memset(&thing, 0, sizeof(thing))
  106. #define MALLOC      my_malloc
  107. #define CALLOC      my_calloc
  108. #define FREE        my_free
  109. typedef struct {
  110.     DWORD sequence;
  111.     DWORD size;
  112.     DWORD signature;
  113.     DWORD checksum;
  114.     char data[];
  115. } TEST_PACKET, *PTEST_PACKET;
  116. void _CRTAPI1 main(int, char**);
  117. void usage(void);
  118. DWORD get_funky_number(char**);
  119. BOOL is_radical_digit(char, DWORD);
  120. DWORD char_to_number(char);
  121. void _CRTAPI1 handle_ctrl_c(int);
  122. void terminate(int);
  123. unsigned char xtou(char);
  124. void open_adapter(void);
  125. unsigned short adapter_status(void);
  126. void close_adapter(void);
  127. void create_buffer(int);
  128. void open_sap(int);
  129. void open_station(void);
  130. void connect_station(unsigned short);
  131. void flow_control(int);
  132. PLLC_BUFFER get_buffer(void);
  133. int free_buffer(PLLC_BUFFER);
  134. void post_receive(void);
  135. PLLC_CCB post_read(void);
  136. void tx_i_frame(void);
  137. DWORD slush(char*, int);
  138. void do_transmit(void);
  139. void do_receive(void);
  140. void check_keyboard(void);
  141. void dispatch_read_events(PLLC_CCB);
  142. void handle_status_change(PLLC_CCB);
  143. void handle_receive_data(PLLC_CCB);
  144. void handle_transmit_complete(PLLC_CCB);
  145. void handle_command_complete(PLLC_CCB);
  146. void twiddle_bits(LPBYTE, DWORD);
  147. unsigned char swap_bits(unsigned char);
  148. void* my_malloc(int);
  149. void* my_calloc(int, int);
  150. void my_free(void*);
  151. char* nice_num(unsigned long);
  152. BYTE Adapter = 0;
  153. DWORD BufferPoolSize = DLCBUFSIZE;
  154. BYTE RemoteNode[6];
  155. WORD LocalSap = SAP_NUMBER;
  156. WORD RemoteSap = SAP_NUMBER;
  157. DWORD Mode = RECEIVE_MODE;
  158. BOOL SwapAddressBits = 0;
  159. HANDLE TheMainEvent;
  160. DWORD MaxFrameSize;
  161. DWORD TransmitDataLength = 0;
  162. LPBYTE BufferPool;
  163. HANDLE BufferHandle;
  164. USHORT StationId;
  165. DWORD RxState = 0;
  166. DWORD TxState = 0;
  167. DWORD LocalBusy = 0;
  168. DWORD RemoteBusy = 0;
  169. DWORD Verbose = 0;
  170. DWORD JustBufferInfo = 0;
  171. LONG AllocatedBytesOutstanding = 0;
  172. DWORD TotalBytesAllocated = 0;
  173. DWORD TotalBytesFreed = 0;
  174. LONG OutstandingTransmits = 0;
  175. DWORD DisplayBufferFreeInfo = 1;
  176. DWORD DisplayFrameReceivedInfo = 1;
  177. DWORD DisplayTransmitInfo = 0;
  178. DWORD DisplayCcb = 1;
  179. DWORD TotalTransmits = 0;
  180. DWORD TotalTransmitCompletions = 0;
  181. DWORD TransmitCompleteEvents = 0;
  182. DWORD CommandCompleteEvents = 0;
  183. DWORD StatusChangeEvents = 0;
  184. DWORD ReceiveDataEvents = 0;
  185. DWORD DataFramesReceived = 0;
  186. DWORD DlcBuffersReceived = 0;
  187. DWORD DlcBuffersFreed = 0;
  188. DWORD TotalBytesTransmitted = 0;
  189. DWORD TotalTxBytesCompleted = 0;
  190. DWORD TotalPacketBytesReceived = 0;
  191. DWORD TotalDlcBytesReceived = 0;
  192. DWORD TotalReadsChecked = 0;
  193. DWORD TotalReadEvents = 0;
  194. DWORD MaxChainedReceives = 0;
  195. DWORD MaxChainedTransmits = 0;
  196. DWORD MinBuffersAvailable = 0;
  197. DWORD MaxBuffersAvailable = 0;
  198. DWORD LinkLostEvents = 0;
  199. DWORD DiscEvents = 0;
  200. DWORD FrmrReceivedEvents = 0;
  201. DWORD FrmrSentEvents = 0;
  202. DWORD SabmeResetEvents = 0;
  203. DWORD SabmeOpenEvents = 0;
  204. DWORD RemoteBusyEnteredEvents = 0;
  205. DWORD RemoteBusyLeftEvents = 0;
  206. DWORD TiExpiredEvents = 0;
  207. DWORD DlcCounterOverflowEvents = 0;
  208. DWORD AccessPriorityLoweredEvents = 0;
  209. DWORD InvalidStatusChangeEvents = 0;
  210. DWORD LocalBusyEvents = 0;
  211. BYTE OptionChainReceiveData = 1;
  212. BYTE OptionChainTransmits = 0;
  213. // The application ID is used on Windows 95, but not on Windows NT.
  214. BYTE bApplId = 0;
  215. void _CRTAPI1 main(int argc, char** argv) {
  216.     printf("nDLC simplex test. Version " SIMPLEX_VERSION " " __DATE__ " " __TIME__ "nn");
  217.     for (--argc, ++argv; argc; --argc, ++argv) {
  218.         if (IS_ARG(**argv)) {
  219.             switch (tolower(*++*argv)) {
  220.             case 'a':
  221.                 Adapter = atoi(++*argv);
  222.                 break;
  223.             case 'b':
  224.                 ++*argv;
  225.                 BufferPoolSize = get_funky_number(argv);
  226.                 break;
  227.             case 'h':
  228.             case '?':
  229.                 usage();
  230.             case 'o':
  231.                 ++*argv;
  232.                 while (**argv) {
  233.                     switch (tolower(**argv)) {
  234.                     case 'r':
  235.                         ++*argv;
  236.                         OptionChainReceiveData = (BYTE)get_funky_number(argv);
  237.                         break;
  238.                     case 't':
  239.                         ++*argv;
  240.                         OptionChainTransmits = (BYTE)get_funky_number(argv);
  241.                         break;
  242.                     default:
  243.                         printf("error: unrecognized option '%c'n", **argv);
  244.                         usage();
  245.                     }
  246.                 }
  247.             case 'r':
  248.                 ++*argv;
  249.                 RemoteSap = (WORD)get_funky_number(argv);
  250.                 break;
  251.             case 's':
  252.                 ++*argv;
  253.                 LocalSap = (WORD)get_funky_number(argv);
  254.                 break;
  255.             case 't': {
  256.                 int i;
  257.                 LPSTR p = ++*argv;
  258.                 Mode = TRANSMIT_MODE;
  259.                 if (strlen(p) != 12) {
  260.                     printf("incorrect remote node format (12 hex digits required)n");
  261.                     usage();
  262.                 }
  263.                 for (i = 0; i < 6; ++i) {
  264.                     RemoteNode[i] = (xtou(*p++) << 4) + xtou(*p++);
  265.                 }
  266.                 break;
  267.             }
  268.             case 'v':
  269.                 Verbose = 1;
  270.                 break;
  271.             case 'z':
  272.                 ++*argv;
  273.                 TransmitDataLength = get_funky_number(argv);
  274.                 break;
  275.             }
  276.         }
  277.     }
  278.     if ((TheMainEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL) {
  279.         printf("CreateEvent returns %dn", GetLastError());
  280.         exit(1);
  281.     }
  282.     printf("Running in %s mode.nn",
  283.             (Mode == TRANSMIT_MODE) ? "Transmit" : "Receive"
  284.             );
  285.     if (Mode == TRANSMIT_MODE) {
  286.         printf("remote node = %02x-%02x-%02x-%02x-%02x-%02xn",
  287.             RemoteNode[0] & 0xff,
  288.             RemoteNode[1] & 0xff,
  289.             RemoteNode[2] & 0xff,
  290.             RemoteNode[3] & 0xff,
  291.             RemoteNode[4] & 0xff,
  292.             RemoteNode[5] & 0xff
  293.             );
  294.         DisplayTransmitInfo = 1;
  295.     }
  296.     open_adapter();
  297.     MaxFrameSize = min((1500 - (14 + 4)), MaxFrameSize);
  298.     if (TransmitDataLength && (TransmitDataLength > MaxFrameSize)) {
  299.         TransmitDataLength = MaxFrameSize;
  300.     }
  301.     printf("opened adapter %d. maximum frame size = %dn", Adapter, MaxFrameSize);
  302.     switch (adapter_status()) {
  303.     case 0:
  304.         printf("type of adapter %d is token ring: not flipping hamburgers (nor address bits)n", Adapter);
  305.         SwapAddressBits = 0;
  306.         break;
  307.     case 1:
  308.         printf("type of adapter %d is ethernet: will flip address bitsn", Adapter);
  309.         SwapAddressBits = 1;
  310.         break;
  311.     case 2:
  312.         printf("type of adapter %d is PC/Network card: don't know how to handlen", Adapter);
  313.         terminate(1);
  314.     case 3:
  315.         printf("adapter %d is >> UNKNOWN <<. Will assume FDDI and flip bits.n"
  316.                "If not correct, please fixn", Adapter);
  317.         printf("hit a key to continue... "); getch(); putchar('n');
  318.         break;
  319.     }
  320.     create_buffer(BufferPoolSize);
  321.     MinBuffersAvailable = free_buffer(get_buffer());
  322.     printf("created %d byte buffer pool @%x. Handle = %x. Initial buffers = %dn",
  323.         BufferPoolSize, BufferPool, BufferHandle, MinBuffersAvailable);
  324.     open_sap(LocalSap);
  325.     if (Verbose) {
  326.         printf("opened SAP %d: StationId = %04xn", LocalSap, StationId);
  327.     }
  328.     signal(SIGINT, handle_ctrl_c);
  329.     if (Mode == TRANSMIT_MODE) {
  330.         if (SwapAddressBits) {
  331.             twiddle_bits(RemoteNode, 6);
  332.         }
  333.         do_transmit();
  334.     } else {
  335.         do_receive();
  336.     }
  337.     terminate(0);
  338. }
  339. void usage() {
  340.     printf("usage: simplex [/a#] [/b#] [/h] [/o<option>] [/r#] [/s#] [/t<node>] [/v] [/z#]n"
  341.            "n"
  342.            "       /a = adapter number. Default = 0n"
  343.            "       /b = buffer pool sizen"
  344.            "       /h = this helpn"
  345.            "       /o = options:n"
  346.            "       /or[#] = chain receive datan"
  347.            "           0 = do NOT chainn"
  348.            "           1 = chain on link station basis (DEFAULT)n"
  349.            "           2 = chain on SAP basisn"
  350.            "       /ot[#] = chain transmit completionsn"
  351.            "           0 = chain on link station basis (DEFAULT)n"
  352.            "           1 = do NOT chainn"
  353.            "           2 = chain on SAP basisn"
  354.            "       /r = remote SAP number (transmitter)n"
  355.            "       /s = local SAP number to usen"
  356.            "       /t = transmit moden"
  357.            "       /v = verbosen"
  358.            "       /z = transmit data length. If omitted, packet size is randomn"
  359.            "n"
  360.            "<node> is remote node id in correct form for mediumn"
  361.            "default mode is receivern"
  362.            "The buffer pool minimum threshold is 25%% of the buffer pool sizen"
  363.            "n"
  364.            );
  365.     exit(1);
  366. }
  367. DWORD get_funky_number(char** string) {
  368.     DWORD radix = 10;
  369.     char* p = *string;
  370.     DWORD num = 0, sign=1;
  371.     if (!*p) {
  372.         return 0;
  373.     }
  374.     if (*p=='-') {
  375.         sign = (DWORD)-1;
  376.         p++;
  377.     }
  378.     if (!strnicmp(p, "0x", 2)) {
  379.         p += 2;
  380.         radix = 16;
  381.     }
  382.     while (is_radical_digit(*p, radix)) {
  383.         num = num * radix + char_to_number(*p);
  384.         ++p;
  385.     }
  386.     if (toupper(*p) == 'K') {
  387.         if (radix == 10) {
  388.             ++p;
  389.             num *= 1024;
  390.         } else {
  391.             *string = NULL;
  392.             return 0;
  393.         }
  394.     }
  395.     *string = p;
  396.     return sign * num;
  397. }
  398. BOOL is_radical_digit(char possible_digit, DWORD radix) {
  399.     return (radix == 16) ? isxdigit(possible_digit) : isdigit(possible_digit);
  400. }
  401. DWORD char_to_number(char character) {
  402.     if (isdigit(character)) {
  403.         return (DWORD)(character - '0');
  404.     } else {
  405.         return (DWORD)(toupper(character) - 'A') + 10;
  406.     }
  407. }
  408. void _CRTAPI1 handle_ctrl_c(int sig) {
  409.     char ch;
  410.     printf("an"
  411.            "Interrupted from console (control-c detected)n"
  412.            "Quit program? [Y/N] "
  413.            );
  414.     do {
  415.         ch = tolower(getch());
  416.         if (ch != 'y' && ch != 'n') {
  417.             putchar('a');
  418.         }
  419.     } while ( ch != 'y' && ch != 'n' );
  420.     putchar(ch);
  421.     putchar('n');
  422.     if (ch == 'y') {
  423.         terminate(1);
  424.     }
  425.     signal(SIGINT, handle_ctrl_c);
  426. }
  427. void terminate(int exit_code) {
  428.     close_adapter();
  429.     printf("nterminating %s moden", (Mode == TRANSMIT_MODE) ? "transmit" : "receive");
  430.     printf("n"
  431.            "Memory statistics:n");
  432.     printf("tAllocatedBytesOutstanding    = %sn", nice_num(AllocatedBytesOutstanding));
  433.     printf("tTotalBytesAllocated          = %sn", nice_num(TotalBytesAllocated));
  434.     printf("tTotalBytesFreed              = %sn", nice_num(TotalBytesFreed));
  435.     printf("n"
  436.            "Buffer statistics:n");
  437.     printf("tMinBuffersAvailable          = %sn", nice_num(MinBuffersAvailable));
  438.     printf("tMaxBuffersAvailable          = %sn", nice_num(MaxBuffersAvailable));
  439.     printf("tDlcBuffersFreed              = %sn", nice_num(DlcBuffersFreed));
  440.     printf("n"
  441.            "READ statistics:n");
  442.     printf("tTotalReadsChecked            = %sn", nice_num(TotalReadsChecked));
  443.     printf("tTotalReadEvents              = %sn", nice_num(TotalReadEvents));
  444.     printf("tCommandCompleteEvents        = %sn", nice_num(CommandCompleteEvents));
  445.     printf("tTransmitCompleteEvents       = %sn", nice_num(TransmitCompleteEvents));
  446.     printf("tReceiveDataEvents            = %sn", nice_num(ReceiveDataEvents));
  447.     printf("tStatusChangeEvents           = %sn", nice_num(StatusChangeEvents));
  448.     if (Mode == TRANSMIT_MODE) {
  449.         printf("n"
  450.                "Transmit statistics:n");
  451.         printf("tTotalTransmits               = %sn", nice_num(TotalTransmits));
  452.         printf("tTotalTransmitCompletions     = %sn", nice_num(TotalTransmitCompletions));
  453.         printf("tOutstandingTransmits         = %sn", nice_num(OutstandingTransmits));
  454.         printf("tTotalBytesTransmitted        = %sn", nice_num(TotalBytesTransmitted));
  455.         printf("tTotalTxBytesCompleted        = %sn", nice_num(TotalTxBytesCompleted));
  456.         printf("tMaxChainedTransmits          = %sn", nice_num(MaxChainedTransmits));
  457.     } else {
  458.         printf("n"
  459.                "Receive statistics:n");
  460.         printf("tDataFramesReceived           = %sn", nice_num(DataFramesReceived));
  461.         printf("tDlcBuffersReceived           = %sn", nice_num(DlcBuffersReceived));
  462.         printf("tTotalPacketBytesReceived     = %sn", nice_num(TotalPacketBytesReceived));
  463.         printf("tTotalDlcBytesReceived        = %sn", nice_num(TotalDlcBytesReceived));
  464.         printf("tMaxChainedReceives           = %sn", nice_num(MaxChainedReceives));
  465.     }
  466.     printf("n"
  467.            "Status change statistics:n");
  468.     printf("tLinkLostEvents               = %sn", nice_num(LinkLostEvents));
  469.     printf("tDiscEvents                   = %sn", nice_num(DiscEvents));
  470.     printf("tFrmrReceivedEvents           = %sn", nice_num(FrmrReceivedEvents));
  471.     printf("tFrmrSentEvents               = %sn", nice_num(FrmrSentEvents));
  472.     printf("tSabmeResetEvents             = %sn", nice_num(SabmeResetEvents));
  473.     printf("tSabmeOpenEvents              = %sn", nice_num(SabmeOpenEvents));
  474.     printf("tRemoteBusyEnteredEvents      = %sn", nice_num(RemoteBusyEnteredEvents));
  475.     printf("tRemoteBusyLeftEvents         = %sn", nice_num(RemoteBusyLeftEvents));
  476.     printf("tTiExpiredEvents              = %sn", nice_num(TiExpiredEvents));
  477.     printf("tDlcCounterOverflowEvents     = %sn", nice_num(DlcCounterOverflowEvents));
  478.     printf("tAccessPriorityLoweredEvents  = %sn", nice_num(AccessPriorityLoweredEvents));
  479.     printf("tInvalidStatusChangeEvents    = %sn", nice_num(InvalidStatusChangeEvents));
  480.     printf("tLocalBusyEvents              = %sn", nice_num(LocalBusyEvents));
  481.     exit(exit_code);
  482. }
  483. unsigned char xtou(char ch) {
  484.     return ((ch >= '0') && (ch <= '9'))
  485.         ? (unsigned char)(ch - '0')
  486.         : ((ch >= 'A') && (ch <= 'F'))
  487.             ? (unsigned char)((ch - 'A') + 10)
  488.             : (unsigned char)((ch - 'a') + 10);
  489. }
  490. void open_adapter() {
  491.     LLC_CCB ccb;
  492.     LLC_DIR_OPEN_ADAPTER_PARMS parms;
  493.     LLC_ADAPTER_OPEN_PARMS adapterParms;
  494.     LLC_DLC_PARMS dlcParms;
  495.     LLC_EXTENDED_ADAPTER_PARMS extendedParms;
  496.     LLC_STATUS status;
  497.     ZAP(ccb);
  498.     ZAP(adapterParms);
  499.     ZAP(dlcParms);
  500.     ZAP(extendedParms);
  501.     parms.pAdapterParms = &adapterParms;
  502.     parms.pExtendedParms = &extendedParms;
  503.     parms.pDlcParms = &dlcParms;
  504.     ccb.uchAdapterNumber = Adapter;
  505.     ccb.uchDlcCommand = LLC_DIR_OPEN_ADAPTER;
  506.     ccb.u.pParameterTable = (PLLC_PARMS)&parms;
  507.     ccb.hCompletionEvent = TheMainEvent;
  508.     ResetEvent(TheMainEvent);
  509.     status = AcsLan(&ccb, NULL);
  510.     if (status != ACSLAN_STATUS_COMMAND_ACCEPTED) {
  511.         printf("open_adapter: AcsLan returns %d [%#.2x]n",
  512.             status, ccb.uchDlcStatus);
  513.         puts(MapCcbRetcode(ccb.uchDlcStatus));
  514.         terminate(1);
  515.     }
  516.     status = WaitForSingleObject(TheMainEvent, INFINITE);
  517.     if (status != WAIT_OBJECT_0) {
  518.         printf("open_adapter: WaitForSingleObject returns %d [%d]n",
  519.             status, GetLastError());
  520.         terminate(1);
  521.     }
  522.     if (ccb.uchDlcStatus) {
  523.         printf("open_adapter: DLC returns %#.2xn", ccb.uchDlcStatus);
  524.         puts(MapCcbRetcode(ccb.uchDlcStatus));
  525.         terminate(1);
  526.     }
  527. bApplId = ccb.uchReserved2;
  528.     MaxFrameSize = adapterParms.usMaxFrameSize;
  529. }
  530. unsigned short adapter_status() {
  531.     LLC_CCB ccb;
  532.     LLC_DIR_STATUS_PARMS parms;
  533.     ACSLAN_STATUS status;
  534.     ZAP(ccb);
  535.     ZAP(parms);
  536.     ccb.uchAdapterNumber = Adapter;
  537.     ccb.uchDlcCommand = LLC_DIR_STATUS;
  538.     ccb.u.pParameterTable = (PLLC_PARMS)&parms;
  539.     ccb.hCompletionEvent = TheMainEvent;
  540.     ResetEvent(TheMainEvent);
  541. ccb.uchReserved2 = bApplId;
  542.     status = AcsLan(&ccb, NULL);
  543.     if (status != ACSLAN_STATUS_COMMAND_ACCEPTED) {
  544.         printf("adapter_status: AcsLan returns %d [%#.2x]n",
  545.             status, ccb.uchDlcStatus);
  546.         puts(MapCcbRetcode(ccb.uchDlcStatus));
  547.         terminate(1);
  548.     }
  549.     status = WaitForSingleObject(TheMainEvent, INFINITE);
  550.     if (status != WAIT_OBJECT_0) {
  551.         printf("adapter_status: WaitForSingleObject returns %d [%d]n",
  552.             status, GetLastError());
  553.         terminate(1);
  554.     }
  555.     if (ccb.uchDlcStatus) {
  556.         printf("adapter_status: DLC returns %#.2xn", ccb.uchDlcStatus);
  557.         puts(MapCcbRetcode(ccb.uchDlcStatus));
  558.         terminate(1);
  559.     }
  560.     switch (parms.usAdapterType) {
  561.     case 0x0001:    // Token Ring Network PC Adapter
  562.     case 0x0002:    // Token Ring Network PC Adapter II
  563.     case 0x0004:    // Token Ring Network Adapter/A
  564.     case 0x0008:    // Token Ring Network PC Adapter II
  565.     case 0x0020:    // Token Ring Network 16/4 Adapter
  566.     case 0x0040:    // Token Ring Network 16/4 Adapter/A
  567.     case 0x0080:    // Token Ring Network Adapter/A
  568.         return 0;
  569.     case 0x0100:    // Ethernet Adapter
  570.         return 1;
  571.     case 0x4000:    // PC Network Adapter
  572.     case 0x8000:    // PC Network Adapter/A
  573.         return 2;
  574.     }
  575.     return 3;   // unknown
  576. }
  577. void close_adapter() {
  578.     LLC_CCB ccb;
  579.     ACSLAN_STATUS status;
  580.     ZAP(ccb);
  581.     ccb.uchAdapterNumber = Adapter;
  582.     ccb.uchDlcCommand = LLC_DIR_CLOSE_ADAPTER;
  583.     ccb.hCompletionEvent = TheMainEvent;
  584.     ResetEvent(TheMainEvent);
  585. ccb.uchReserved2 = bApplId;
  586.     status = AcsLan(&ccb, NULL);
  587.     if (status != ACSLAN_STATUS_COMMAND_ACCEPTED) {
  588.         printf("close_adapter: AcsLan returns %d [%#.2x]n",
  589.             status, ccb.uchDlcStatus);
  590.         terminate(1);
  591.     }
  592.     status = WaitForSingleObject(TheMainEvent, INFINITE);
  593.     if (status != WAIT_OBJECT_0) {
  594.         printf("close_adapter: WaitForSingleObject returns %d [%d]n",
  595.             status, GetLastError());
  596.         terminate(1);
  597.     }
  598.     if (ccb.uchDlcStatus) {
  599.         printf("close_adapter: DLC returns %#.2xn", ccb.uchDlcStatus);
  600.         puts(MapCcbRetcode(ccb.uchDlcStatus));
  601.         terminate(1);
  602.     }
  603. }
  604. void create_buffer(int buflen) {
  605.     LLC_CCB ccb;
  606.     LLC_BUFFER_CREATE_PARMS parms;
  607.     LPBYTE buffer;
  608.     LLC_STATUS status;
  609.     ZAP(ccb);
  610.     ZAP(parms);
  611.     buffer = MALLOC(buflen);
  612.     parms.pBuffer = buffer;
  613.     parms.cbBufferSize = buflen;
  614.     parms.cbMinimumSizeThreshold = buflen / 4;
  615.     ccb.uchAdapterNumber = Adapter;
  616.     ccb.uchDlcCommand = LLC_BUFFER_CREATE;
  617.     ccb.u.pParameterTable = (PLLC_PARMS)&parms;
  618.     ccb.hCompletionEvent = TheMainEvent;
  619.     ResetEvent(TheMainEvent);
  620. ccb.uchReserved2 = bApplId;
  621.     status = AcsLan(&ccb, NULL);
  622.     if (status != ACSLAN_STATUS_COMMAND_ACCEPTED || ccb.uchDlcStatus) {
  623.         printf("create_buffer: AcsLan returns %d [%#.2x]n",
  624.             status, ccb.uchDlcStatus);
  625.         puts(MapCcbRetcode(ccb.uchDlcStatus));
  626.         terminate(1);
  627.     }
  628.     status = WaitForSingleObject(TheMainEvent, INFINITE);
  629.     if (status != WAIT_OBJECT_0) {
  630.         printf("create_buffer: WaitForSingleObject returns %d [%d]n",
  631.             status, GetLastError());
  632.         terminate(1);
  633.     }
  634.     if (ccb.uchDlcStatus) {
  635.         printf("create_buffer: DLC returns %#.2xn", ccb.uchDlcStatus);
  636.         puts(MapCcbRetcode(ccb.uchDlcStatus));
  637.         terminate(1);
  638.     }
  639.     BufferHandle = parms.hBufferPool;
  640.     BufferPool = buffer;
  641. }
  642. void open_sap(int sap) {
  643.     LLC_CCB ccb;
  644.     LLC_DLC_OPEN_SAP_PARMS parms;
  645.     LLC_STATUS status;
  646.     ZAP(ccb);
  647.     ZAP(parms);
  648.     ccb.uchAdapterNumber = Adapter;
  649.     ccb.uchDlcCommand = LLC_DLC_OPEN_SAP;
  650.     ccb.u.pParameterTable = (PLLC_PARMS)&parms;
  651.     ccb.hCompletionEvent = TheMainEvent;
  652.     ResetEvent(TheMainEvent);
  653. ccb.uchReserved2 = bApplId;
  654.     parms.uchSapValue = (UCHAR)sap;
  655.     parms.uchOptionsPriority = LLC_INDIVIDUAL_SAP;
  656.     parms.uchcStationCount = 1;
  657. // Set this to non-0 so event will be signalled.
  658. // The ibm specs mandate that.
  659. parms.DlcStatusFlags = 1;  // non-0 to get signalled - johnlee
  660.     status = AcsLan(&ccb, NULL);
  661.     if (status != ACSLAN_STATUS_COMMAND_ACCEPTED || ccb.uchDlcStatus) {
  662.         printf("open_sap: AcsLan returns %d [%#.2x]n",
  663.             status, ccb.uchDlcStatus);
  664.         terminate(1);
  665.     }
  666.     status = WaitForSingleObject(TheMainEvent, INFINITE);
  667.     if (status != WAIT_OBJECT_0) {
  668.         printf("open_sap: WaitForSingleObject returns %d [%d]n",
  669.             status, GetLastError());
  670.         terminate(1);
  671.     }
  672.     if (ccb.uchDlcStatus) {
  673.         printf("open_sap: DLC returns %#.2xn", ccb.uchDlcStatus);
  674.         puts(MapCcbRetcode(ccb.uchDlcStatus));
  675.         terminate(1);
  676.     }
  677.     StationId = parms.usStationId;
  678. }
  679. void open_station() {
  680.     LLC_CCB ccb;
  681.     LLC_DLC_OPEN_STATION_PARMS parms;
  682.     LLC_STATUS status;
  683.     ZAP(ccb);
  684.     ZAP(parms);
  685. // This should not be LocalSap. Read the specs. -- johnlee
  686.     parms.usSapStationId = StationId; //(USHORT)LocalSap << 8;
  687.     parms.uchRemoteSap = (UCHAR)RemoteSap;
  688.     parms.pRemoteNodeAddress = (PVOID)RemoteNode;
  689.     ccb.uchAdapterNumber = Adapter;
  690.     ccb.uchDlcCommand = LLC_DLC_OPEN_STATION;
  691.     ccb.u.pParameterTable = (PLLC_PARMS)&parms;
  692.     ccb.hCompletionEvent = TheMainEvent;
  693.     ResetEvent(TheMainEvent);
  694. ccb.uchReserved2 = bApplId;
  695.     status = AcsLan(&ccb, NULL);
  696.     if (status != ACSLAN_STATUS_COMMAND_ACCEPTED || ccb.uchDlcStatus) {
  697.         printf("open_station: AcsLan returns %d [%#.2x]n",
  698.             status, ccb.uchDlcStatus);
  699.         terminate(1);
  700.     }
  701.     status = WaitForSingleObject(TheMainEvent, INFINITE);
  702.     if (status != WAIT_OBJECT_0) {
  703.         printf("open_station: WaitForSingleObject returns %d [%d]n",
  704.             status, GetLastError());
  705.         terminate(1);
  706.     }
  707.     if (ccb.uchDlcStatus) {
  708.         printf("open_station: DLC returns %#.2xn", ccb.uchDlcStatus);
  709.         puts(MapCcbRetcode(ccb.uchDlcStatus));
  710.         terminate(1);
  711.     }
  712.     StationId = parms.usLinkStationId;
  713. }
  714. void connect_station(unsigned short station) {
  715.     LLC_CCB ccb;
  716.     LLC_DLC_CONNECT_PARMS parms;
  717.     ACSLAN_STATUS status;
  718.     ZAP(ccb);
  719.     ZAP(parms);
  720.     parms.usStationId = station;
  721.     ccb.uchAdapterNumber = Adapter;
  722.     ccb.uchDlcCommand = LLC_DLC_CONNECT_STATION;
  723.     ccb.u.pParameterTable = (PLLC_PARMS)&parms;
  724.     ccb.hCompletionEvent = TheMainEvent;
  725.     ResetEvent(TheMainEvent);
  726. ccb.uchReserved2 = bApplId;
  727.     status = AcsLan(&ccb, NULL);
  728.     if (status != ACSLAN_STATUS_COMMAND_ACCEPTED) {
  729.         printf("connect_station: AcsLan returns %d [%#.2x]n",
  730.             status, ccb.uchDlcStatus);
  731.         terminate(1);
  732.     }
  733.     status = WaitForSingleObject(TheMainEvent, INFINITE);
  734.     if (status != WAIT_OBJECT_0) {
  735.         printf("connect_station: WaitForSingleObject returns %d [%d]n",
  736.             status, GetLastError());
  737.         terminate(1);
  738.     }
  739.     if (ccb.uchDlcStatus) {
  740.         printf("connect_station: DLC returns %#.2xn", ccb.uchDlcStatus);
  741.         puts(MapCcbRetcode(ccb.uchDlcStatus));
  742.         terminate(1);
  743.     }
  744.     if (Verbose) {
  745.         printf("connect_station: OKn");
  746.     }
  747. }
  748. void flow_control(int station) {
  749.     LLC_CCB ccb;
  750.     ACSLAN_STATUS status;
  751.     ZAP(ccb);
  752.     ccb.uchAdapterNumber = Adapter;
  753.     ccb.uchDlcCommand = LLC_DLC_FLOW_CONTROL;
  754.     ccb.u.dlc.usStationId = station;
  755.     ccb.u.dlc.usParameter = 0xc0;
  756.     ccb.hCompletionEvent = TheMainEvent;
  757.     ResetEvent(TheMainEvent);
  758. ccb.uchReserved2 = bApplId;
  759.     if (Verbose) {
  760.         printf("flow_control(%04x, c0)n", station);
  761.     }
  762.     status = AcsLan(&ccb, NULL);
  763.     if (status != ACSLAN_STATUS_COMMAND_ACCEPTED) {
  764.         printf("flow_control: AcsLan returns %d [%#.2x]n",
  765.             status, ccb.uchDlcStatus);
  766.         terminate(1);
  767.     }
  768.     status = WaitForSingleObject(TheMainEvent, INFINITE);
  769.     if (status != WAIT_OBJECT_0) {
  770.         printf("flow_control: WaitForSingleObject returns %d [%d]n",
  771.             status, GetLastError());
  772.         terminate(1);
  773.     }
  774.     if (ccb.uchDlcStatus) {
  775.         printf("flow_control: DLC returns %#.2xn", ccb.uchDlcStatus);
  776.         puts(MapCcbRetcode(ccb.uchDlcStatus));
  777.         terminate(1);
  778.     }
  779.     if (Verbose) {
  780.         printf("flow_control: OKn");
  781.     }
  782.     LocalBusy = 0;
  783. }
  784. PLLC_BUFFER get_buffer() {
  785.     LLC_CCB ccb;
  786.     LLC_BUFFER_GET_PARMS parms;
  787.     ACSLAN_STATUS status;
  788.     ZAP(ccb);
  789.     ZAP(parms);
  790.     parms.cBuffersToGet = 1;
  791.     parms.cbBufferSize = 256;
  792.     ccb.uchAdapterNumber = Adapter;
  793.     ccb.uchDlcCommand = LLC_BUFFER_GET;
  794.     ccb.u.pParameterTable = (PLLC_PARMS)&parms;
  795.     ccb.hCompletionEvent = TheMainEvent;
  796.     ResetEvent(TheMainEvent);
  797. ccb.uchReserved2 = bApplId;
  798.     status = AcsLan(&ccb, NULL);
  799.     if (status != ACSLAN_STATUS_COMMAND_ACCEPTED) {
  800.         printf("get_buffer(): AcsLan returns %d [%#.2x]n", status, ccb.uchDlcStatus);
  801.         //terminate(1);
  802.         return NULL;
  803.     }
  804.     if (WaitForSingleObject(TheMainEvent, INFINITE) != WAIT_OBJECT_0) {
  805.         printf("get_buffer: WaitForSingleObject returns %dn", GetLastError());
  806.         terminate(1);
  807.     }
  808.     if (ccb.uchDlcStatus) {
  809.         printf("get_buffer: DLC returns %#.2xn", ccb.uchDlcStatus);
  810.         puts(MapCcbRetcode(ccb.uchDlcStatus));
  811.         terminate(1);
  812.     }
  813.     if (parms.cBuffersLeft < MinBuffersAvailable) {
  814.         MinBuffersAvailable = parms.cBuffersLeft;
  815.     }
  816.     if (parms.cBuffersLeft > MaxBuffersAvailable) {
  817.         MaxBuffersAvailable = parms.cBuffersLeft;
  818.     }
  819.     return (PLLC_BUFFER)parms.pFirstBuffer;
  820. }
  821. int free_buffer(PLLC_BUFFER buffer) {
  822.     LLC_CCB ccb;
  823.     LLC_BUFFER_FREE_PARMS parms;
  824.     ACSLAN_STATUS status;
  825.     if (!buffer) {
  826.         //
  827.         // microhackette in case get_buffer failed
  828.         //
  829.         return 0;
  830.     }
  831.     ZAP(ccb);
  832.     ZAP(parms);
  833.     parms.pFirstBuffer = (PLLC_XMIT_BUFFER)buffer;
  834.     ccb.uchAdapterNumber = Adapter;
  835.     ccb.uchDlcCommand = LLC_BUFFER_FREE;
  836.     ccb.u.pParameterTable = (PLLC_PARMS)&parms;
  837.     ccb.hCompletionEvent = TheMainEvent;
  838.     ResetEvent(TheMainEvent);
  839. ccb.uchReserved2 = bApplId;
  840.     status = AcsLan(&ccb, NULL);
  841.     if (status != ACSLAN_STATUS_COMMAND_ACCEPTED) {
  842.         printf("free_buffer(%x): AcsLan returns %d [%#.2x]n", buffer, status, ccb.uchDlcStatus);
  843.         terminate(1);
  844.     }
  845.     if (WaitForSingleObject(TheMainEvent, INFINITE) != WAIT_OBJECT_0) {
  846.         printf("free_buffer: WaitForSingleObject returns %dn", GetLastError());
  847.         terminate(1);
  848.     }
  849.     if (ccb.uchDlcStatus) {
  850.         printf("free_buffer(%#x): DLC returns %#.2xn", buffer, ccb.uchDlcStatus);
  851.         puts(MapCcbRetcode(ccb.uchDlcStatus));
  852.         terminate(1);
  853.     }
  854.     if (DisplayBufferFreeInfo) {
  855.         printf("free_buffer(%x): %u buffers leftn", buffer, parms.cBuffersLeft);
  856.     }
  857.     if (parms.cBuffersLeft < MinBuffersAvailable) {
  858.         MinBuffersAvailable = parms.cBuffersLeft;
  859.     }
  860.     if (parms.cBuffersLeft > MaxBuffersAvailable) {
  861.         MaxBuffersAvailable = parms.cBuffersLeft;
  862.     }
  863.     return parms.cBuffersLeft;
  864. }
  865. void post_receive() {
  866.     PLLC_CCB pccb;
  867.     PLLC_RECEIVE_PARMS pparms;
  868.     ACSLAN_STATUS status;
  869.     pccb = CALLOC(1, sizeof(*pccb));
  870.     pparms = CALLOC(1, sizeof(*pparms));
  871.     pparms->usStationId = StationId;
  872.     pparms->ulReceiveFlag = RECEIVE_DATA_FLAG;
  873.     pparms->uchRcvReadOption = OptionChainReceiveData;
  874.     pccb->uchAdapterNumber = Adapter;
  875.     pccb->uchDlcCommand = LLC_RECEIVE;
  876.     pccb->ulCompletionFlag = RECEIVE_COMPLETE_FLAG;
  877.     pccb->u.pParameterTable = (PLLC_PARMS)pparms;
  878. pccb->uchReserved2 = bApplId;
  879.     status = AcsLan(pccb, NULL);
  880.     if (status != ACSLAN_STATUS_COMMAND_ACCEPTED) {
  881.         printf("post_receive: AcsLan returns %d [%#.2x]n", status, pccb->uchDlcStatus);
  882.         terminate(1);
  883.     }
  884.     if (pccb->uchDlcStatus != 0xFF) {
  885.         printf("post_receive: CCB.RETCODE = %#.2xn", pccb->uchDlcStatus);
  886.         puts(MapCcbRetcode(pccb->uchDlcStatus));
  887.         terminate(1);
  888.     }
  889.     if (Verbose) {
  890.         printf("receive posted on station %04xn", StationId);
  891.     }
  892. }
  893. PLLC_CCB post_read() {
  894.     PLLC_CCB pccb;
  895.     PLLC_READ_PARMS pparms;
  896.     ACSLAN_STATUS status;
  897.     pccb = CALLOC(1, sizeof(*pccb));
  898.     pparms = CALLOC(1, sizeof(*pparms));
  899.     pparms->usStationId = StationId;
  900.     pparms->uchOptionIndicator = 2; // retrieve ALL events for this app
  901.     pparms->uchEventSet = 0x7f;     // interested in ALL possible events
  902.    
  903.  pccb->uchAdapterNumber = Adapter;
  904.     pccb->uchDlcCommand = LLC_READ;
  905.     pccb->u.pParameterTable = (PLLC_PARMS)pparms;
  906.     pccb->hCompletionEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  907.     if (!pccb->hCompletionEvent) {
  908.         printf("post_read: CreateEvent returns %dn", GetLastError());
  909.         terminate(1);
  910.     }
  911. pccb->uchReserved2 = bApplId;
  912.     status = AcsLan(pccb, NULL);
  913.     if (status != ACSLAN_STATUS_COMMAND_ACCEPTED) {
  914.         printf("post_read: AcsLan returns %d [%#.2x]n", status, pccb->uchDlcStatus);
  915.         terminate(1);
  916.     }
  917.     return pccb;
  918. }
  919. void tx_i_frame() {
  920.     PLLC_CCB pccb;
  921.     PLLC_TRANSMIT_PARMS pparms;
  922.     ACSLAN_STATUS status;
  923.     int data_size;
  924.     PTEST_PACKET packet;
  925.     static DWORD PacketSequenceNumber = 0;
  926.     pccb = CALLOC(1, sizeof(*pccb));
  927.     pparms = CALLOC(1, sizeof(*pparms));
  928.     data_size = TransmitDataLength
  929.               ? TransmitDataLength
  930.               : (rand() * 600) / RAND_MAX;
  931.   // since this app does not specify max i-frame
  932.   // 600 will be used by windows dlc32 as specified by
  933.   // the ibm dlc specs -- johnlee
  934.               //: (rand() * MaxFrameSize) / RAND_MAX;
  935.     data_size = max(data_size, sizeof(TEST_PACKET));
  936.     packet = (PTEST_PACKET)MALLOC(data_size);
  937.     packet->sequence = PacketSequenceNumber++;
  938.     packet->size = data_size;
  939.     packet->signature = 0x11191962;
  940.     packet->checksum = slush(packet->data, data_size - sizeof(TEST_PACKET));
  941.     pparms->usStationId = StationId;
  942.     pparms->cbBuffer1 = data_size;
  943.     pparms->pBuffer1 = packet;
  944.     pparms->uchXmitReadOption = OptionChainTransmits;
  945.     pccb->uchAdapterNumber = Adapter;
  946.     pccb->uchDlcCommand = LLC_TRANSMIT_I_FRAME;
  947.     pccb->ulCompletionFlag = TRANSMIT_COMPLETE_FLAG;
  948.     pccb->u.pParameterTable = (PLLC_PARMS)pparms;
  949. pccb->uchReserved2 = bApplId;
  950.     status = AcsLan(pccb, NULL);
  951.     //
  952.     // this may fail with 0x69 (or maybe 0xa1) if the system is out of MDL
  953.     // resources. This can happen if we have a lot of completed transmits
  954.     // waiting to be deallocated. In this case just deallocate resources and
  955.     // return - do_transmit should spin removing completed transmits until we
  956.     // can continue
  957.     //
  958.     if (status != ACSLAN_STATUS_COMMAND_ACCEPTED) {
  959.         printf("tx_i_frame: AcsLan returns %d [%#.2x]n",
  960.                status,
  961.                pccb->uchDlcStatus
  962.                );
  963.         puts(MapCcbRetcode(pccb->uchDlcStatus));
  964.         printf("AllocatedBytesOutstanding = %s [%#x]n",
  965.                 nice_num(AllocatedBytesOutstanding),
  966.                 AllocatedBytesOutstanding
  967.                 );
  968.         printf("TotalBytesAllocated       = %s [%#x]n",
  969.                 nice_num(TotalBytesAllocated)
  970.                 , TotalBytesAllocated
  971.                 );
  972.         printf("OutstandingTransmits      = %sn",
  973.                 nice_num(OutstandingTransmits)
  974.                 );
  975.         printf("TotalTransmits            = %sn",
  976.                 nice_num(TotalTransmits)
  977.                 );
  978.         printf("TotalTransmitCompletions  = %sn",
  979.                 nice_num(TotalTransmitCompletions)
  980.                 );
  981.         printf("TransmitCompleteEvents    = %sn",
  982.                 nice_num(TransmitCompleteEvents)
  983.                 );
  984.         if (DisplayCcb) {
  985.             DUMPCCB(pccb, TRUE, FALSE);
  986.         }
  987.         FREE(packet);
  988.         FREE(pparms);
  989.         FREE(pccb);
  990.         --PacketSequenceNumber; // didn't tx this sequence #
  991.     } else {
  992.         if (Verbose) {
  993.             printf("tx_i_frame: transmitted %4d bytesn", data_size);
  994.         }
  995.         ++OutstandingTransmits;
  996.         ++TotalTransmits;
  997.         TotalBytesTransmitted += (DWORD)data_size;
  998.     }
  999. }
  1000. DWORD slush(char* buffer, int length) {
  1001.     DWORD cs = 0;
  1002.     unsigned char ch;
  1003.     while (length--) {
  1004.         ch = (unsigned char)(rand() & 0xff);
  1005.         *buffer++ = ch;
  1006.         cs += (DWORD)ch;
  1007.     }
  1008.     return cs;
  1009. }
  1010. void do_transmit() {
  1011.     PLLC_CCB read_ccb;
  1012.     BOOL need_read = TRUE;
  1013.     BOOL wait_min = FALSE;
  1014.     TxState = TX_STATE_OPENING;
  1015.     open_station();
  1016.     if (Verbose) {
  1017.         printf("opened link station. StationId = %04xn", StationId);
  1018.     }
  1019.     connect_station(StationId);
  1020.     TxState = TX_STATE_OPENED;
  1021.     if (Verbose) {
  1022.         printf("connected to remoten");
  1023.     }
  1024.     while (1) {
  1025.         if (need_read) {
  1026.             read_ccb = post_read();
  1027.             need_read = FALSE;
  1028.         }
  1029.         if (WaitForSingleObject(read_ccb->hCompletionEvent, 0) == WAIT_OBJECT_0) {
  1030.             dispatch_read_events(read_ccb);
  1031.             need_read = TRUE;
  1032.         }
  1033.         if (wait_min) {
  1034.             if (OutstandingTransmits <= MIN_OUTSTANDING_TRANSMIT_THRESHOLD) {
  1035.                 wait_min = FALSE;
  1036.             }
  1037.         } else if (OutstandingTransmits > MAX_OUTSTANDING_TRANSMIT_THRESHOLD) {
  1038.             if (Verbose) {
  1039.                 printf("do_transmit: not transmitting: outstanding transmits (%d) > threshold (%d)n",
  1040.                     OutstandingTransmits, MAX_OUTSTANDING_TRANSMIT_THRESHOLD);
  1041.             }
  1042.             wait_min = TRUE;
  1043.         } else if (RemoteBusy) {
  1044.             if (Verbose) {
  1045.                 printf("do_transmit: not transmitting: remote busyn");
  1046.             }
  1047.             Sleep(100);
  1048.         } else {
  1049.             tx_i_frame();
  1050.         }
  1051.         check_keyboard();
  1052.     }
  1053. }
  1054. void do_receive() {
  1055.     PLLC_CCB read_ccb;
  1056.     DWORD waitStatus;
  1057.     post_receive();
  1058.     RxState = RX_STATE_LISTENING;
  1059.     while (1) {
  1060.         read_ccb = post_read();
  1061.         waitStatus = WaitForSingleObject(read_ccb->hCompletionEvent, INFINITE);
  1062.         if (waitStatus != WAIT_OBJECT_0) {
  1063.             printf("do_receive: WaitForSingleObject returns %d??n", GetLastError());
  1064.             continue;
  1065.         }
  1066.         dispatch_read_events(read_ccb);
  1067.         check_keyboard();
  1068.     }
  1069. }
  1070. void check_keyboard() {
  1071.     if (kbhit()) {
  1072.         switch (tolower(getch())) {
  1073.         case 'b':   // just the facts ma'am
  1074.             JustBufferInfo = !JustBufferInfo;
  1075.             if (JustBufferInfo) {
  1076.                 Verbose = 0;
  1077.             }
  1078.             break;
  1079.         case 'd':
  1080.             DisplayCcb = !DisplayCcb;
  1081.             break;
  1082.         case 'f':
  1083.             DisplayFrameReceivedInfo = !DisplayFrameReceivedInfo;
  1084.             break;
  1085.         case 'i':
  1086.             DisplayBufferFreeInfo = !DisplayBufferFreeInfo;
  1087.             break;
  1088.         case 's':   // Stop & Go
  1089.             while (tolower(getch()) != 'g') {
  1090.                 putchar('a');
  1091.             }
  1092.             break;
  1093.         case 't':
  1094.             DisplayTransmitInfo = !DisplayTransmitInfo;
  1095.             break;
  1096.         case 'v':   // toggle Verbose
  1097.             Verbose = !Verbose;
  1098.             break;
  1099.         case 'x':   // eXit
  1100.             terminate(0);
  1101.         default:
  1102.             putchar('a');
  1103.         }
  1104.     }
  1105. }
  1106. void dispatch_read_events(PLLC_CCB read_ccb) {
  1107.     BYTE event;
  1108.     BYTE comb;
  1109.     ++TotalReadsChecked;
  1110.     if (read_ccb->uchDlcStatus == LLC_STATUS_SUCCESS) {
  1111.         event = ((PLLC_READ_PARMS)read_ccb->u.pParameterTable)->uchEvent;
  1112.         if (Verbose) {
  1113.             printf("dispatch_read_events: event %02x occurred: ", event);
  1114.         }
  1115.         for (comb = 0x80; comb; comb >>= 1) {
  1116.             if (event & comb) {
  1117.                 ++TotalReadEvents;
  1118.             }
  1119.             switch (event & comb) {
  1120.             case 0x80:
  1121.                 if (Verbose) {
  1122.                     printf("RESERVED - shouldn't happen??!!n");
  1123.                 }
  1124.                 break;
  1125.             case 0x40:
  1126.                 if (Verbose) {
  1127.                     printf("SYSTEM ACTION (non-critical)?n");
  1128.                 }
  1129.                 break;
  1130.             case 0x20:
  1131.                 if (Verbose) {
  1132.                     printf("NETWORK STATUS (non-critical)?n");
  1133.                 }
  1134.                 break;
  1135.             case 0x10:
  1136.                 if (Verbose) {
  1137.                     printf("CRITICAL EXCEPTION?n");
  1138.                 }
  1139.                 break;
  1140.             case 0x08:
  1141.                 if (Verbose) {
  1142.                     printf("DLC STATUS CHANGEn");
  1143.                 }
  1144.                 handle_status_change(read_ccb);
  1145.                 break;
  1146.             case 0x04:
  1147.                 if (Verbose) {
  1148.                     printf("RECEIVED DATAn");
  1149.                 }
  1150.                 handle_receive_data(read_ccb);
  1151.                 break;
  1152.             case 0x02:
  1153.                 if (Verbose) {
  1154.                     printf("TRANSMIT COMPLETIONn");
  1155.                 }
  1156.                 handle_transmit_complete(read_ccb);
  1157.                 break;
  1158.             case 0x01:
  1159.                 if (Verbose) {
  1160.                     printf("COMMAND COMPLETIONn");
  1161.                 }
  1162.                 handle_command_complete(read_ccb);
  1163.                 break;
  1164.             }
  1165.         }
  1166.     } else {
  1167.         printf("dispatch_read_events: read error %#.2xn", read_ccb->uchDlcStatus);
  1168.     }
  1169.     FREE(read_ccb->u.pParameterTable);
  1170.     CloseHandle(read_ccb->hCompletionEvent);
  1171.     FREE(read_ccb);
  1172. }
  1173. void handle_status_change(PLLC_CCB read_ccb) {
  1174.     PLLC_READ_PARMS parms = (PLLC_READ_PARMS)read_ccb->u.pParameterTable;
  1175.     USHORT status = parms->Type.Status.usDlcStatusCode;
  1176.     USHORT comb;
  1177.     BOOL lost_it = FALSE;
  1178.     for (comb = 0x8000; comb; comb >>= 1) {
  1179.         if (status & comb) {
  1180.             ++StatusChangeEvents;
  1181.         }
  1182.         switch (status & comb) {
  1183.         case 0x8000:
  1184.             printf("LINK LOSTn");
  1185.             lost_it = TRUE;
  1186.             ++LinkLostEvents;
  1187.             break;
  1188.         case 0x4000:
  1189.             printf("DM/DISC received or DISC ackedn");
  1190.             lost_it = TRUE;
  1191.             ++DiscEvents;
  1192.             break;
  1193.         case 0x2000:
  1194.             printf("FRMR receivedn");
  1195.             lost_it = TRUE;
  1196.             ++FrmrReceivedEvents;
  1197.             break;
  1198.         case 0x1000:
  1199.             printf("FRMR sentn");
  1200.             ++FrmrSentEvents;
  1201.             break;
  1202.         case 0x0800:
  1203.             printf("SABME received on open LINK stationn");
  1204.             ++SabmeResetEvents;
  1205.             break;
  1206.         case 0x0400:
  1207.             memcpy(RemoteNode, parms->Type.Status.uchRemoteNodeAddress, 6);
  1208.             if (SwapAddressBits) {
  1209.                 twiddle_bits(RemoteNode, 6);
  1210.             }
  1211.             printf("SABME received - new link %04x. RemoteNode = %02x-%02x-%02x-%02x-%02x-%02xn",
  1212.                     parms->Type.Status.usStationId,
  1213.                     RemoteNode[0] & 0xff,
  1214.                     RemoteNode[1] & 0xff,
  1215.                     RemoteNode[2] & 0xff,
  1216.                     RemoteNode[3] & 0xff,
  1217.                     RemoteNode[4] & 0xff,
  1218.                     RemoteNode[5] & 0xff
  1219.                     );
  1220.             if (Mode == RECEIVE_MODE) {
  1221.                 connect_station(parms->Type.Status.usStationId);
  1222.                 RxState = RX_STATE_RECEIVING;
  1223.             } else {
  1224.                 printf(" - ON TRANSMITTING SIDE????n");
  1225.             }
  1226.             ++SabmeOpenEvents;
  1227.             break;
  1228.         case 0x0200:
  1229.             printf("REMOTE BUSYn");
  1230.             RemoteBusy = 1;
  1231.             ++RemoteBusyEnteredEvents;
  1232.             break;
  1233.         case 0x0100:
  1234.             printf("REMOTE BUSY CLEAREDn");
  1235.             RemoteBusy = 0;
  1236.             ++RemoteBusyLeftEvents;
  1237.             break;
  1238.         case 0x0080:
  1239.             printf("Ti EXPIREDn");
  1240.             ++TiExpiredEvents;
  1241.             break;
  1242.         case 0x0040:
  1243.             printf("DLC counter overflown");
  1244.             ++DlcCounterOverflowEvents;
  1245.             break;
  1246.         case 0x0020:
  1247.             printf("Access priority lowered (on ethernet????!)n");
  1248.             ++AccessPriorityLoweredEvents;
  1249.             break;
  1250.         case 0x0010:
  1251.         case 0x0008:
  1252.         case 0x0004:
  1253.         case 0x0002:
  1254.             printf("aThis status code (%04x) should be reserved!n", status & comb);
  1255.             ++InvalidStatusChangeEvents;
  1256.             break;
  1257.         case 0x0001: {
  1258.             int bufs_avail;
  1259.             LocalBusy = 1;
  1260.             flow_control(parms->Type.Status.usStationId);
  1261.             ++LocalBusyEvents;
  1262.             bufs_avail = free_buffer(get_buffer());
  1263.             printf("LOCAL BUSY: %d buffers leftn", bufs_avail);
  1264.             if (bufs_avail) {
  1265.                 LocalBusy = 0;
  1266.                 printf("LOCAL BUSY CLEAREDn");
  1267.             }
  1268.             break;
  1269.         }
  1270.         }
  1271.     }
  1272.     if (lost_it) {
  1273.         printf("lost it - quittingn");
  1274.         terminate(1);
  1275.     }
  1276. }
  1277. void handle_receive_data(PLLC_CCB read_ccb) {
  1278.     PLLC_READ_PARMS parms = (PLLC_READ_PARMS)read_ccb->u.pParameterTable;
  1279.     DWORD i;
  1280.     PLLC_BUFFER rx_frame;
  1281.     PLLC_BUFFER next_frame;
  1282.     DWORD nframes;
  1283.     DWORD bufs_left;
  1284.     PLLC_BUFFER pbuf;
  1285.     ++ReceiveDataEvents;
  1286.     nframes = parms->Type.Event.usReceivedFrameCount;
  1287.     if (nframes > MaxChainedReceives) {
  1288.         MaxChainedReceives = nframes;
  1289.     }
  1290.     rx_frame = parms->Type.Event.pReceivedFrame;
  1291.     bufs_left = rx_frame->NotContiguous.cBuffersLeft;
  1292.     if (bufs_left < MinBuffersAvailable) {
  1293.         MinBuffersAvailable = bufs_left;
  1294.     }
  1295.     if (bufs_left > MaxBuffersAvailable) {
  1296.         MaxBuffersAvailable = bufs_left;
  1297.     }
  1298.     if (DisplayFrameReceivedInfo) {
  1299.         printf("handle_receive_data: %d frames received, %d buffers leftn",
  1300.             nframes,
  1301.             bufs_left
  1302.             );
  1303.     }
  1304.     for (i = 0; i < nframes; ++i) {
  1305.         ++DataFramesReceived;
  1306.         next_frame = rx_frame->NotContiguous.pNextFrame;
  1307.         if (!JustBufferInfo) {
  1308.             printf("Packet Sequence %08x  # bytes = %4d  %d buffers leftn",
  1309.                 ((PTEST_PACKET)&rx_frame->NotCont.auchData)->sequence,
  1310.                 ((PTEST_PACKET)&rx_frame->NotCont.auchData)->size,
  1311.                 rx_frame->NotContiguous.cBuffersLeft
  1312.                 );
  1313.         }
  1314.         TotalDlcBytesReceived += rx_frame->Next.cbFrame;
  1315.         TotalPacketBytesReceived += ((PTEST_PACKET)&rx_frame->NotCont.auchData)->size;
  1316.         for (pbuf = rx_frame; pbuf; pbuf = pbuf->pNext) {
  1317.             ++DlcBuffersReceived;
  1318.         }
  1319.         free_buffer(rx_frame);
  1320.         ++DlcBuffersFreed;
  1321.         if (!next_frame && i != nframes - 1) {
  1322.             printf("handle_receive_data: unexpected NULL pointer terminates list @ %dn", i);
  1323.             break;
  1324.         }
  1325.         rx_frame = next_frame;
  1326.     }
  1327. }
  1328. void handle_transmit_complete(PLLC_CCB read_ccb) {
  1329.     PLLC_READ_PARMS parms = (PLLC_READ_PARMS)read_ccb->u.pParameterTable;
  1330.     DWORD i;
  1331.     PLLC_CCB tx_ccb;
  1332.     PLLC_CCB next_ccb;
  1333.     DWORD nframes;
  1334.     DWORD txlen;
  1335.     ++TransmitCompleteEvents;
  1336.     nframes = parms->Type.Event.usCcbCount;
  1337.     if (nframes > MaxChainedTransmits) {
  1338.         MaxChainedTransmits = nframes;
  1339.     }
  1340.     if (Verbose || DisplayTransmitInfo) {
  1341.         printf("handle_transmit_complete: %d transmits completedn", nframes);
  1342.     }
  1343.     tx_ccb = parms->Type.Event.pCcbCompletionList;
  1344.     for (i = 0; i < nframes; ++i) {
  1345.         next_ccb = tx_ccb->pNext;
  1346.         txlen = ((PLLC_TRANSMIT_PARMS)tx_ccb->u.pParameterTable)->cbBuffer1;
  1347.         TotalTxBytesCompleted += txlen;
  1348.         if (tx_ccb->uchDlcStatus) {
  1349.             printf("ahandle_transmit_complete: TX CCB %08x error %#.2xn",
  1350.                 tx_ccb, tx_ccb->uchDlcStatus);
  1351.             if (tx_ccb->uchDlcStatus == LLC_STATUS_INVALID_FRAME_LENGTH) {
  1352.                 printf("data length = %dn", txlen);
  1353.             }
  1354.         }
  1355.         FREE(((PLLC_TRANSMIT_PARMS)tx_ccb->u.pParameterTable)->pBuffer1);
  1356.         FREE(tx_ccb->u.pParameterTable);
  1357.         FREE(tx_ccb);
  1358.         --OutstandingTransmits;
  1359.         if (OutstandingTransmits < 0) {
  1360.             printf("handle_transmit_complete: more transmit completions than transmits (%d)n",
  1361.                 OutstandingTransmits);
  1362.         }
  1363.         ++TotalTransmitCompletions;
  1364.         tx_ccb = next_ccb;
  1365.         if (!next_ccb && i != nframes - 1) {
  1366.             printf("handle_transmit_complete: unexpected NULL pointer terminates list @ %dn", i);
  1367.             break;
  1368.         }
  1369.     }
  1370. }
  1371. void handle_command_complete(PLLC_CCB read_ccb) {
  1372.     PLLC_READ_PARMS parms = (PLLC_READ_PARMS)read_ccb->u.pParameterTable;
  1373.     ++CommandCompleteEvents;
  1374.     printf("handle_command_complete: %d CCBs, %d buffers, %d received framesn",
  1375.         parms->Type.Event.usCcbCount,
  1376.         parms->Type.Event.usBufferCount,
  1377.         parms->Type.Event.usReceivedFrameCount
  1378.         );
  1379. }
  1380. void twiddle_bits(LPBYTE buffer, DWORD length) {
  1381.     while (length--) {
  1382.         *buffer = swap_bits(*buffer);
  1383.         ++buffer;
  1384.     }
  1385. }
  1386. unsigned char swap_bits(unsigned char b) {
  1387.     unsigned char bb = 0;
  1388.     unsigned char mask;
  1389.     for (mask = 1; mask; mask <<= 1) {
  1390.         bb <<= 1;
  1391.         bb |= ((b & mask) ? 1 : 0);
  1392.     }
  1393.     return bb;
  1394. }
  1395. void* my_malloc(int size) {
  1396.     void* ptr;
  1397.     size += 2 * sizeof(DWORD);
  1398.     ptr = malloc(size);
  1399.     if (ptr) {
  1400.         *((LPDWORD)ptr)++ = (DWORD)size;
  1401.         *((LPDWORD)ptr)++ = 0xcec171a2;
  1402.         AllocatedBytesOutstanding += (LONG)size;
  1403.         if (AllocatedBytesOutstanding < 0) {
  1404.             printf("my_malloc: alloc overflow? AllocatedBytesOutstanding=%xn", AllocatedBytesOutstanding);
  1405.         }
  1406.         TotalBytesAllocated += (DWORD)size;
  1407.     }
  1408.     return ptr;
  1409. }
  1410. void* my_calloc(int num, int size) {
  1411.     void* ptr;
  1412.     size = (num * size) + 2 * sizeof(DWORD);
  1413.     ptr = calloc(1, size);
  1414.     if (ptr) {
  1415.         *((LPDWORD)ptr)++ = (DWORD)size;
  1416.         *((LPDWORD)ptr)++ = 0xcec171a2;
  1417.         AllocatedBytesOutstanding += (LONG)size;
  1418.         if (AllocatedBytesOutstanding < 0) {
  1419.             printf("my_calloc: alloc overflow? AllocatedBytesOutstanding=%xn", AllocatedBytesOutstanding);
  1420.         }
  1421.         TotalBytesAllocated += (DWORD)size;
  1422.     }
  1423.     return ptr;
  1424. }
  1425. void my_free(void* ptr) {
  1426.     DWORD size;
  1427.     ((LPDWORD)ptr) -= 2;
  1428.     size = ((LPDWORD)ptr)[0];
  1429.     if (((LPDWORD)ptr)[1] != 0xcec171a2) {
  1430.         printf("amy_free: bad block %x?n", ptr);
  1431.     } else {
  1432.         AllocatedBytesOutstanding -= size;
  1433.         if (AllocatedBytesOutstanding < 0) {
  1434.             printf("my_free: free underflow? AllocatedBytesOutstanding=%xn", AllocatedBytesOutstanding);
  1435.         }
  1436.         free(ptr);
  1437.         TotalBytesFreed += (DWORD)size;
  1438.     }
  1439. }
  1440. char* nice_num(unsigned long number) {
  1441.     int fwidth = 0;
  1442.     int i;
  1443.     static char buffer[32];
  1444.     char* buf = buffer;
  1445.     if (!number) {
  1446.         if (!fwidth) {
  1447.             buf[0] = '0';
  1448.             buf[1] = 0;
  1449.         } else {
  1450.             memset(buf, ' ', fwidth);
  1451.             buf[fwidth-1] = '0';
  1452.             buf[fwidth] = 0;
  1453.         }
  1454.     } else {
  1455.         if (!fwidth) {
  1456.             ULONG n = number;
  1457.             ++fwidth;
  1458.             for (i = 10; i <= 1000000000; i *= 10) {
  1459.                 if (n/i) {
  1460.                     ++fwidth;
  1461.                 } else {
  1462.                     break;
  1463.                 }
  1464.             }
  1465.             fwidth += (fwidth / 3) - (((fwidth % 3) == 0) ? 1 : 0);
  1466.         }
  1467.         buf[fwidth] = 0;
  1468.         buf += fwidth;
  1469.         i=0;
  1470.         while (number && fwidth) {
  1471.             *--buf = (char)((number%10)+'0');
  1472.             --fwidth;
  1473.             number /= 10;
  1474.             if (++i == 3 && fwidth) {
  1475.                 if (number) {
  1476.                     *--buf = ',';
  1477.                     --fwidth;
  1478.                     i=0;
  1479.                 }
  1480.             }
  1481.         }
  1482.         while (fwidth--) *--buf = ' ';
  1483.     }
  1484.     return buf;
  1485. }