1b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek/*
277349cb20bfd7069d081f84c91975bfa8ef60a32Ted Kremenek *  File.........: pktdrvr.c
377349cb20bfd7069d081f84c91975bfa8ef60a32Ted Kremenek *
477349cb20bfd7069d081f84c91975bfa8ef60a32Ted Kremenek *  Responsible..: Gisle Vanem,  giva@bgnett.no
577349cb20bfd7069d081f84c91975bfa8ef60a32Ted Kremenek *
677349cb20bfd7069d081f84c91975bfa8ef60a32Ted Kremenek *  Created......: 26.Sept 1995
777349cb20bfd7069d081f84c91975bfa8ef60a32Ted Kremenek *
877349cb20bfd7069d081f84c91975bfa8ef60a32Ted Kremenek *  Description..: Packet-driver interface for 16/32-bit C :
977349cb20bfd7069d081f84c91975bfa8ef60a32Ted Kremenek *                 Borland C/C++ 3.0+ small/large model
10b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek *                 Watcom C/C++ 11+, DOS4GW flat model
1141573ebf8fb971f40fa8a3e20648362c359b4916Ted Kremenek *                 Metaware HighC 3.1+ and PharLap 386|DosX
12b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek *                 GNU C/C++ 2.7+ and djgpp 2.x extender
1377349cb20bfd7069d081f84c91975bfa8ef60a32Ted Kremenek *
1477349cb20bfd7069d081f84c91975bfa8ef60a32Ted Kremenek *  References...: PC/TCP Packet driver Specification. rev 1.09
1577349cb20bfd7069d081f84c91975bfa8ef60a32Ted Kremenek *                 FTP Software Inc.
16d065d6080f0620bb80b933f3f5d52d37bb2ea770Ted Kremenek *
17d065d6080f0620bb80b933f3f5d52d37bb2ea770Ted Kremenek */
18d065d6080f0620bb80b933f3f5d52d37bb2ea770Ted Kremenek
19c77a55126fcad66fb086f8e100a494caa2496a2dZhongxing Xu#include <stdio.h>
201309f9a3b225ea846e5822691c39a77423125505Ted Kremenek#include <stdlib.h>
211309f9a3b225ea846e5822691c39a77423125505Ted Kremenek#include <string.h>
221309f9a3b225ea846e5822691c39a77423125505Ted Kremenek#include <dos.h>
231309f9a3b225ea846e5822691c39a77423125505Ted Kremenek
246b67630d5df195f4fe0e4273061c016901d69681Ted Kremenek#include "pcap-dos.h"
25c0c3f5dbc9e78aa53a86c7d5e3eeda23ddad93d6Ted Kremenek#include "pcap-int.h"
26f494b579b22f9950f5af021f0bf9879a91bb8b41Steve Naroff#include "msdos/pktdrvr.h"
27bb141217871e93767aa3f2de1b9946fa6d37066aZhongxing Xu
284beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek#if (DOSX)
2977349cb20bfd7069d081f84c91975bfa8ef60a32Ted Kremenek#define NUM_RX_BUF  32      /* # of buffers in Rx FIFO queue */
301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump#else
315e2d2c2ee3cf410643e0f9a5701708e51409d973Benjamin Kramer#define NUM_RX_BUF  10
325e2d2c2ee3cf410643e0f9a5701708e51409d973Benjamin Kramer#endif
335e2d2c2ee3cf410643e0f9a5701708e51409d973Benjamin Kramer
34f494b579b22f9950f5af021f0bf9879a91bb8b41Steve Naroff#define DIM(x)   (sizeof((x)) / sizeof(x[0]))
351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump#define PUTS(s)  do {                                           \
3625e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu                   if (!pktInfo.quiet)                          \
3725e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu                      pktInfo.error ?                           \
380111f575b968e423dccae439e501225b8314b257Zhongxing Xu                        printf ("%s: %s\n", s, pktInfo.error) : \
391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                        printf ("%s\n", pktInfo.error = s);     \
40b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek                 } while (0)
41031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xu
421eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump#if defined(__HIGHC__)
43b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek  extern UINT _mwenv;
44b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek
45031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xu#elif defined(__DJGPP__)
461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  #include <stddef.h>
47b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek  #include <dpmi.h>
484adc81e540b874bafa15715fd2c5cb662463debdTed Kremenek  #include <go32.h>
49cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  #include <pc.h>
50b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek  #include <sys/farptr.h>
51b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek
521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump#elif defined(__WATCOMC__)
53846eabd187be4bfe992e8bca131166b734d86e0dTed Kremenek  #include <i86.h>
54846eabd187be4bfe992e8bca131166b734d86e0dTed Kremenek  #include <stddef.h>
551eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  extern char _Extender;
56846d4e923bf11bcdc2816758aafa331795f29230Ted Kremenek
57031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xu#else
58846d4e923bf11bcdc2816758aafa331795f29230Ted Kremenek  extern void far PktReceiver (void);
59846d4e923bf11bcdc2816758aafa331795f29230Ted Kremenek#endif
600d093d3005dd583675a45a85bd688063572cc8afTed Kremenek
611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
621eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump#if (DOSX & (DJGPP|DOS4GW))
63b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek  #include <sys/pack_on.h>
6403509aea098772644bf4662dc1c88634818ceeccZhongxing Xu
651eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  struct DPMI_regs {
66e448ab4f9dd162802f5d7cfea60f7830cc61c654Ted Kremenek         DWORD  r_di;
67e448ab4f9dd162802f5d7cfea60f7830cc61c654Ted Kremenek         DWORD  r_si;
681eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump         DWORD  r_bp;
69e448ab4f9dd162802f5d7cfea60f7830cc61c654Ted Kremenek         DWORD  reserved;
70e448ab4f9dd162802f5d7cfea60f7830cc61c654Ted Kremenek         DWORD  r_bx;
71e448ab4f9dd162802f5d7cfea60f7830cc61c654Ted Kremenek         DWORD  r_dx;
721eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump         DWORD  r_cx;
7372905cfa81cfd126f322c4173f56d332aac5539eJordy Rose         DWORD  r_ax;
7472905cfa81cfd126f322c4173f56d332aac5539eJordy Rose         WORD   r_flags;
7572905cfa81cfd126f322c4173f56d332aac5539eJordy Rose         WORD   r_es, r_ds, r_fs, r_gs;
76c2b7dfaad674587cfd220ff447b3710d252130c3Jordy Rose         WORD   r_ip, r_cs, r_sp, r_ss;
77c2b7dfaad674587cfd220ff447b3710d252130c3Jordy Rose       };
7872905cfa81cfd126f322c4173f56d332aac5539eJordy Rose
7972905cfa81cfd126f322c4173f56d332aac5539eJordy Rose  /* Data located in a real-mode segment. This becomes far at runtime
8072905cfa81cfd126f322c4173f56d332aac5539eJordy Rose   */
8172905cfa81cfd126f322c4173f56d332aac5539eJordy Rose  typedef struct  {          /* must match data/code in pkt_rx1.s */
8272905cfa81cfd126f322c4173f56d332aac5539eJordy Rose          WORD       _rxOutOfs;
8372905cfa81cfd126f322c4173f56d332aac5539eJordy Rose          WORD       _rxInOfs;
8472905cfa81cfd126f322c4173f56d332aac5539eJordy Rose          DWORD      _pktDrop;
8572905cfa81cfd126f322c4173f56d332aac5539eJordy Rose          BYTE       _pktTemp [20];
8672905cfa81cfd126f322c4173f56d332aac5539eJordy Rose          TX_ELEMENT _pktTxBuf[1];
8772905cfa81cfd126f322c4173f56d332aac5539eJordy Rose          RX_ELEMENT _pktRxBuf[NUM_RX_BUF];
8872905cfa81cfd126f322c4173f56d332aac5539eJordy Rose          WORD       _dummy[2];        /* screenSeg,newInOffset */
8972905cfa81cfd126f322c4173f56d332aac5539eJordy Rose          BYTE       _fanChars[4];
90094bef56a7900f13bb777f9a352704104b1458e7Ted Kremenek          WORD       _fanIndex;
91b94b81a9ab46c99b00c7ad28c5e1e212c63fc9acZhongxing Xu          BYTE       _PktReceiver[15]; /* starts on a paragraph (16byte) */
9272905cfa81cfd126f322c4173f56d332aac5539eJordy Rose        } PktRealStub;
939e9595b12e9b55586c4d50d370f429c7a3c92a90Ted Kremenek  #include <sys/pack_off.h>
949e9595b12e9b55586c4d50d370f429c7a3c92a90Ted Kremenek
959e9595b12e9b55586c4d50d370f429c7a3c92a90Ted Kremenek  static BYTE real_stub_array [] = {
969e9595b12e9b55586c4d50d370f429c7a3c92a90Ted Kremenek         #include "pkt_stub.inc"       /* generated opcode array */
979e9595b12e9b55586c4d50d370f429c7a3c92a90Ted Kremenek       };
989e9595b12e9b55586c4d50d370f429c7a3c92a90Ted Kremenek
999e9595b12e9b55586c4d50d370f429c7a3c92a90Ted Kremenek  #define rxOutOfs      offsetof (PktRealStub,_rxOutOfs)
100094bef56a7900f13bb777f9a352704104b1458e7Ted Kremenek  #define rxInOfs       offsetof (PktRealStub,_rxInOfs)
101ff944a8c481d6c0f1ad2633e4be9bf8b1dd2a09fZhongxing Xu  #define PktReceiver   offsetof (PktRealStub,_PktReceiver [para_skip])
1029e9595b12e9b55586c4d50d370f429c7a3c92a90Ted Kremenek  #define pktDrop       offsetof (PktRealStub,_pktDrop)
10372905cfa81cfd126f322c4173f56d332aac5539eJordy Rose  #define pktTemp       offsetof (PktRealStub,_pktTemp)
1049e9595b12e9b55586c4d50d370f429c7a3c92a90Ted Kremenek  #define pktTxBuf      offsetof (PktRealStub,_pktTxBuf)
1059e9595b12e9b55586c4d50d370f429c7a3c92a90Ted Kremenek  #define FIRST_RX_BUF  offsetof (PktRealStub,_pktRxBuf [0])
1069e9595b12e9b55586c4d50d370f429c7a3c92a90Ted Kremenek  #define LAST_RX_BUF   offsetof (PktRealStub,_pktRxBuf [NUM_RX_BUF-1])
1079e9595b12e9b55586c4d50d370f429c7a3c92a90Ted Kremenek
1089e9595b12e9b55586c4d50d370f429c7a3c92a90Ted Kremenek#else
109cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  extern WORD       rxOutOfs;    /* offsets into pktRxBuf FIFO queue   */
11032a58084a4c53e6938dd81bfce224db25a5976d1Ted Kremenek  extern WORD       rxInOfs;
11132a58084a4c53e6938dd81bfce224db25a5976d1Ted Kremenek  extern DWORD      pktDrop;     /* # packets dropped in PktReceiver() */
1121eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  extern BYTE       pktRxEnd;    /* marks the end of r-mode code/data  */
113b22d589e2ccd09cada0bcea136f0966883a8bb11Ted Kremenek
11432a58084a4c53e6938dd81bfce224db25a5976d1Ted Kremenek  extern RX_ELEMENT pktRxBuf [NUM_RX_BUF];       /* PktDrvr Rx buffers */
115cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  extern TX_ELEMENT pktTxBuf;                    /* PktDrvr Tx buffer  */
11650a6d0ce344c02782e0207574005c3b2aaa5077cTed Kremenek  extern char       pktTemp[20];                 /* PktDrvr temp area  */
1171eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
11825e695b2d574d919cc1bbddf3a2efe073d449b1cZhongxing Xu  #define FIRST_RX_BUF (WORD) &pktRxBuf [0]
1192ce43c8f43254a9edea53a20dc0e69195bc82ae0Zhongxing Xu  #define LAST_RX_BUF  (WORD) &pktRxBuf [NUM_RX_BUF-1]
1202ce43c8f43254a9edea53a20dc0e69195bc82ae0Zhongxing Xu#endif
1212ce43c8f43254a9edea53a20dc0e69195bc82ae0Zhongxing Xu
1222ce43c8f43254a9edea53a20dc0e69195bc82ae0Zhongxing Xu
1232ce43c8f43254a9edea53a20dc0e69195bc82ae0Zhongxing Xu#ifdef __BORLANDC__           /* Use Borland's inline functions */
1242ce43c8f43254a9edea53a20dc0e69195bc82ae0Zhongxing Xu  #define memcpy  __memcpy__
1252ce43c8f43254a9edea53a20dc0e69195bc82ae0Zhongxing Xu  #define memcmp  __memcmp__
1262ce43c8f43254a9edea53a20dc0e69195bc82ae0Zhongxing Xu  #define memset  __memset__
1272ce43c8f43254a9edea53a20dc0e69195bc82ae0Zhongxing Xu#endif
1282ce43c8f43254a9edea53a20dc0e69195bc82ae0Zhongxing Xu
129b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek
1301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump#if (DOSX & PHARLAP)
131b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek  extern void PktReceiver (void);     /* in pkt_rx0.asm */
132c77a55126fcad66fb086f8e100a494caa2496a2dZhongxing Xu  static int  RealCopy    (ULONG, ULONG, REALPTR*, FARPTR*, USHORT*);
1335032ffe4259e7d436f2eb19e5a29fdae559e7c12Zhongxing Xu
1342ce43c8f43254a9edea53a20dc0e69195bc82ae0Zhongxing Xu  #undef  FP_SEG
1351eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  #undef  FP_OFF
136846eabd187be4bfe992e8bca131166b734d86e0dTed Kremenek  #define FP_OFF(x)     ((WORD)(x))
1371eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  #define FP_SEG(x)     ((WORD)(realBase >> 16))
13832a58084a4c53e6938dd81bfce224db25a5976d1Ted Kremenek  #define DOS_ADDR(s,o) (((DWORD)(s) << 16) + (WORD)(o))
1391eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  #define r_ax          eax
140cf118d41f7930a18dce97416ef7834a62642f587Ted Kremenek  #define r_bx          ebx
1411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  #define r_dx          edx
142ec9227fea66c3439991fc84b0d33b0a8b4b8875eZhongxing Xu  #define r_cx          ecx
143ec9227fea66c3439991fc84b0d33b0a8b4b8875eZhongxing Xu  #define r_si          esi
14432a58084a4c53e6938dd81bfce224db25a5976d1Ted Kremenek  #define r_di          edi
14532a58084a4c53e6938dd81bfce224db25a5976d1Ted Kremenek  #define r_ds          ds
1461eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  #define r_es          es
147e01c98767dfd7153c3c84637c36659e3bbe16ff7Ted Kremenek  LOCAL FARPTR          protBase;
148e01c98767dfd7153c3c84637c36659e3bbe16ff7Ted Kremenek  LOCAL REALPTR         realBase;
149ffe0f43806d4823271c2406c1fccc2373115c36aTed Kremenek  LOCAL WORD            realSeg;   /* DOS para-address of allocated area */
1501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  LOCAL SWI_REGS        reg;
151031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xu
1521eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  static WORD _far *rxOutOfsFp, *rxInOfsFp;
153b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek
154b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek#elif (DOSX & DJGPP)
15517fd8632dcda97022a51effc24060eacdad9dbe0Zhongxing Xu  static _go32_dpmi_seginfo rm_mem;
1561eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  static __dpmi_regs        reg;
157031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xu  static DWORD              realBase;
158031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xu  static int                para_skip = 0;
15950a6d0ce344c02782e0207574005c3b2aaa5077cTed Kremenek
160ec9227fea66c3439991fc84b0d33b0a8b4b8875eZhongxing Xu  #define DOS_ADDR(s,o)     (((WORD)(s) << 4) + (o))
161094bef56a7900f13bb777f9a352704104b1458e7Ted Kremenek  #define r_ax              x.ax
162094bef56a7900f13bb777f9a352704104b1458e7Ted Kremenek  #define r_bx              x.bx
163094bef56a7900f13bb777f9a352704104b1458e7Ted Kremenek  #define r_dx              x.dx
164094bef56a7900f13bb777f9a352704104b1458e7Ted Kremenek  #define r_cx              x.cx
165094bef56a7900f13bb777f9a352704104b1458e7Ted Kremenek  #define r_si              x.si
166ec9227fea66c3439991fc84b0d33b0a8b4b8875eZhongxing Xu  #define r_di              x.di
167094bef56a7900f13bb777f9a352704104b1458e7Ted Kremenek  #define r_ds              x.ds
168094bef56a7900f13bb777f9a352704104b1458e7Ted Kremenek  #define r_es              x.es
169ec9227fea66c3439991fc84b0d33b0a8b4b8875eZhongxing Xu
170ec9227fea66c3439991fc84b0d33b0a8b4b8875eZhongxing Xu#elif (DOSX & DOS4GW)
171094bef56a7900f13bb777f9a352704104b1458e7Ted Kremenek  LOCAL struct DPMI_regs    reg;
172094bef56a7900f13bb777f9a352704104b1458e7Ted Kremenek  LOCAL WORD                rm_base_seg, rm_base_sel;
1735a5d98bc6962dc2d1aaa5e0e522f1bf84273b9c1Ted Kremenek  LOCAL DWORD               realBase;
1741eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  LOCAL int                 para_skip = 0;
1759c6cd67ea416bace666d614c84d5531124287653Zhongxing Xu
1769c6cd67ea416bace666d614c84d5531124287653Zhongxing Xu  LOCAL DWORD dpmi_get_real_vector (int intr);
1779c6cd67ea416bace666d614c84d5531124287653Zhongxing Xu  LOCAL WORD  dpmi_real_malloc     (int size, WORD *selector);
1789c6cd67ea416bace666d614c84d5531124287653Zhongxing Xu  LOCAL void  dpmi_real_free       (WORD selector);
1799c6cd67ea416bace666d614c84d5531124287653Zhongxing Xu  #define DOS_ADDR(s,o) (((DWORD)(s) << 4) + (WORD)(o))
1809c6cd67ea416bace666d614c84d5531124287653Zhongxing Xu
1819c6cd67ea416bace666d614c84d5531124287653Zhongxing Xu#else              /* real-mode Borland etc. */
1829c6cd67ea416bace666d614c84d5531124287653Zhongxing Xu  static struct  {
1839c6cd67ea416bace666d614c84d5531124287653Zhongxing Xu         WORD r_ax, r_bx, r_cx, r_dx, r_bp;
1841eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump         WORD r_si, r_di, r_ds, r_es, r_flags;
1854ffcb9974c6b7142c4a1483abfcb1f88b6371c45Zhongxing Xu       } reg;
1864ffcb9974c6b7142c4a1483abfcb1f88b6371c45Zhongxing Xu#endif
1874ffcb9974c6b7142c4a1483abfcb1f88b6371c45Zhongxing Xu
1884ffcb9974c6b7142c4a1483abfcb1f88b6371c45Zhongxing Xu#ifdef __HIGHC__
1894ffcb9974c6b7142c4a1483abfcb1f88b6371c45Zhongxing Xu  #pragma Alias (pktDrop,    "_pktDrop")
1904ffcb9974c6b7142c4a1483abfcb1f88b6371c45Zhongxing Xu  #pragma Alias (pktRxBuf,   "_pktRxBuf")
1914ffcb9974c6b7142c4a1483abfcb1f88b6371c45Zhongxing Xu  #pragma Alias (pktTxBuf,   "_pktTxBuf")
1926a6719a3a11087b48d9f1a4eb08b3bd43cb05a65Ted Kremenek  #pragma Alias (pktTemp,    "_pktTemp")
1936a6719a3a11087b48d9f1a4eb08b3bd43cb05a65Ted Kremenek  #pragma Alias (rxOutOfs,   "_rxOutOfs")
1946a6719a3a11087b48d9f1a4eb08b3bd43cb05a65Ted Kremenek  #pragma Alias (rxInOfs,    "_rxInOfs")
19503509aea098772644bf4662dc1c88634818ceeccZhongxing Xu  #pragma Alias (pktRxEnd,   "_pktRxEnd")
1964323a57627e796dcfdfdb7d47672dc09ed308edaTed Kremenek  #pragma Alias (PktReceiver,"_PktReceiver")
1971eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump#endif
198b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek
199b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek
20003509aea098772644bf4662dc1c88634818ceeccZhongxing XuPUBLIC PKT_STAT    pktStat;    /* statistics for packets    */
20103509aea098772644bf4662dc1c88634818ceeccZhongxing XuPUBLIC PKT_INFO    pktInfo;    /* packet-driver information */
2021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
203b387a3f23e423d62c053be86294b703da1d1a222Ted KremenekPUBLIC PKT_RX_MODE receiveMode  = PDRX_DIRECT;
204b387a3f23e423d62c053be86294b703da1d1a222Ted KremenekPUBLIC ETHER       myAddress    = {   0,  0,  0,  0,  0,  0 };
205031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing XuPUBLIC ETHER       ethBroadcast = { 255,255,255,255,255,255 };
2061eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
207b387a3f23e423d62c053be86294b703da1d1a222Ted KremenekLOCAL  struct {             /* internal statistics */
208b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek       DWORD  tooSmall;     /* size < ETH_MIN */
209031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xu       DWORD  tooLarge;     /* size > ETH_MAX */
2101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump       DWORD  badSync;      /* count_1 != count_2 */
21111062b118476368fa5b294954713e5df97d8599fTed Kremenek       DWORD  wrongHandle;  /* upcall to wrong handle */
21211062b118476368fa5b294954713e5df97d8599fTed Kremenek     } intStat;
21373099bfea9f5d4ec05265170bbefec3d76fb6b5eTed Kremenek
214102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor/***************************************************************************/
215ccc263b44c62ce3a02f797a3ddb3d6017cf0e5e4Ted Kremenek
216102acd5369bbb17c0d6ab868af376671acff7a93Douglas GregorPUBLIC const char *PktGetErrorStr (int errNum)
217102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor{
218ccc263b44c62ce3a02f797a3ddb3d6017cf0e5e4Ted Kremenek  static const char *errStr[] = {
219102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor                    "",
220102acd5369bbb17c0d6ab868af376671acff7a93Douglas Gregor                    "Invalid handle number",
221ccc263b44c62ce3a02f797a3ddb3d6017cf0e5e4Ted Kremenek                    "No interfaces of specified class found",
222ccc263b44c62ce3a02f797a3ddb3d6017cf0e5e4Ted Kremenek                    "No interfaces of specified type found",
223ccc263b44c62ce3a02f797a3ddb3d6017cf0e5e4Ted Kremenek                    "No interfaces of specified number found",
2249c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek                    "Bad packet type specified",
22532a58084a4c53e6938dd81bfce224db25a5976d1Ted Kremenek                    "Interface does not support multicast",
22603509aea098772644bf4662dc1c88634818ceeccZhongxing Xu                    "Packet driver cannot terminate",
2271eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump                    "Invalid receiver mode specified",
228c2b7dfaad674587cfd220ff447b3710d252130c3Jordy Rose                    "Insufficient memory space",
229c2b7dfaad674587cfd220ff447b3710d252130c3Jordy Rose                    "Type previously accessed, and not released",
230c2b7dfaad674587cfd220ff447b3710d252130c3Jordy Rose                    "Command out of range, or not implemented",
231c2b7dfaad674587cfd220ff447b3710d252130c3Jordy Rose                    "Cannot send packet (usually hardware error)",
232c2b7dfaad674587cfd220ff447b3710d252130c3Jordy Rose                    "Cannot change hardware address ( > 1 handle open)",
233c2b7dfaad674587cfd220ff447b3710d252130c3Jordy Rose                    "Hardware address has bad length or format",
234c2b7dfaad674587cfd220ff447b3710d252130c3Jordy Rose                    "Cannot reset interface (more than 1 handle open)",
235c2b7dfaad674587cfd220ff447b3710d252130c3Jordy Rose                    "Bad Check-sum",
236c2b7dfaad674587cfd220ff447b3710d252130c3Jordy Rose                    "Bad size",
237c2b7dfaad674587cfd220ff447b3710d252130c3Jordy Rose                    "Bad sync" ,
2382ce43c8f43254a9edea53a20dc0e69195bc82ae0Zhongxing Xu                    "Source hit"
23990e72e4106a0c3efa7575e9f9cba0c775bb54552Zhongxing Xu                  };
24090e72e4106a0c3efa7575e9f9cba0c775bb54552Zhongxing Xu
2411eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  if (errNum < 0 || errNum >= DIM(errStr))
242a516ce16b472e61924f5dd10d181c3e8330979afTed Kremenek     return ("Unknown driver error.");
243a516ce16b472e61924f5dd10d181c3e8330979afTed Kremenek  return (errStr [errNum]);
244a516ce16b472e61924f5dd10d181c3e8330979afTed Kremenek}
2451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
246c8413fd03f73084a5c93028f8b4db619fc388087Ted Kremenek/**************************************************************************/
2476297a8ec313c722db50f686fd190842b7ea91118Ted Kremenek
2486297a8ec313c722db50f686fd190842b7ea91118Ted KremenekPUBLIC const char *PktGetClassName (WORD class)
2496297a8ec313c722db50f686fd190842b7ea91118Ted Kremenek{
2506297a8ec313c722db50f686fd190842b7ea91118Ted Kremenek  switch (class)
2516297a8ec313c722db50f686fd190842b7ea91118Ted Kremenek  {
2526297a8ec313c722db50f686fd190842b7ea91118Ted Kremenek    case PD_ETHER:
2531eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump         return ("DIX-Ether");
254044b6f0417cb98741f277602fabf5f07ec9a02c0Ted Kremenek    case PD_PRONET10:
25500a3a5f024ac54088ab887712b292171188064f0Ted Kremenek         return ("ProNET-10");
25600a3a5f024ac54088ab887712b292171188064f0Ted Kremenek    case PD_IEEE8025:
2571eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump         return ("IEEE 802.5");
258bc42c533e7d3d946704a49e242939dd232f33072Tom Care    case PD_OMNINET:
259bc42c533e7d3d946704a49e242939dd232f33072Tom Care         return ("OmniNet");
26052d861ce41ce84d8389495ea78d97bcc962ac5baTom Care    case PD_APPLETALK:
261bc42c533e7d3d946704a49e242939dd232f33072Tom Care         return ("AppleTalk");
262a7a8a450d908b34fa5f569f2e694ebd4b61aae2fTom Care    case PD_SLIP:
263bc42c533e7d3d946704a49e242939dd232f33072Tom Care         return ("SLIP");
264bc42c533e7d3d946704a49e242939dd232f33072Tom Care    case PD_STARTLAN:
265a7a8a450d908b34fa5f569f2e694ebd4b61aae2fTom Care         return ("StartLAN");
266bc42c533e7d3d946704a49e242939dd232f33072Tom Care    case PD_ARCNET:
26705a2378c708688c8ef498a5cea40ed7f5db15fa5Ted Kremenek         return ("ArcNet");
268031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xu    case PD_AX25:
269846d4e923bf11bcdc2816758aafa331795f29230Ted Kremenek         return ("AX.25");
270512c913a6f93d225faacdb8e20308f5c4065c3ebTed Kremenek    case PD_KISS:
2711eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump         return ("KISS");
2721670e403c48f3af4fceff3f6773a0e1cfc6c4eb3Ted Kremenek    case PD_IEEE8023_2:
2733992a50eea030a2913f1d267554f55ecd00d694cZhongxing Xu         return ("IEEE 802.3 w/802.2 hdr");
2743992a50eea030a2913f1d267554f55ecd00d694cZhongxing Xu    case PD_FDDI8022:
275bb141217871e93767aa3f2de1b9946fa6d37066aZhongxing Xu         return ("FDDI w/802.2 hdr");
276bb141217871e93767aa3f2de1b9946fa6d37066aZhongxing Xu    case PD_X25:
2777b71c1977cccafa23f9ecb3b0b22199e61ae634cZhongxing Xu         return ("X.25");
2785a5d98bc6962dc2d1aaa5e0e522f1bf84273b9c1Ted Kremenek    case PD_LANstar:
2795a5d98bc6962dc2d1aaa5e0e522f1bf84273b9c1Ted Kremenek         return ("LANstar");
28003509aea098772644bf4662dc1c88634818ceeccZhongxing Xu    case PD_PPP:
28172905cfa81cfd126f322c4173f56d332aac5539eJordy Rose         return ("PPP");
282a46e4d91d8f3eb341f2387768db66dcfe8dd0afaZhongxing Xu    default:
283935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xu         return ("unknown");
284935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xu  }
285935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xu}
286935ef90f4b065c7c865ee5b2a99c5f9b1a115d72Zhongxing Xu
287a46e4d91d8f3eb341f2387768db66dcfe8dd0afaZhongxing Xu/**************************************************************************/
288a46e4d91d8f3eb341f2387768db66dcfe8dd0afaZhongxing Xu
289a46e4d91d8f3eb341f2387768db66dcfe8dd0afaZhongxing XuPUBLIC char const *PktRXmodeStr (PKT_RX_MODE mode)
290a46e4d91d8f3eb341f2387768db66dcfe8dd0afaZhongxing Xu{
291b107c4b7efb907d75620cd3c17f82fe27dc5b745Ted Kremenek  static const char *modeStr [] = {
29279d73044b7d0adfbd18ee34285395e1d5135f662Ted Kremenek                    "Receiver turned off",
29379d73044b7d0adfbd18ee34285395e1d5135f662Ted Kremenek                    "Receive only directly addressed packets",
29479d73044b7d0adfbd18ee34285395e1d5135f662Ted Kremenek                    "Receive direct & broadcast packets",
295ec9227fea66c3439991fc84b0d33b0a8b4b8875eZhongxing Xu                    "Receive direct,broadcast and limited multicast packets",
296b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek                    "Receive direct,broadcast and all multicast packets",
297b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek                    "Receive all packets (promiscuouos mode)"
29803509aea098772644bf4662dc1c88634818ceeccZhongxing Xu                  };
2991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
3009c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek  if (mode > DIM(modeStr))
3016d69b5d82281992e981caa9bc038e3f6cac6594aZhongxing Xu     return ("??");
3026d69b5d82281992e981caa9bc038e3f6cac6594aZhongxing Xu  return (modeStr [mode-1]);
30303509aea098772644bf4662dc1c88634818ceeccZhongxing Xu}
3041eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
305c5b1bf10133a8ecbfe9e6b3ec92bae84e3d927e8Ted Kremenek/**************************************************************************/
30603509aea098772644bf4662dc1c88634818ceeccZhongxing Xu
307031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing XuLOCAL __inline BOOL PktInterrupt (void)
3081eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump{
309ef44bfb9d0f15ba0391f8346c9f01355fb450a09Ted Kremenek  BOOL okay;
31003509aea098772644bf4662dc1c88634818ceeccZhongxing Xu
3111eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump#if (DOSX & PHARLAP)
31203509aea098772644bf4662dc1c88634818ceeccZhongxing Xu  _dx_real_int ((UINT)pktInfo.intr, &reg);
31303509aea098772644bf4662dc1c88634818ceeccZhongxing Xu  okay = ((reg.flags & 1) == 0);  /* OK if carry clear */
31403509aea098772644bf4662dc1c88634818ceeccZhongxing Xu
315031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xu#elif (DOSX & DJGPP)
3161eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  __dpmi_int ((int)pktInfo.intr, &reg);
31703509aea098772644bf4662dc1c88634818ceeccZhongxing Xu  okay = ((reg.x.flags & 1) == 0);
31803509aea098772644bf4662dc1c88634818ceeccZhongxing Xu
31903509aea098772644bf4662dc1c88634818ceeccZhongxing Xu#elif (DOSX & DOS4GW)
320031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xu  union  REGS  r;
321c95ad9ff6e574aecdd759542d5578bc65d586d93Ted Kremenek  struct SREGS s;
322c95ad9ff6e574aecdd759542d5578bc65d586d93Ted Kremenek
32303509aea098772644bf4662dc1c88634818ceeccZhongxing Xu  memset (&r, 0, sizeof(r));
32403509aea098772644bf4662dc1c88634818ceeccZhongxing Xu  segread (&s);
3251eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  r.w.ax  = 0x300;
326b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek  r.x.ebx = pktInfo.intr;
32703509aea098772644bf4662dc1c88634818ceeccZhongxing Xu  r.w.cx  = 0;
328662174ca204cb520f634bdcb34a3708f45389d14Zhongxing Xu  s.es    = FP_SEG (&reg);
329469ecbded3616416ef938ed94a67f86149faf226Ted Kremenek  r.x.edi = FP_OFF (&reg);
3301eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  reg.r_flags = 0;
331de43424560f1a744de6214dab6bbee28ad8437f5Ted Kremenek  reg.r_ss = reg.r_sp = 0;     /* DPMI host provides stack */
33203509aea098772644bf4662dc1c88634818ceeccZhongxing Xu
33303509aea098772644bf4662dc1c88634818ceeccZhongxing Xu  int386x (0x31, &r, &r, &s);
33403509aea098772644bf4662dc1c88634818ceeccZhongxing Xu  okay = (!r.w.cflag);
33553287518f69b8f06f82a6cdbd13e4e3a13b58186Ted Kremenek
3361eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump#else
337b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek  reg.r_flags = 0;
33803509aea098772644bf4662dc1c88634818ceeccZhongxing Xu  intr (pktInfo.intr, (struct REGPACK*)&reg);
339b79b117d3b76da58b14ef835ccfcf2e988b7345fZhongxing Xu  okay = ((reg.r_flags & 1) == 0);
340e1c2a675e0c089e1f53cbd55d2197a8beaa852aeTed Kremenek#endif
3414f09027385466f1f4c382c80ca77157e2aef97d9Ted Kremenek
34203509aea098772644bf4662dc1c88634818ceeccZhongxing Xu  if (okay)
34303509aea098772644bf4662dc1c88634818ceeccZhongxing Xu       pktInfo.error = NULL;
34403509aea098772644bf4662dc1c88634818ceeccZhongxing Xu  else pktInfo.error = PktGetErrorStr (reg.r_dx >> 8);
3451eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  return (okay);
346b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek}
34703509aea098772644bf4662dc1c88634818ceeccZhongxing Xu
348c05f23994720b3eb0a3b3494e7bfcec9e1536c89Ted Kremenek/**************************************************************************/
3491eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
35067d1287035767f4f6c8ca0c2bb755990012a44caTed Kremenek/*
35103509aea098772644bf4662dc1c88634818ceeccZhongxing Xu * Search for packet driver at interrupt 60h through 80h. If ASCIIZ
35267d1287035767f4f6c8ca0c2bb755990012a44caTed Kremenek * string "PKT DRVR" found at offset 3 in the interrupt handler, return
35367d1287035767f4f6c8ca0c2bb755990012a44caTed Kremenek * interrupt number, else return zero in pktInfo.intr
35403509aea098772644bf4662dc1c88634818ceeccZhongxing Xu */
35503509aea098772644bf4662dc1c88634818ceeccZhongxing XuPUBLIC BOOL PktSearchDriver (void)
35603509aea098772644bf4662dc1c88634818ceeccZhongxing Xu{
35767d1287035767f4f6c8ca0c2bb755990012a44caTed Kremenek  BYTE intr  = 0x20;
358b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek  BOOL found = FALSE;
35903509aea098772644bf4662dc1c88634818ceeccZhongxing Xu
36003509aea098772644bf4662dc1c88634818ceeccZhongxing Xu  while (!found && intr < 0xFF)
3611eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  {
362b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek    static char str[12];                 /* 3 + strlen("PKT DRVR") */
36303509aea098772644bf4662dc1c88634818ceeccZhongxing Xu    static char pktStr[9] = "PKT DRVR";  /* ASCIIZ string at ofs 3 */
36403509aea098772644bf4662dc1c88634818ceeccZhongxing Xu    DWORD  rp;                           /* in interrupt  routine  */
365c4f8706b6539e06a5de153bd72850bb2e0a71456Zhongxing Xu
366fcfb503c280ed8c66d428fed911b2846c0f434fcTed Kremenek#if (DOSX & PHARLAP)
367fcfb503c280ed8c66d428fed911b2846c0f434fcTed Kremenek    _dx_rmiv_get (intr, &rp);
36803509aea098772644bf4662dc1c88634818ceeccZhongxing Xu    ReadRealMem (&str, (REALPTR)rp, sizeof(str));
369fcfb503c280ed8c66d428fed911b2846c0f434fcTed Kremenek
37061dfbecd8e6181b2ba42ffb5feede27a2bab3b8aTed Kremenek#elif (DOSX & DJGPP)
37103509aea098772644bf4662dc1c88634818ceeccZhongxing Xu    __dpmi_raddr realAdr;
372c05f23994720b3eb0a3b3494e7bfcec9e1536c89Ted Kremenek    __dpmi_get_real_mode_interrupt_vector (intr, &realAdr);
373c4f8706b6539e06a5de153bd72850bb2e0a71456Zhongxing Xu    rp = (realAdr.segment << 4) + realAdr.offset16;
374b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek    dosmemget (rp, sizeof(str), &str);
37503509aea098772644bf4662dc1c88634818ceeccZhongxing Xu
376c05f23994720b3eb0a3b3494e7bfcec9e1536c89Ted Kremenek#elif (DOSX & DOS4GW)
3771eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    rp = dpmi_get_real_vector (intr);
378469ecbded3616416ef938ed94a67f86149faf226Ted Kremenek    memcpy (&str, (void*)rp, sizeof(str));
37903509aea098772644bf4662dc1c88634818ceeccZhongxing Xu
38003509aea098772644bf4662dc1c88634818ceeccZhongxing Xu#else
3811eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    _fmemcpy (&str, getvect(intr), sizeof(str));
3824beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek#endif
3834beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek
3844beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek    found = memcmp (&str[3],&pktStr,sizeof(pktStr)) == 0;
3854beaa9f51b2da57c64740cef2bd1c2fdb0c325d5Ted Kremenek    intr++;
38697ed4f68f5dba3e21e7a490ef0f9ffd3bfead7f8Ted Kremenek  }
38703509aea098772644bf4662dc1c88634818ceeccZhongxing Xu  pktInfo.intr = (found ? intr-1 : 0);
388c05f23994720b3eb0a3b3494e7bfcec9e1536c89Ted Kremenek  return (found);
389af3374187c47acea45706eab6744be6b1c66a856Ted Kremenek}
390af3374187c47acea45706eab6744be6b1c66a856Ted Kremenek
391af3374187c47acea45706eab6744be6b1c66a856Ted Kremenek
39203509aea098772644bf4662dc1c88634818ceeccZhongxing Xu/**************************************************************************/
39303509aea098772644bf4662dc1c88634818ceeccZhongxing Xu
3941eb4433ac451dc16f4133a88af2d002ac26c58efMike Stumpstatic BOOL PktSetAccess (void)
39503509aea098772644bf4662dc1c88634818ceeccZhongxing Xu{
396bb141217871e93767aa3f2de1b9946fa6d37066aZhongxing Xu  reg.r_ax = 0x0200 + pktInfo.class;
397031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xu  reg.r_bx = 0xFFFF;
3981eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  reg.r_dx = 0;
399469ecbded3616416ef938ed94a67f86149faf226Ted Kremenek  reg.r_cx = 0;
40003509aea098772644bf4662dc1c88634818ceeccZhongxing Xu
40138ac4f504bf8ed514520b5a82be538bdb0860687Ted Kremenek#if (DOSX & PHARLAP)
4021eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  reg.ds  = 0;
40302737ed29d7fff2206f7c7ee958cdf0665e35542Ted Kremenek  reg.esi = 0;
40403509aea098772644bf4662dc1c88634818ceeccZhongxing Xu  reg.es  = RP_SEG (realBase);
40503509aea098772644bf4662dc1c88634818ceeccZhongxing Xu  reg.edi = (WORD) &PktReceiver;
4068ecdb65716cd7914ffb2eeee993fa9039fcd31e8Douglas Gregor
4078ecdb65716cd7914ffb2eeee993fa9039fcd31e8Douglas Gregor#elif (DOSX & DJGPP)
40803509aea098772644bf4662dc1c88634818ceeccZhongxing Xu  reg.x.ds = 0;
4098ecdb65716cd7914ffb2eeee993fa9039fcd31e8Douglas Gregor  reg.x.si = 0;
4101eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  reg.x.es = rm_mem.rm_segment;
4110518999d3adcc289997bd974dce90cc97f5c1c44Sebastian Redl  reg.x.di = PktReceiver;
41203509aea098772644bf4662dc1c88634818ceeccZhongxing Xu
413031ccc0555a82afc2e8afe29e19dd57ff204e2deZhongxing Xu#elif (DOSX & DOS4GW)
4141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  reg.r_ds = 0;
415b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek  reg.r_si = 0;
41603509aea098772644bf4662dc1c88634818ceeccZhongxing Xu  reg.r_es = rm_base_seg;
417bb141217871e93767aa3f2de1b9946fa6d37066aZhongxing Xu  reg.r_di = PktReceiver;
418bb141217871e93767aa3f2de1b9946fa6d37066aZhongxing Xu
41903509aea098772644bf4662dc1c88634818ceeccZhongxing Xu#else
420bb141217871e93767aa3f2de1b9946fa6d37066aZhongxing Xu  reg.r_ds = 0;
421d706434b0231c76fd9acf30060646a7aa8f69aefZhongxing Xu  reg.r_si = 0;
422d706434b0231c76fd9acf30060646a7aa8f69aefZhongxing Xu  reg.r_es = FP_SEG (&PktReceiver);
423d706434b0231c76fd9acf30060646a7aa8f69aefZhongxing Xu  reg.r_di = FP_OFF (&PktReceiver);
424d706434b0231c76fd9acf30060646a7aa8f69aefZhongxing Xu#endif
425d706434b0231c76fd9acf30060646a7aa8f69aefZhongxing Xu
426d706434b0231c76fd9acf30060646a7aa8f69aefZhongxing Xu  if (!PktInterrupt())
427d706434b0231c76fd9acf30060646a7aa8f69aefZhongxing Xu     return (FALSE);
4287ce351db56fbce162a3b650518ce05b5c61ebf36Zhongxing Xu
429d706434b0231c76fd9acf30060646a7aa8f69aefZhongxing Xu  pktInfo.handle = reg.r_ax;
430d706434b0231c76fd9acf30060646a7aa8f69aefZhongxing Xu  return (TRUE);
431950db87e5efe2ff0c7234116929f8637aaf7ae7aZhongxing Xu}
432b13453bd8a91f331d0910ca95ad52aa41b52f648Zhongxing Xu
433b13453bd8a91f331d0910ca95ad52aa41b52f648Zhongxing Xu/**************************************************************************/
434b13453bd8a91f331d0910ca95ad52aa41b52f648Zhongxing Xu
435b13453bd8a91f331d0910ca95ad52aa41b52f648Zhongxing XuPUBLIC BOOL PktReleaseHandle (WORD handle)
436950db87e5efe2ff0c7234116929f8637aaf7ae7aZhongxing Xu{
437950db87e5efe2ff0c7234116929f8637aaf7ae7aZhongxing Xu  reg.r_ax = 0x0300;
438950db87e5efe2ff0c7234116929f8637aaf7ae7aZhongxing Xu  reg.r_bx = handle;
4396a02b609c2e23b28d24f9db4c8006137c6b55ae4Marcin Swiderski  return PktInterrupt();
4406a02b609c2e23b28d24f9db4c8006137c6b55ae4Marcin Swiderski}
4416a02b609c2e23b28d24f9db4c8006137c6b55ae4Marcin Swiderski
44203509aea098772644bf4662dc1c88634818ceeccZhongxing Xu/**************************************************************************/
443856c6bcaea56e05255e9f3997ddd56b5c18a14f0Zhongxing Xu
444856c6bcaea56e05255e9f3997ddd56b5c18a14f0Zhongxing XuPUBLIC BOOL PktTransmit (const void *eth, int len)
44503509aea098772644bf4662dc1c88634818ceeccZhongxing Xu{
4466b8513829895e56a7b97e787ea74520bc626512eZhongxing Xu  if (len > ETH_MTU)
4476b8513829895e56a7b97e787ea74520bc626512eZhongxing Xu     return (FALSE);
4487ce351db56fbce162a3b650518ce05b5c61ebf36Zhongxing Xu
4497b71c1977cccafa23f9ecb3b0b22199e61ae634cZhongxing Xu  reg.r_ax = 0x0400;             /* Function 4, send pkt */
4507b71c1977cccafa23f9ecb3b0b22199e61ae634cZhongxing Xu  reg.r_cx = len;                /* total size of frame  */
451bc37b8dd9914e02580f531fa6e5e72be34d9675eZhongxing Xu
45203509aea098772644bf4662dc1c88634818ceeccZhongxing Xu#if (DOSX & DJGPP)
453bc37b8dd9914e02580f531fa6e5e72be34d9675eZhongxing Xu  dosmemput (eth, len, realBase+pktTxBuf);
454bc37b8dd9914e02580f531fa6e5e72be34d9675eZhongxing Xu  reg.x.ds = rm_mem.rm_segment;  /* DOS data segment and */
4558e18c1b840882d26039503629d7e4ad4822f3bdaZhongxing Xu  reg.x.si = pktTxBuf;           /* DOS offset to buffer */
4569dc84c9455df2a77195147d0210c915dc1775a88Zhongxing Xu
4578e18c1b840882d26039503629d7e4ad4822f3bdaZhongxing Xu#elif (DOSX & DOS4GW)
4588e18c1b840882d26039503629d7e4ad4822f3bdaZhongxing Xu  memcpy ((void*)(realBase+pktTxBuf), eth, len);
45932303020d0f1a21cbcab65ae0c69a4218dc8f0fbZhongxing Xu  reg.r_ds = rm_base_seg;
46032303020d0f1a21cbcab65ae0c69a4218dc8f0fbZhongxing Xu  reg.r_si = pktTxBuf;
46132303020d0f1a21cbcab65ae0c69a4218dc8f0fbZhongxing Xu
462b17b1b3cc2b0d4d3b263b9384571bbc7f3995771Zhongxing Xu#elif (DOSX & PHARLAP)
4639c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek  memcpy (&pktTxBuf, eth, len);
464b17b1b3cc2b0d4d3b263b9384571bbc7f3995771Zhongxing Xu  reg.r_ds = FP_SEG (&pktTxBuf);
46582c63bfa0c5130e0cf274c1974b6157ebefc04feMarcin Swiderski  reg.r_si = FP_OFF (&pktTxBuf);
46682c63bfa0c5130e0cf274c1974b6157ebefc04feMarcin Swiderski
467b17b1b3cc2b0d4d3b263b9384571bbc7f3995771Zhongxing Xu#else
4686a02b609c2e23b28d24f9db4c8006137c6b55ae4Marcin Swiderski  reg.r_ds = FP_SEG (eth);
4696a02b609c2e23b28d24f9db4c8006137c6b55ae4Marcin Swiderski  reg.r_si = FP_OFF (eth);
4709c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek#endif
4716a02b609c2e23b28d24f9db4c8006137c6b55ae4Marcin Swiderski
4726a02b609c2e23b28d24f9db4c8006137c6b55ae4Marcin Swiderski  return PktInterrupt();
4736a02b609c2e23b28d24f9db4c8006137c6b55ae4Marcin Swiderski}
4749c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek
47548af2a9c1ed3259512f2d1431720add1fbe8fb5fTed Kremenek/**************************************************************************/
47648af2a9c1ed3259512f2d1431720add1fbe8fb5fTed Kremenek
4779c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek#if (DOSX & (DJGPP|DOS4GW))
47803509aea098772644bf4662dc1c88634818ceeccZhongxing XuLOCAL __inline BOOL CheckElement (RX_ELEMENT *rx)
4791eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump#else
4809c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed KremenekLOCAL __inline BOOL CheckElement (RX_ELEMENT _far *rx)
4819c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek#endif
482b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek{
4831eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  WORD count_1, count_2;
4849c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek
4859c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek  /*
48690e420321f60860f4c4e7a68ca9f7567824b46ecTed Kremenek   * We got an upcall to the same RMCB with wrong handle.
487248072a8b9cd956c4ac63172fc2af09790f7c6a9Zhongxing Xu   * This can happen if we failed to release handle at program exit
4881670e403c48f3af4fceff3f6773a0e1cfc6c4eb3Ted Kremenek   */
4891eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  if (rx->handle != pktInfo.handle)
4909c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek  {
491cd8f6ac9b613e1fe962ebf9c87d822ce765275e6Ted Kremenek    pktInfo.error = "Wrong handle";
4929c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek    intStat.wrongHandle++;
4936297a8ec313c722db50f686fd190842b7ea91118Ted Kremenek    PktReleaseHandle (rx->handle);
49410c16657eec144def180ee53d1e0249c9ed2b3b5Ted Kremenek    return (FALSE);
4959c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek  }
496cd8f6ac9b613e1fe962ebf9c87d822ce765275e6Ted Kremenek  count_1 = rx->firstCount;
4979c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek  count_2 = rx->secondCount;
498b640b3b5dfccaf259967cb2cb6755c9aa20d4423Ted Kremenek
4991eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump  if (count_1 != count_2)
5009c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek  {
501ff4264dae31cf42807b64ecc114906b0b835690aTed Kremenek    pktInfo.error = "Bad sync";
5029c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek    intStat.badSync++;
503ff4264dae31cf42807b64ecc114906b0b835690aTed Kremenek    return (FALSE);
5045b9bd2137ebef350af803c634e3fdf5d74678100Ted Kremenek  }
5051670e403c48f3af4fceff3f6773a0e1cfc6c4eb3Ted Kremenek  if (count_1 > ETH_MAX)
5069c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek  {
507a46e4d91d8f3eb341f2387768db66dcfe8dd0afaZhongxing Xu    pktInfo.error = "Large esize";
508e695e1cd7d8a579455e8969be36cbaf10a316a64Ted Kremenek    intStat.tooLarge++;
5099c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek    return (FALSE);
510de43424560f1a744de6214dab6bbee28ad8437f5Ted Kremenek  }
5111670e403c48f3af4fceff3f6773a0e1cfc6c4eb3Ted Kremenek#if 0
51203509aea098772644bf4662dc1c88634818ceeccZhongxing Xu  if (count_1 < ETH_MIN)
5131670e403c48f3af4fceff3f6773a0e1cfc6c4eb3Ted Kremenek  {
5141eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump    pktInfo.error = "Small esize";
5159c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek    intStat.tooSmall++;
5169c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek    return (FALSE);
5179c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek  }
518f6f56d4fc8ebce17e7b83eb2c35f57a055c22283Ted Kremenek#endif
519f6f56d4fc8ebce17e7b83eb2c35f57a055c22283Ted Kremenek  return (TRUE);
5201eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump}
5211670e403c48f3af4fceff3f6773a0e1cfc6c4eb3Ted Kremenek
522b4b817d704287836b52b34369009e682f208aa2bTed Kremenek/**************************************************************************/
523b4b817d704287836b52b34369009e682f208aa2bTed Kremenek
524834f9de3d3d76986d09f41725a70ba45a3e2aecdZhanyong WanPUBLIC BOOL PktTerminHandle (WORD handle)
525834f9de3d3d76986d09f41725a70ba45a3e2aecdZhanyong Wan{
526834f9de3d3d76986d09f41725a70ba45a3e2aecdZhanyong Wan  reg.r_ax = 0x0500;
527834f9de3d3d76986d09f41725a70ba45a3e2aecdZhanyong Wan  reg.r_bx = handle;
5289c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek  return PktInterrupt();
529652be346f74feba027bcbdeb6a3e3f4755a0e62cZhongxing Xu}
530652be346f74feba027bcbdeb6a3e3f4755a0e62cZhongxing Xu
5311eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump/**************************************************************************/
532b4b817d704287836b52b34369009e682f208aa2bTed Kremenek
533b4b817d704287836b52b34369009e682f208aa2bTed KremenekPUBLIC BOOL PktResetInterface (WORD handle)
5349c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek{
535b4b817d704287836b52b34369009e682f208aa2bTed Kremenek  reg.r_ax = 0x0700;
5361670e403c48f3af4fceff3f6773a0e1cfc6c4eb3Ted Kremenek  reg.r_bx = handle;
537834f9de3d3d76986d09f41725a70ba45a3e2aecdZhanyong Wan  return PktInterrupt();
5389c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek}
539852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek
540852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek/**************************************************************************/
541852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek
542852274d4257134906995cb252fb3dfd2d71deae8Ted KremenekPUBLIC BOOL PktSetReceiverMode (PKT_RX_MODE mode)
543852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek{
5449c14953d0c84f7cf5adfb4cd3c0f05a9b1723c1cTed Kremenek  if (pktInfo.class == PD_SLIP || pktInfo.class == PD_PPP)
545852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek     return (TRUE);
546852274d4257134906995cb252fb3dfd2d71deae8Ted Kremenek
5471c625f25055331bf76ab5479a8060d2b0f61e8b8Zhongxing Xu  reg.r_ax = 0x1400;
5481c625f25055331bf76ab5479a8060d2b0f61e8b8Zhongxing Xu  reg.r_bx = pktInfo.handle;
549b387a3f23e423d62c053be86294b703da1d1a222Ted Kremenek  reg.r_cx = (WORD)mode;
5501eb4433ac451dc16f4133a88af2d002ac26c58efMike Stump
551c0c3f5dbc9e78aa53a86c7d5e3eeda23ddad93d6Ted Kremenek  if (!PktInterrupt())
552c0c3f5dbc9e78aa53a86c7d5e3eeda23ddad93d6Ted Kremenek     return (FALSE);
553d065d6080f0620bb80b933f3f5d52d37bb2ea770Ted Kremenek
554  receiveMode = mode;
555  return (TRUE);
556}
557
558/**************************************************************************/
559
560PUBLIC BOOL PktGetReceiverMode (PKT_RX_MODE *mode)
561{
562  reg.r_ax = 0x1500;
563  reg.r_bx = pktInfo.handle;
564
565  if (!PktInterrupt())
566     return (FALSE);
567
568  *mode = reg.r_ax;
569  return (TRUE);
570}
571
572/**************************************************************************/
573
574static PKT_STAT initialStat;         /* statistics at startup */
575static BOOL     resetStat = FALSE;   /* statistics reset ? */
576
577PUBLIC BOOL PktGetStatistics (WORD handle)
578{
579  reg.r_ax = 0x1800;
580  reg.r_bx = handle;
581
582  if (!PktInterrupt())
583     return (FALSE);
584
585#if (DOSX & PHARLAP)
586  ReadRealMem (&pktStat, DOS_ADDR(reg.ds,reg.esi), sizeof(pktStat));
587
588#elif (DOSX & DJGPP)
589  dosmemget (DOS_ADDR(reg.x.ds,reg.x.si), sizeof(pktStat), &pktStat);
590
591#elif (DOSX & DOS4GW)
592  memcpy (&pktStat, (void*)DOS_ADDR(reg.r_ds,reg.r_si), sizeof(pktStat));
593
594#else
595  _fmemcpy (&pktStat, MK_FP(reg.r_ds,reg.r_si), sizeof(pktStat));
596#endif
597
598  return (TRUE);
599}
600
601/**************************************************************************/
602
603PUBLIC BOOL PktSessStatistics (WORD handle)
604{
605  if (!PktGetStatistics(pktInfo.handle))
606     return (FALSE);
607
608  if (resetStat)
609  {
610    pktStat.inPackets  -= initialStat.inPackets;
611    pktStat.outPackets -= initialStat.outPackets;
612    pktStat.inBytes    -= initialStat.inBytes;
613    pktStat.outBytes   -= initialStat.outBytes;
614    pktStat.inErrors   -= initialStat.inErrors;
615    pktStat.outErrors  -= initialStat.outErrors;
616    pktStat.outErrors  -= initialStat.outErrors;
617    pktStat.lost       -= initialStat.lost;
618  }
619  return (TRUE);
620}
621
622/**************************************************************************/
623
624PUBLIC BOOL PktResetStatistics (WORD handle)
625{
626  if (!PktGetStatistics(pktInfo.handle))
627     return (FALSE);
628
629  memcpy (&initialStat, &pktStat, sizeof(initialStat));
630  resetStat = TRUE;
631  return (TRUE);
632}
633
634/**************************************************************************/
635
636PUBLIC BOOL PktGetAddress (ETHER *addr)
637{
638  reg.r_ax = 0x0600;
639  reg.r_bx = pktInfo.handle;
640  reg.r_cx = sizeof (*addr);
641
642#if (DOSX & DJGPP)
643  reg.x.es = rm_mem.rm_segment;
644  reg.x.di = pktTemp;
645#elif (DOSX & DOS4GW)
646  reg.r_es = rm_base_seg;
647  reg.r_di = pktTemp;
648#else
649  reg.r_es = FP_SEG (&pktTemp);
650  reg.r_di = FP_OFF (&pktTemp);  /* ES:DI = address for result */
651#endif
652
653  if (!PktInterrupt())
654     return (FALSE);
655
656#if (DOSX & PHARLAP)
657  ReadRealMem (addr, realBase + (WORD)&pktTemp, sizeof(*addr));
658
659#elif (DOSX & DJGPP)
660  dosmemget (realBase+pktTemp, sizeof(*addr), addr);
661
662#elif (DOSX & DOS4GW)
663  memcpy (addr, (void*)(realBase+pktTemp), sizeof(*addr));
664
665#else
666  memcpy ((void*)addr, &pktTemp, sizeof(*addr));
667#endif
668
669  return (TRUE);
670}
671
672/**************************************************************************/
673
674PUBLIC BOOL PktSetAddress (const ETHER *addr)
675{
676  /* copy addr to real-mode scrath area */
677
678#if (DOSX & PHARLAP)
679  WriteRealMem (realBase + (WORD)&pktTemp, (void*)addr, sizeof(*addr));
680
681#elif (DOSX & DJGPP)
682  dosmemput (addr, sizeof(*addr), realBase+pktTemp);
683
684#elif (DOSX & DOS4GW)
685  memcpy ((void*)(realBase+pktTemp), addr, sizeof(*addr));
686
687#else
688  memcpy (&pktTemp, (void*)addr, sizeof(*addr));
689#endif
690
691  reg.r_ax = 0x1900;
692  reg.r_cx = sizeof (*addr);      /* address length       */
693
694#if (DOSX & DJGPP)
695  reg.x.es = rm_mem.rm_segment;   /* DOS offset to param  */
696  reg.x.di = pktTemp;             /* DOS segment to param */
697#elif (DOSX & DOS4GW)
698  reg.r_es = rm_base_seg;
699  reg.r_di = pktTemp;
700#else
701  reg.r_es = FP_SEG (&pktTemp);
702  reg.r_di = FP_OFF (&pktTemp);
703#endif
704
705  return PktInterrupt();
706}
707
708/**************************************************************************/
709
710PUBLIC BOOL PktGetDriverInfo (void)
711{
712  pktInfo.majVer = 0;
713  pktInfo.minVer = 0;
714  memset (&pktInfo.name, 0, sizeof(pktInfo.name));
715  reg.r_ax = 0x01FF;
716  reg.r_bx = 0;
717
718  if (!PktInterrupt())
719     return (FALSE);
720
721  pktInfo.number = reg.r_cx & 0xFF;
722  pktInfo.class  = reg.r_cx >> 8;
723#if 0
724  pktInfo.minVer = reg.r_bx % 10;
725  pktInfo.majVer = reg.r_bx / 10;
726#else
727  pktInfo.majVer = reg.r_bx;  // !!
728#endif
729  pktInfo.funcs  = reg.r_ax & 0xFF;
730  pktInfo.type   = reg.r_dx & 0xFF;
731
732#if (DOSX & PHARLAP)
733  ReadRealMem (&pktInfo.name, DOS_ADDR(reg.ds,reg.esi), sizeof(pktInfo.name));
734
735#elif (DOSX & DJGPP)
736  dosmemget (DOS_ADDR(reg.x.ds,reg.x.si), sizeof(pktInfo.name), &pktInfo.name);
737
738#elif (DOSX & DOS4GW)
739  memcpy (&pktInfo.name, (void*)DOS_ADDR(reg.r_ds,reg.r_si), sizeof(pktInfo.name));
740
741#else
742  _fmemcpy (&pktInfo.name, MK_FP(reg.r_ds,reg.r_si), sizeof(pktInfo.name));
743#endif
744  return (TRUE);
745}
746
747/**************************************************************************/
748
749PUBLIC BOOL PktGetDriverParam (void)
750{
751  reg.r_ax = 0x0A00;
752
753  if (!PktInterrupt())
754     return (FALSE);
755
756#if (DOSX & PHARLAP)
757  ReadRealMem (&pktInfo.majVer, DOS_ADDR(reg.es,reg.edi), PKT_PARAM_SIZE);
758
759#elif (DOSX & DJGPP)
760  dosmemget (DOS_ADDR(reg.x.es,reg.x.di), PKT_PARAM_SIZE, &pktInfo.majVer);
761
762#elif (DOSX & DOS4GW)
763  memcpy (&pktInfo.majVer, (void*)DOS_ADDR(reg.r_es,reg.r_di), PKT_PARAM_SIZE);
764
765#else
766  _fmemcpy (&pktInfo.majVer, MK_FP(reg.r_es,reg.r_di), PKT_PARAM_SIZE);
767#endif
768  return (TRUE);
769}
770
771/**************************************************************************/
772
773#if (DOSX & PHARLAP)
774  PUBLIC int PktReceive (BYTE *buf, int max)
775  {
776    WORD inOfs  = *rxInOfsFp;
777    WORD outOfs = *rxOutOfsFp;
778
779    if (outOfs != inOfs)
780    {
781      RX_ELEMENT _far *head = (RX_ELEMENT _far*)(protBase+outOfs);
782      int size, len = max;
783
784      if (CheckElement(head))
785      {
786        size = min (head->firstCount, sizeof(RX_ELEMENT));
787        len  = min (size, max);
788        _fmemcpy (buf, &head->destin, len);
789      }
790      else
791        size = -1;
792
793      outOfs += sizeof (RX_ELEMENT);
794      if (outOfs > LAST_RX_BUF)
795          outOfs = FIRST_RX_BUF;
796      *rxOutOfsFp = outOfs;
797      return (size);
798    }
799    return (0);
800  }
801
802  PUBLIC void PktQueueBusy (BOOL busy)
803  {
804    *rxOutOfsFp = busy ? (*rxInOfsFp + sizeof(RX_ELEMENT)) : *rxInOfsFp;
805    if (*rxOutOfsFp > LAST_RX_BUF)
806        *rxOutOfsFp = FIRST_RX_BUF;
807    *(DWORD _far*)(protBase + (WORD)&pktDrop) = 0;
808  }
809
810  PUBLIC WORD PktBuffersUsed (void)
811  {
812    WORD inOfs  = *rxInOfsFp;
813    WORD outOfs = *rxOutOfsFp;
814
815    if (inOfs >= outOfs)
816       return (inOfs - outOfs) / sizeof(RX_ELEMENT);
817    return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));
818  }
819
820  PUBLIC DWORD PktRxDropped (void)
821  {
822    return (*(DWORD _far*)(protBase + (WORD)&pktDrop));
823  }
824
825#elif (DOSX & DJGPP)
826  PUBLIC int PktReceive (BYTE *buf, int max)
827  {
828    WORD ofs = _farpeekw (_dos_ds, realBase+rxOutOfs);
829
830    if (ofs != _farpeekw (_dos_ds, realBase+rxInOfs))
831    {
832      RX_ELEMENT head;
833      int  size, len = max;
834
835      head.firstCount  = _farpeekw (_dos_ds, realBase+ofs);
836      head.secondCount = _farpeekw (_dos_ds, realBase+ofs+2);
837      head.handle      = _farpeekw (_dos_ds, realBase+ofs+4);
838
839      if (CheckElement(&head))
840      {
841        size = min (head.firstCount, sizeof(RX_ELEMENT));
842        len  = min (size, max);
843        dosmemget (realBase+ofs+6, len, buf);
844      }
845      else
846        size = -1;
847
848      ofs += sizeof (RX_ELEMENT);
849      if (ofs > LAST_RX_BUF)
850           _farpokew (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);
851      else _farpokew (_dos_ds, realBase+rxOutOfs, ofs);
852      return (size);
853    }
854    return (0);
855  }
856
857  PUBLIC void PktQueueBusy (BOOL busy)
858  {
859    WORD ofs;
860
861    disable();
862    ofs = _farpeekw (_dos_ds, realBase+rxInOfs);
863    if (busy)
864       ofs += sizeof (RX_ELEMENT);
865
866    if (ofs > LAST_RX_BUF)
867         _farpokew (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);
868    else _farpokew (_dos_ds, realBase+rxOutOfs, ofs);
869    _farpokel (_dos_ds, realBase+pktDrop, 0UL);
870    enable();
871  }
872
873  PUBLIC WORD PktBuffersUsed (void)
874  {
875    WORD inOfs, outOfs;
876
877    disable();
878    inOfs  = _farpeekw (_dos_ds, realBase+rxInOfs);
879    outOfs = _farpeekw (_dos_ds, realBase+rxOutOfs);
880    enable();
881    if (inOfs >= outOfs)
882       return (inOfs - outOfs) / sizeof(RX_ELEMENT);
883    return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));
884  }
885
886  PUBLIC DWORD PktRxDropped (void)
887  {
888    return _farpeekl (_dos_ds, realBase+pktDrop);
889  }
890
891#elif (DOSX & DOS4GW)
892  PUBLIC int PktReceive (BYTE *buf, int max)
893  {
894    WORD ofs = *(WORD*) (realBase+rxOutOfs);
895
896    if (ofs != *(WORD*) (realBase+rxInOfs))
897    {
898      RX_ELEMENT head;
899      int  size, len = max;
900
901      head.firstCount  = *(WORD*) (realBase+ofs);
902      head.secondCount = *(WORD*) (realBase+ofs+2);
903      head.handle      = *(WORD*) (realBase+ofs+4);
904
905      if (CheckElement(&head))
906      {
907        size = min (head.firstCount, sizeof(RX_ELEMENT));
908        len  = min (size, max);
909        memcpy (buf, (const void*)(realBase+ofs+6), len);
910      }
911      else
912        size = -1;
913
914      ofs += sizeof (RX_ELEMENT);
915      if (ofs > LAST_RX_BUF)
916           *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;
917      else *(WORD*) (realBase+rxOutOfs) = ofs;
918      return (size);
919    }
920    return (0);
921  }
922
923  PUBLIC void PktQueueBusy (BOOL busy)
924  {
925    WORD ofs;
926
927    _disable();
928    ofs = *(WORD*) (realBase+rxInOfs);
929    if (busy)
930       ofs += sizeof (RX_ELEMENT);
931
932    if (ofs > LAST_RX_BUF)
933         *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;
934    else *(WORD*) (realBase+rxOutOfs) = ofs;
935    *(DWORD*) (realBase+pktDrop) = 0UL;
936    _enable();
937  }
938
939  PUBLIC WORD PktBuffersUsed (void)
940  {
941    WORD inOfs, outOfs;
942
943    _disable();
944    inOfs  = *(WORD*) (realBase+rxInOfs);
945    outOfs = *(WORD*) (realBase+rxOutOfs);
946    _enable();
947    if (inOfs >= outOfs)
948       return (inOfs - outOfs) / sizeof(RX_ELEMENT);
949    return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));
950  }
951
952  PUBLIC DWORD PktRxDropped (void)
953  {
954    return *(DWORD*) (realBase+pktDrop);
955  }
956
957#else     /* real-mode small/large model */
958
959  PUBLIC int PktReceive (BYTE *buf, int max)
960  {
961    if (rxOutOfs != rxInOfs)
962    {
963      RX_ELEMENT far *head = (RX_ELEMENT far*) MK_FP (_DS,rxOutOfs);
964      int  size, len = max;
965
966      if (CheckElement(head))
967      {
968        size = min (head->firstCount, sizeof(RX_ELEMENT));
969        len  = min (size, max);
970        _fmemcpy (buf, &head->destin, len);
971      }
972      else
973        size = -1;
974
975      rxOutOfs += sizeof (RX_ELEMENT);
976      if (rxOutOfs > LAST_RX_BUF)
977          rxOutOfs = FIRST_RX_BUF;
978      return (size);
979    }
980    return (0);
981  }
982
983  PUBLIC void PktQueueBusy (BOOL busy)
984  {
985    rxOutOfs = busy ? (rxInOfs + sizeof(RX_ELEMENT)) : rxInOfs;
986    if (rxOutOfs > LAST_RX_BUF)
987        rxOutOfs = FIRST_RX_BUF;
988    pktDrop = 0L;
989  }
990
991  PUBLIC WORD PktBuffersUsed (void)
992  {
993    WORD inOfs  = rxInOfs;
994    WORD outOfs = rxOutOfs;
995
996    if (inOfs >= outOfs)
997       return ((inOfs - outOfs) / sizeof(RX_ELEMENT));
998    return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));
999  }
1000
1001  PUBLIC DWORD PktRxDropped (void)
1002  {
1003    return (pktDrop);
1004  }
1005#endif
1006
1007/**************************************************************************/
1008
1009LOCAL __inline void PktFreeMem (void)
1010{
1011#if (DOSX & PHARLAP)
1012  if (realSeg)
1013  {
1014    _dx_real_free (realSeg);
1015    realSeg = 0;
1016  }
1017#elif (DOSX & DJGPP)
1018  if (rm_mem.rm_segment)
1019  {
1020    unsigned ofs;  /* clear the DOS-mem to prevent further upcalls */
1021
1022    for (ofs = 0; ofs < 16 * rm_mem.size / 4; ofs += 4)
1023       _farpokel (_dos_ds, realBase + ofs, 0);
1024    _go32_dpmi_free_dos_memory (&rm_mem);
1025    rm_mem.rm_segment = 0;
1026  }
1027#elif (DOSX & DOS4GW)
1028  if (rm_base_sel)
1029  {
1030    dpmi_real_free (rm_base_sel);
1031    rm_base_sel = 0;
1032  }
1033#endif
1034}
1035
1036/**************************************************************************/
1037
1038PUBLIC BOOL PktExitDriver (void)
1039{
1040  if (pktInfo.handle)
1041  {
1042    if (!PktSetReceiverMode(PDRX_BROADCAST))
1043       PUTS ("Error restoring receiver mode.");
1044
1045    if (!PktReleaseHandle(pktInfo.handle))
1046       PUTS ("Error releasing PKT-DRVR handle.");
1047
1048    PktFreeMem();
1049    pktInfo.handle = 0;
1050  }
1051
1052  if (pcap_pkt_debug >= 1)
1053     printf ("Internal stats: too-small %lu, too-large %lu, bad-sync %lu, "
1054             "wrong-handle %lu\n",
1055             intStat.tooSmall, intStat.tooLarge,
1056             intStat.badSync, intStat.wrongHandle);
1057  return (TRUE);
1058}
1059
1060#if (DOSX & (DJGPP|DOS4GW))
1061static void dump_pkt_stub (void)
1062{
1063  int i;
1064
1065  fprintf (stderr, "PktReceiver %lu, pkt_stub[PktReceiver] =\n",
1066           PktReceiver);
1067  for (i = 0; i < 15; i++)
1068      fprintf (stderr, "%02X, ", real_stub_array[i+PktReceiver]);
1069  fputs ("\n", stderr);
1070}
1071#endif
1072
1073/*
1074 * Front end initialization routine
1075 */
1076PUBLIC BOOL PktInitDriver (PKT_RX_MODE mode)
1077{
1078  PKT_RX_MODE rxMode;
1079  BOOL   writeInfo = (pcap_pkt_debug >= 3);
1080
1081  pktInfo.quiet = (pcap_pkt_debug < 3);
1082
1083#if (DOSX & PHARLAP) && defined(__HIGHC__)
1084  if (_mwenv != 2)
1085  {
1086    fprintf (stderr, "Only Pharlap DOS extender supported.\n");
1087    return (FALSE);
1088  }
1089#endif
1090
1091#if (DOSX & PHARLAP) && defined(__WATCOMC__)
1092  if (_Extender != 1)
1093  {
1094    fprintf (stderr, "Only DOS4GW style extenders supported.\n");
1095    return (FALSE);
1096  }
1097#endif
1098
1099  if (!PktSearchDriver())
1100  {
1101    PUTS ("Packet driver not found.");
1102    PktFreeMem();
1103    return (FALSE);
1104  }
1105
1106  if (!PktGetDriverInfo())
1107  {
1108    PUTS ("Error getting pkt-drvr information.");
1109    PktFreeMem();
1110    return (FALSE);
1111  }
1112
1113#if (DOSX & PHARLAP)
1114  if (RealCopy((ULONG)&rxOutOfs, (ULONG)&pktRxEnd,
1115               &realBase, &protBase, (USHORT*)&realSeg))
1116  {
1117    rxOutOfsFp  = (WORD _far *) (protBase + (WORD) &rxOutOfs);
1118    rxInOfsFp   = (WORD _far *) (protBase + (WORD) &rxInOfs);
1119    *rxOutOfsFp = FIRST_RX_BUF;
1120    *rxInOfsFp  = FIRST_RX_BUF;
1121  }
1122  else
1123  {
1124    PUTS ("Cannot allocate real-mode stub.");
1125    return (FALSE);
1126  }
1127
1128#elif (DOSX & (DJGPP|DOS4GW))
1129  if (sizeof(real_stub_array) > 0xFFFF)
1130  {
1131    fprintf (stderr, "`real_stub_array[]' too big.\n");
1132    return (FALSE);
1133  }
1134#if (DOSX & DJGPP)
1135  rm_mem.size = (sizeof(real_stub_array) + 15) / 16;
1136
1137  if (_go32_dpmi_allocate_dos_memory(&rm_mem) || rm_mem.rm_offset != 0)
1138  {
1139    PUTS ("real-mode init failed.");
1140    return (FALSE);
1141  }
1142  realBase = (rm_mem.rm_segment << 4);
1143  dosmemput (&real_stub_array, sizeof(real_stub_array), realBase);
1144  _farpokel (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);
1145  _farpokel (_dos_ds, realBase+rxInOfs,  FIRST_RX_BUF);
1146
1147#elif (DOSX & DOS4GW)
1148  rm_base_seg = dpmi_real_malloc (sizeof(real_stub_array), &rm_base_sel);
1149  if (!rm_base_seg)
1150  {
1151    PUTS ("real-mode init failed.");
1152    return (FALSE);
1153  }
1154  realBase = (rm_base_seg << 4);
1155  memcpy ((void*)realBase, &real_stub_array, sizeof(real_stub_array));
1156  *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;
1157  *(WORD*) (realBase+rxInOfs)  = FIRST_RX_BUF;
1158
1159#endif
1160  {
1161    int pushf = PktReceiver;
1162
1163    while (real_stub_array[pushf++] != 0x9C &&    /* pushf */
1164           real_stub_array[pushf]   != 0xFA)      /* cli   */
1165    {
1166      if (++para_skip > 16)
1167      {
1168        fprintf (stderr, "Something wrong with `pkt_stub.inc'.\n");
1169        para_skip = 0;
1170        dump_pkt_stub();
1171        return (FALSE);
1172      }
1173    }
1174    if (*(WORD*)(real_stub_array + offsetof(PktRealStub,_dummy)) != 0xB800)
1175    {
1176      fprintf (stderr, "`real_stub_array[]' is misaligned.\n");
1177      return (FALSE);
1178    }
1179  }
1180
1181  if (pcap_pkt_debug > 2)
1182      dump_pkt_stub();
1183
1184#else
1185  rxOutOfs = FIRST_RX_BUF;
1186  rxInOfs  = FIRST_RX_BUF;
1187#endif
1188
1189  if (!PktSetAccess())
1190  {
1191    PUTS ("Error setting pkt-drvr access.");
1192    PktFreeMem();
1193    return (FALSE);
1194  }
1195
1196  if (!PktGetAddress(&myAddress))
1197  {
1198    PUTS ("Error fetching adapter address.");
1199    PktFreeMem();
1200    return (FALSE);
1201  }
1202
1203  if (!PktSetReceiverMode(mode))
1204  {
1205    PUTS ("Error setting receiver mode.");
1206    PktFreeMem();
1207    return (FALSE);
1208  }
1209
1210  if (!PktGetReceiverMode(&rxMode))
1211  {
1212    PUTS ("Error getting receiver mode.");
1213    PktFreeMem();
1214    return (FALSE);
1215  }
1216
1217  if (writeInfo)
1218     printf ("Pkt-driver information:\n"
1219             "  Version  : %d.%d\n"
1220             "  Name     : %.15s\n"
1221             "  Class    : %u (%s)\n"
1222             "  Type     : %u\n"
1223             "  Number   : %u\n"
1224             "  Funcs    : %u\n"
1225             "  Intr     : %Xh\n"
1226             "  Handle   : %u\n"
1227             "  Extended : %s\n"
1228             "  Hi-perf  : %s\n"
1229             "  RX mode  : %s\n"
1230             "  Eth-addr : %02X:%02X:%02X:%02X:%02X:%02X\n",
1231
1232             pktInfo.majVer, pktInfo.minVer, pktInfo.name,
1233             pktInfo.class,  PktGetClassName(pktInfo.class),
1234             pktInfo.type,   pktInfo.number,
1235             pktInfo.funcs,  pktInfo.intr,   pktInfo.handle,
1236             pktInfo.funcs == 2 || pktInfo.funcs == 6 ? "Yes" : "No",
1237             pktInfo.funcs == 5 || pktInfo.funcs == 6 ? "Yes" : "No",
1238             PktRXmodeStr(rxMode),
1239             myAddress[0], myAddress[1], myAddress[2],
1240             myAddress[3], myAddress[4], myAddress[5]);
1241
1242#if defined(DEBUG) && (DOSX & PHARLAP)
1243  if (writeInfo)
1244  {
1245    DWORD    rAdr = realBase + (WORD)&PktReceiver;
1246    unsigned sel, ofs;
1247
1248    printf ("\nReceiver at   %04X:%04X\n", RP_SEG(rAdr),    RP_OFF(rAdr));
1249    printf ("Realbase    = %04X:%04X\n",   RP_SEG(realBase),RP_OFF(realBase));
1250
1251    sel = _FP_SEG (protBase);
1252    ofs = _FP_OFF (protBase);
1253    printf ("Protbase    = %04X:%08X\n", sel,ofs);
1254    printf ("RealSeg     = %04X\n", realSeg);
1255
1256    sel = _FP_SEG (rxOutOfsFp);
1257    ofs = _FP_OFF (rxOutOfsFp);
1258    printf ("rxOutOfsFp  = %04X:%08X\n", sel,ofs);
1259
1260    sel = _FP_SEG (rxInOfsFp);
1261    ofs = _FP_OFF (rxInOfsFp);
1262    printf ("rxInOfsFp   = %04X:%08X\n", sel,ofs);
1263
1264    printf ("Ready: *rxOutOfsFp = %04X *rxInOfsFp = %04X\n",
1265            *rxOutOfsFp, *rxInOfsFp);
1266
1267    PktQueueBusy (TRUE);
1268    printf ("Busy:  *rxOutOfsFp = %04X *rxInOfsFp = %04X\n",
1269            *rxOutOfsFp, *rxInOfsFp);
1270  }
1271#endif
1272
1273  memset (&pktStat, 0, sizeof(pktStat));  /* clear statistics */
1274  PktQueueBusy (TRUE);
1275  return (TRUE);
1276}
1277
1278
1279/*
1280 * DPMI functions only for Watcom + DOS4GW extenders
1281 */
1282#if (DOSX & DOS4GW)
1283LOCAL DWORD dpmi_get_real_vector (int intr)
1284{
1285  union REGS r;
1286
1287  r.x.eax = 0x200;
1288  r.x.ebx = (DWORD) intr;
1289  int386 (0x31, &r, &r);
1290  return ((r.w.cx << 4) + r.w.dx);
1291}
1292
1293LOCAL WORD dpmi_real_malloc (int size, WORD *selector)
1294{
1295  union REGS r;
1296
1297  r.x.eax = 0x0100;             /* DPMI allocate DOS memory */
1298  r.x.ebx = (size + 15) / 16;   /* Number of paragraphs requested */
1299  int386 (0x31, &r, &r);
1300  if (r.w.cflag & 1)
1301     return (0);
1302
1303  *selector = r.w.dx;
1304  return (r.w.ax);              /* Return segment address */
1305}
1306
1307LOCAL void dpmi_real_free (WORD selector)
1308{
1309  union REGS r;
1310
1311  r.x.eax = 0x101;              /* DPMI free DOS memory */
1312  r.x.ebx = selector;           /* Selector to free */
1313  int386 (0x31, &r, &r);
1314}
1315#endif
1316
1317
1318#if defined(DOSX) && (DOSX & PHARLAP)
1319/*
1320 * Description:
1321 *     This routine allocates conventional memory for the specified block
1322 *     of code (which must be within the first 64K of the protected mode
1323 *     program segment) and copies the code to it.
1324 *
1325 *     The caller should free up the conventional memory block when it
1326 *     is done with the conventional memory.
1327 *
1328 *     NOTE THIS ROUTINE REQUIRES 386|DOS-EXTENDER 3.0 OR LATER.
1329 *
1330 * Calling arguments:
1331 *     start_offs      start of real mode code in program segment
1332 *     end_offs        1 byte past end of real mode code in program segment
1333 *     real_basep      returned;  real mode ptr to use as a base for the
1334 *                        real mode code (eg, to get the real mode FAR
1335 *                        addr of a function foo(), take
1336 *                        real_basep + (ULONG) foo).
1337 *                        This pointer is constructed such that
1338 *                        offsets within the real mode segment are
1339 *                        the same as the link-time offsets in the
1340 *                        protected mode program segment
1341 *     prot_basep      returned;  prot mode ptr to use as a base for getting
1342 *                        to the conventional memory, also constructed
1343 *                        so that adding the prot mode offset of a
1344 *                        function or variable to the base gets you a
1345 *                        ptr to the function or variable in the
1346 *                        conventional memory block.
1347 *     rmem_adrp       returned;  real mode para addr of allocated
1348 *                        conventional memory block, to be used to free
1349 *                        up the conventional memory when done.  DO NOT
1350 *                        USE THIS TO CONSTRUCT A REAL MODE PTR, USE
1351 *                        REAL_BASEP INSTEAD SO THAT OFFSETS WORK OUT
1352 *                        CORRECTLY.
1353 *
1354 * Returned values:
1355 *     0      if error
1356 *     1      if success
1357 */
1358int RealCopy (ULONG    start_offs,
1359              ULONG    end_offs,
1360              REALPTR *real_basep,
1361              FARPTR  *prot_basep,
1362              USHORT  *rmem_adrp)
1363{
1364  ULONG   rm_base;    /* base real mode para addr for accessing */
1365                      /* allocated conventional memory          */
1366  UCHAR  *source;     /* source pointer for copy                */
1367  FARPTR  destin;     /* destination pointer for copy           */
1368  ULONG   len;        /* number of bytes to copy                */
1369  ULONG   temp;
1370  USHORT  stemp;
1371
1372  /* First check for valid inputs
1373   */
1374  if (start_offs >= end_offs || end_offs > 0x10000)
1375     return (FALSE);
1376
1377  /* Round start_offs down to a paragraph (16-byte) boundary so we can set up
1378   * the real mode pointer easily. Round up end_offs to make sure we allocate
1379   * enough paragraphs
1380   */
1381  start_offs &= ~15;
1382  end_offs = (15 + (end_offs << 4)) >> 4;
1383
1384  /* Allocate the conventional memory for our real mode code.  Remember to
1385   * round byte count UP to 16-byte paragraph size.  We alloc it
1386   * above the DOS data buffer so both the DOS data buffer and the appl
1387   * conventional mem block can still be resized.
1388   *
1389   * First just try to alloc it;  if we can't get it, shrink the appl mem
1390   * block down to the minimum, try to alloc the memory again, then grow the
1391   * appl mem block back to the maximum.  (Don't try to shrink the DOS data
1392   * buffer to free conventional memory;  it wouldn't be good for this routine
1393   * to have the possible side effect of making file I/O run slower.)
1394   */
1395  len = ((end_offs - start_offs) + 15) >> 4;
1396  if (_dx_real_above(len, rmem_adrp, &stemp) != _DOSE_NONE)
1397  {
1398    if (_dx_cmem_usage(0, 0, &temp, &temp) != _DOSE_NONE)
1399       return (FALSE);
1400
1401    if (_dx_real_above(len, rmem_adrp, &stemp) != _DOSE_NONE)
1402       *rmem_adrp = 0;
1403
1404    if (_dx_cmem_usage(0, 1, &temp, &temp) != _DOSE_NONE)
1405    {
1406      if (*rmem_adrp != 0)
1407         _dx_real_free (*rmem_adrp);
1408      return (FALSE);
1409    }
1410
1411    if (*rmem_adrp == 0)
1412       return (FALSE);
1413  }
1414
1415  /* Construct real mode & protected mode pointers to access the allocated
1416   * memory.  Note we know start_offs is aligned on a paragraph (16-byte)
1417   * boundary, because we rounded it down.
1418   *
1419   * We make the offsets come out rights by backing off the real mode selector
1420   * by start_offs.
1421   */
1422  rm_base = ((ULONG) *rmem_adrp) - (start_offs >> 4);
1423  RP_SET (*real_basep, 0, rm_base);
1424  FP_SET (*prot_basep, rm_base << 4, SS_DOSMEM);
1425
1426  /* Copy the real mode code/data to the allocated memory
1427   */
1428  source = (UCHAR *) start_offs;
1429  destin = *prot_basep;
1430  FP_SET (destin, FP_OFF(*prot_basep) + start_offs, FP_SEL(*prot_basep));
1431  len = end_offs - start_offs;
1432  WriteFarMem (destin, source, len);
1433
1434  return (TRUE);
1435}
1436#endif /* DOSX && (DOSX & PHARLAP) */
1437