-/*\r
- * File.........: pktdrvr.c\r
- *\r
- *\r
- * Created......: 26.Sept 1995\r
- *\r
- * Description..: Packet-driver interface for 16/32-bit C :\r
- * Borland C/C++ 3.0+ small/large model\r
- * Watcom C/C++ 11+, DOS4GW flat model\r
- * Metaware HighC 3.1+ and PharLap 386|DosX\r
- * GNU C/C++ 2.7+ and djgpp 2.x extender\r
- *\r
- * References...: PC/TCP Packet driver Specification. rev 1.09\r
- * FTP Software Inc.\r
- *\r
- */\r
-\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include <dos.h>\r
-\r
-#include "pcap-dos.h"\r
-#include "pcap-int.h"\r
-#include "msdos/pktdrvr.h"\r
-\r
-#if (DOSX)\r
-#define NUM_RX_BUF 32 /* # of buffers in Rx FIFO queue */\r
-#else\r
-#define NUM_RX_BUF 10\r
-#endif\r
-\r
-#define DIM(x) (sizeof((x)) / sizeof(x[0]))\r
-#define PUTS(s) do { \\r
- if (!pktInfo.quiet) \\r
- pktInfo.error ? \\r
- printf ("%s: %s\n", s, pktInfo.error) : \\r
- printf ("%s\n", pktInfo.error = s); \\r
- } while (0)\r
-\r
-#if defined(__HIGHC__)\r
- extern UINT _mwenv;\r
-\r
-#elif defined(__DJGPP__)\r
- #include <stddef.h>\r
- #include <dpmi.h>\r
- #include <go32.h>\r
- #include <pc.h>\r
- #include <sys/farptr.h>\r
-\r
-#elif defined(__WATCOMC__)\r
- #include <i86.h>\r
- #include <stddef.h>\r
- extern char _Extender;\r
-\r
-#else\r
- extern void far PktReceiver (void);\r
-#endif\r
-\r
-\r
-#if (DOSX & (DJGPP|DOS4GW))\r
- #include <sys/pack_on.h>\r
-\r
- struct DPMI_regs {\r
- DWORD r_di;\r
- DWORD r_si;\r
- DWORD r_bp;\r
- DWORD reserved;\r
- DWORD r_bx;\r
- DWORD r_dx;\r
- DWORD r_cx;\r
- DWORD r_ax;\r
- WORD r_flags;\r
- WORD r_es, r_ds, r_fs, r_gs;\r
- WORD r_ip, r_cs, r_sp, r_ss;\r
- };\r
-\r
- /* Data located in a real-mode segment. This becomes far at runtime\r
- */\r
- typedef struct { /* must match data/code in pkt_rx1.s */\r
- WORD _rxOutOfs;\r
- WORD _rxInOfs;\r
- DWORD _pktDrop;\r
- BYTE _pktTemp [20];\r
- TX_ELEMENT _pktTxBuf[1];\r
- RX_ELEMENT _pktRxBuf[NUM_RX_BUF];\r
- WORD _dummy[2]; /* screenSeg,newInOffset */\r
- BYTE _fanChars[4];\r
- WORD _fanIndex;\r
- BYTE _PktReceiver[15]; /* starts on a paragraph (16byte) */\r
- } PktRealStub;\r
- #include <sys/pack_off.h>\r
-\r
- static BYTE real_stub_array [] = {\r
- #include "pkt_stub.inc" /* generated opcode array */\r
- };\r
-\r
- #define rxOutOfs offsetof (PktRealStub,_rxOutOfs)\r
- #define rxInOfs offsetof (PktRealStub,_rxInOfs)\r
- #define PktReceiver offsetof (PktRealStub,_PktReceiver [para_skip])\r
- #define pktDrop offsetof (PktRealStub,_pktDrop)\r
- #define pktTemp offsetof (PktRealStub,_pktTemp)\r
- #define pktTxBuf offsetof (PktRealStub,_pktTxBuf)\r
- #define FIRST_RX_BUF offsetof (PktRealStub,_pktRxBuf [0])\r
- #define LAST_RX_BUF offsetof (PktRealStub,_pktRxBuf [NUM_RX_BUF-1])\r
-\r
-#else\r
- extern WORD rxOutOfs; /* offsets into pktRxBuf FIFO queue */\r
- extern WORD rxInOfs;\r
- extern DWORD pktDrop; /* # packets dropped in PktReceiver() */\r
- extern BYTE pktRxEnd; /* marks the end of r-mode code/data */\r
-\r
- extern RX_ELEMENT pktRxBuf [NUM_RX_BUF]; /* PktDrvr Rx buffers */\r
- extern TX_ELEMENT pktTxBuf; /* PktDrvr Tx buffer */\r
- extern char pktTemp[20]; /* PktDrvr temp area */\r
-\r
- #define FIRST_RX_BUF (WORD) &pktRxBuf [0]\r
- #define LAST_RX_BUF (WORD) &pktRxBuf [NUM_RX_BUF-1]\r
-#endif\r
-\r
-\r
-#ifdef __BORLANDC__ /* Use Borland's inline functions */\r
- #define memcpy __memcpy__\r
- #define memcmp __memcmp__\r
- #define memset __memset__\r
-#endif\r
-\r
-\r
-#if (DOSX & PHARLAP)\r
- extern void PktReceiver (void); /* in pkt_rx0.asm */\r
- static int RealCopy (ULONG, ULONG, REALPTR*, FARPTR*, USHORT*);\r
-\r
- #undef FP_SEG\r
- #undef FP_OFF\r
- #define FP_OFF(x) ((WORD)(x))\r
- #define FP_SEG(x) ((WORD)(realBase >> 16))\r
- #define DOS_ADDR(s,o) (((DWORD)(s) << 16) + (WORD)(o))\r
- #define r_ax eax\r
- #define r_bx ebx\r
- #define r_dx edx\r
- #define r_cx ecx\r
- #define r_si esi\r
- #define r_di edi\r
- #define r_ds ds\r
- #define r_es es\r
- LOCAL FARPTR protBase;\r
- LOCAL REALPTR realBase;\r
- LOCAL WORD realSeg; /* DOS para-address of allocated area */\r
- LOCAL SWI_REGS reg;\r
-\r
- static WORD _far *rxOutOfsFp, *rxInOfsFp;\r
-\r
-#elif (DOSX & DJGPP)\r
- static _go32_dpmi_seginfo rm_mem;\r
- static __dpmi_regs reg;\r
- static DWORD realBase;\r
- static int para_skip = 0;\r
-\r
- #define DOS_ADDR(s,o) (((WORD)(s) << 4) + (o))\r
- #define r_ax x.ax\r
- #define r_bx x.bx\r
- #define r_dx x.dx\r
- #define r_cx x.cx\r
- #define r_si x.si\r
- #define r_di x.di\r
- #define r_ds x.ds\r
- #define r_es x.es\r
-\r
-#elif (DOSX & DOS4GW)\r
- LOCAL struct DPMI_regs reg;\r
- LOCAL WORD rm_base_seg, rm_base_sel;\r
- LOCAL DWORD realBase;\r
- LOCAL int para_skip = 0;\r
-\r
- LOCAL DWORD dpmi_get_real_vector (int intr);\r
- LOCAL WORD dpmi_real_malloc (int size, WORD *selector);\r
- LOCAL void dpmi_real_free (WORD selector);\r
- #define DOS_ADDR(s,o) (((DWORD)(s) << 4) + (WORD)(o))\r
-\r
-#else /* real-mode Borland etc. */\r
- static struct {\r
- WORD r_ax, r_bx, r_cx, r_dx, r_bp;\r
- WORD r_si, r_di, r_ds, r_es, r_flags;\r
- } reg;\r
-#endif\r
-\r
-#ifdef __HIGHC__\r
- #pragma Alias (pktDrop, "_pktDrop")\r
- #pragma Alias (pktRxBuf, "_pktRxBuf")\r
- #pragma Alias (pktTxBuf, "_pktTxBuf")\r
- #pragma Alias (pktTemp, "_pktTemp")\r
- #pragma Alias (rxOutOfs, "_rxOutOfs")\r
- #pragma Alias (rxInOfs, "_rxInOfs")\r
- #pragma Alias (pktRxEnd, "_pktRxEnd")\r
- #pragma Alias (PktReceiver,"_PktReceiver")\r
-#endif\r
-\r
-\r
-PUBLIC PKT_STAT pktStat; /* statistics for packets */\r
-PUBLIC PKT_INFO pktInfo; /* packet-driver information */\r
-\r
-PUBLIC PKT_RX_MODE receiveMode = PDRX_DIRECT;\r
-PUBLIC ETHER myAddress = { 0, 0, 0, 0, 0, 0 };\r
-PUBLIC ETHER ethBroadcast = { 255,255,255,255,255,255 };\r
-\r
-LOCAL struct { /* internal statistics */\r
- DWORD tooSmall; /* size < ETH_MIN */\r
- DWORD tooLarge; /* size > ETH_MAX */\r
- DWORD badSync; /* count_1 != count_2 */\r
- DWORD wrongHandle; /* upcall to wrong handle */\r
- } intStat; \r
-\r
-/***************************************************************************/\r
-\r
-PUBLIC const char *PktGetErrorStr (int errNum)\r
-{\r
- static const char *errStr[] = {\r
- "",\r
- "Invalid handle number",\r
- "No interfaces of specified class found",\r
- "No interfaces of specified type found",\r
- "No interfaces of specified number found",\r
- "Bad packet type specified",\r
- "Interface does not support multicast",\r
- "Packet driver cannot terminate",\r
- "Invalid receiver mode specified",\r
- "Insufficient memory space",\r
- "Type previously accessed, and not released",\r
- "Command out of range, or not implemented",\r
- "Cannot send packet (usually hardware error)",\r
- "Cannot change hardware address ( > 1 handle open)",\r
- "Hardware address has bad length or format",\r
- "Cannot reset interface (more than 1 handle open)",\r
- "Bad Check-sum",\r
- "Bad size",\r
- "Bad sync" ,\r
- "Source hit"\r
- };\r
-\r
- if (errNum < 0 || errNum >= DIM(errStr))\r
- return ("Unknown driver error.");\r
- return (errStr [errNum]);\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-PUBLIC const char *PktGetClassName (WORD class)\r
-{\r
- switch (class)\r
- { \r
- case PD_ETHER:\r
- return ("DIX-Ether");\r
- case PD_PRONET10:\r
- return ("ProNET-10");\r
- case PD_IEEE8025:\r
- return ("IEEE 802.5");\r
- case PD_OMNINET:\r
- return ("OmniNet");\r
- case PD_APPLETALK:\r
- return ("AppleTalk");\r
- case PD_SLIP:\r
- return ("SLIP");\r
- case PD_STARTLAN:\r
- return ("StartLAN");\r
- case PD_ARCNET:\r
- return ("ArcNet");\r
- case PD_AX25:\r
- return ("AX.25");\r
- case PD_KISS:\r
- return ("KISS");\r
- case PD_IEEE8023_2:\r
- return ("IEEE 802.3 w/802.2 hdr");\r
- case PD_FDDI8022:\r
- return ("FDDI w/802.2 hdr");\r
- case PD_X25:\r
- return ("X.25");\r
- case PD_LANstar:\r
- return ("LANstar");\r
- case PD_PPP:\r
- return ("PPP");\r
- default:\r
- return ("unknown");\r
- }\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-PUBLIC char const *PktRXmodeStr (PKT_RX_MODE mode)\r
-{\r
- static const char *modeStr [] = {\r
- "Receiver turned off",\r
- "Receive only directly addressed packets",\r
- "Receive direct & broadcast packets",\r
- "Receive direct,broadcast and limited multicast packets",\r
- "Receive direct,broadcast and all multicast packets",\r
- "Receive all packets (promiscuouos mode)"\r
- };\r
-\r
- if (mode > DIM(modeStr))\r
- return ("??");\r
- return (modeStr [mode-1]);\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-LOCAL __inline BOOL PktInterrupt (void)\r
-{\r
- BOOL okay;\r
-\r
-#if (DOSX & PHARLAP)\r
- _dx_real_int ((UINT)pktInfo.intr, ®);\r
- okay = ((reg.flags & 1) == 0); /* OK if carry clear */\r
-\r
-#elif (DOSX & DJGPP)\r
- __dpmi_int ((int)pktInfo.intr, ®);\r
- okay = ((reg.x.flags & 1) == 0);\r
-\r
-#elif (DOSX & DOS4GW)\r
- union REGS r;\r
- struct SREGS s;\r
-\r
- memset (&r, 0, sizeof(r));\r
- segread (&s);\r
- r.w.ax = 0x300;\r
- r.x.ebx = pktInfo.intr;\r
- r.w.cx = 0;\r
- s.es = FP_SEG (®);\r
- r.x.edi = FP_OFF (®);\r
- reg.r_flags = 0;\r
- reg.r_ss = reg.r_sp = 0; /* DPMI host provides stack */\r
-\r
- int386x (0x31, &r, &r, &s);\r
- okay = (!r.w.cflag);\r
-\r
-#else\r
- reg.r_flags = 0;\r
- intr (pktInfo.intr, (struct REGPACK*)®);\r
- okay = ((reg.r_flags & 1) == 0);\r
-#endif\r
-\r
- if (okay)\r
- pktInfo.error = NULL;\r
- else pktInfo.error = PktGetErrorStr (reg.r_dx >> 8);\r
- return (okay);\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-/*\r
- * Search for packet driver at interrupt 60h through 80h. If ASCIIZ\r
- * string "PKT DRVR" found at offset 3 in the interrupt handler, return\r
- * interrupt number, else return zero in pktInfo.intr\r
- */\r
-PUBLIC BOOL PktSearchDriver (void)\r
-{\r
- BYTE intr = 0x20;\r
- BOOL found = FALSE;\r
-\r
- while (!found && intr < 0xFF)\r
- {\r
- static char str[12]; /* 3 + strlen("PKT DRVR") */\r
- static char pktStr[9] = "PKT DRVR"; /* ASCIIZ string at ofs 3 */\r
- DWORD rp; /* in interrupt routine */\r
-\r
-#if (DOSX & PHARLAP)\r
- _dx_rmiv_get (intr, &rp);\r
- ReadRealMem (&str, (REALPTR)rp, sizeof(str));\r
-\r
-#elif (DOSX & DJGPP)\r
- __dpmi_raddr realAdr;\r
- __dpmi_get_real_mode_interrupt_vector (intr, &realAdr);\r
- rp = (realAdr.segment << 4) + realAdr.offset16;\r
- dosmemget (rp, sizeof(str), &str);\r
-\r
-#elif (DOSX & DOS4GW)\r
- rp = dpmi_get_real_vector (intr);\r
- memcpy (&str, (void*)rp, sizeof(str));\r
-\r
-#else\r
- _fmemcpy (&str, getvect(intr), sizeof(str));\r
-#endif\r
-\r
- found = memcmp (&str[3],&pktStr,sizeof(pktStr)) == 0;\r
- intr++;\r
- }\r
- pktInfo.intr = (found ? intr-1 : 0);\r
- return (found);\r
-}\r
-\r
-\r
-/**************************************************************************/\r
-\r
-static BOOL PktSetAccess (void)\r
-{\r
- reg.r_ax = 0x0200 + pktInfo.class;\r
- reg.r_bx = 0xFFFF;\r
- reg.r_dx = 0;\r
- reg.r_cx = 0;\r
-\r
-#if (DOSX & PHARLAP)\r
- reg.ds = 0;\r
- reg.esi = 0;\r
- reg.es = RP_SEG (realBase);\r
- reg.edi = (WORD) &PktReceiver;\r
-\r
-#elif (DOSX & DJGPP)\r
- reg.x.ds = 0;\r
- reg.x.si = 0;\r
- reg.x.es = rm_mem.rm_segment;\r
- reg.x.di = PktReceiver;\r
-\r
-#elif (DOSX & DOS4GW)\r
- reg.r_ds = 0;\r
- reg.r_si = 0;\r
- reg.r_es = rm_base_seg;\r
- reg.r_di = PktReceiver;\r
-\r
-#else\r
- reg.r_ds = 0;\r
- reg.r_si = 0;\r
- reg.r_es = FP_SEG (&PktReceiver);\r
- reg.r_di = FP_OFF (&PktReceiver);\r
-#endif\r
-\r
- if (!PktInterrupt())\r
- return (FALSE);\r
-\r
- pktInfo.handle = reg.r_ax;\r
- return (TRUE);\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-PUBLIC BOOL PktReleaseHandle (WORD handle)\r
-{\r
- reg.r_ax = 0x0300;\r
- reg.r_bx = handle;\r
- return PktInterrupt();\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-PUBLIC BOOL PktTransmit (const void *eth, int len)\r
-{\r
- if (len > ETH_MTU)\r
- return (FALSE);\r
-\r
- reg.r_ax = 0x0400; /* Function 4, send pkt */\r
- reg.r_cx = len; /* total size of frame */\r
-\r
-#if (DOSX & DJGPP)\r
- dosmemput (eth, len, realBase+pktTxBuf);\r
- reg.x.ds = rm_mem.rm_segment; /* DOS data segment and */\r
- reg.x.si = pktTxBuf; /* DOS offset to buffer */\r
-\r
-#elif (DOSX & DOS4GW)\r
- memcpy ((void*)(realBase+pktTxBuf), eth, len);\r
- reg.r_ds = rm_base_seg;\r
- reg.r_si = pktTxBuf;\r
-\r
-#elif (DOSX & PHARLAP)\r
- memcpy (&pktTxBuf, eth, len);\r
- reg.r_ds = FP_SEG (&pktTxBuf);\r
- reg.r_si = FP_OFF (&pktTxBuf);\r
-\r
-#else\r
- reg.r_ds = FP_SEG (eth);\r
- reg.r_si = FP_OFF (eth);\r
-#endif\r
-\r
- return PktInterrupt();\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-#if (DOSX & (DJGPP|DOS4GW))\r
-LOCAL __inline BOOL CheckElement (RX_ELEMENT *rx)\r
-#else\r
-LOCAL __inline BOOL CheckElement (RX_ELEMENT _far *rx)\r
-#endif\r
-{\r
- WORD count_1, count_2;\r
-\r
- /*\r
- * We got an upcall to the same RMCB with wrong handle.\r
- * This can happen if we failed to release handle at program exit\r
- */\r
- if (rx->handle != pktInfo.handle)\r
- {\r
- pktInfo.error = "Wrong handle";\r
- intStat.wrongHandle++;\r
- PktReleaseHandle (rx->handle);\r
- return (FALSE);\r
- }\r
- count_1 = rx->firstCount;\r
- count_2 = rx->secondCount;\r
-\r
- if (count_1 != count_2)\r
- {\r
- pktInfo.error = "Bad sync";\r
- intStat.badSync++;\r
- return (FALSE);\r
- }\r
- if (count_1 > ETH_MAX)\r
- {\r
- pktInfo.error = "Large esize";\r
- intStat.tooLarge++;\r
- return (FALSE);\r
- }\r
-#if 0\r
- if (count_1 < ETH_MIN)\r
- {\r
- pktInfo.error = "Small esize";\r
- intStat.tooSmall++;\r
- return (FALSE);\r
- }\r
-#endif\r
- return (TRUE);\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-PUBLIC BOOL PktTerminHandle (WORD handle)\r
-{\r
- reg.r_ax = 0x0500;\r
- reg.r_bx = handle;\r
- return PktInterrupt();\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-PUBLIC BOOL PktResetInterface (WORD handle)\r
-{\r
- reg.r_ax = 0x0700;\r
- reg.r_bx = handle;\r
- return PktInterrupt();\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-PUBLIC BOOL PktSetReceiverMode (PKT_RX_MODE mode)\r
-{\r
- if (pktInfo.class == PD_SLIP || pktInfo.class == PD_PPP)\r
- return (TRUE);\r
-\r
- reg.r_ax = 0x1400;\r
- reg.r_bx = pktInfo.handle;\r
- reg.r_cx = (WORD)mode;\r
-\r
- if (!PktInterrupt())\r
- return (FALSE);\r
-\r
- receiveMode = mode;\r
- return (TRUE);\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-PUBLIC BOOL PktGetReceiverMode (PKT_RX_MODE *mode)\r
-{\r
- reg.r_ax = 0x1500;\r
- reg.r_bx = pktInfo.handle;\r
-\r
- if (!PktInterrupt())\r
- return (FALSE);\r
-\r
- *mode = reg.r_ax;\r
- return (TRUE);\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-static PKT_STAT initialStat; /* statistics at startup */\r
-static BOOL resetStat = FALSE; /* statistics reset ? */\r
-\r
-PUBLIC BOOL PktGetStatistics (WORD handle)\r
-{\r
- reg.r_ax = 0x1800;\r
- reg.r_bx = handle;\r
-\r
- if (!PktInterrupt())\r
- return (FALSE);\r
-\r
-#if (DOSX & PHARLAP)\r
- ReadRealMem (&pktStat, DOS_ADDR(reg.ds,reg.esi), sizeof(pktStat));\r
-\r
-#elif (DOSX & DJGPP)\r
- dosmemget (DOS_ADDR(reg.x.ds,reg.x.si), sizeof(pktStat), &pktStat);\r
-\r
-#elif (DOSX & DOS4GW)\r
- memcpy (&pktStat, (void*)DOS_ADDR(reg.r_ds,reg.r_si), sizeof(pktStat));\r
-\r
-#else\r
- _fmemcpy (&pktStat, MK_FP(reg.r_ds,reg.r_si), sizeof(pktStat));\r
-#endif\r
-\r
- return (TRUE);\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-PUBLIC BOOL PktSessStatistics (WORD handle)\r
-{\r
- if (!PktGetStatistics(pktInfo.handle))\r
- return (FALSE);\r
-\r
- if (resetStat)\r
- {\r
- pktStat.inPackets -= initialStat.inPackets;\r
- pktStat.outPackets -= initialStat.outPackets;\r
- pktStat.inBytes -= initialStat.inBytes;\r
- pktStat.outBytes -= initialStat.outBytes;\r
- pktStat.inErrors -= initialStat.inErrors;\r
- pktStat.outErrors -= initialStat.outErrors;\r
- pktStat.outErrors -= initialStat.outErrors;\r
- pktStat.lost -= initialStat.lost;\r
- }\r
- return (TRUE);\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-PUBLIC BOOL PktResetStatistics (WORD handle)\r
-{\r
- if (!PktGetStatistics(pktInfo.handle))\r
- return (FALSE);\r
-\r
- memcpy (&initialStat, &pktStat, sizeof(initialStat));\r
- resetStat = TRUE;\r
- return (TRUE);\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-PUBLIC BOOL PktGetAddress (ETHER *addr)\r
-{\r
- reg.r_ax = 0x0600;\r
- reg.r_bx = pktInfo.handle;\r
- reg.r_cx = sizeof (*addr);\r
-\r
-#if (DOSX & DJGPP)\r
- reg.x.es = rm_mem.rm_segment;\r
- reg.x.di = pktTemp;\r
-#elif (DOSX & DOS4GW)\r
- reg.r_es = rm_base_seg;\r
- reg.r_di = pktTemp;\r
-#else\r
- reg.r_es = FP_SEG (&pktTemp);\r
- reg.r_di = FP_OFF (&pktTemp); /* ES:DI = address for result */\r
-#endif\r
-\r
- if (!PktInterrupt())\r
- return (FALSE);\r
-\r
-#if (DOSX & PHARLAP)\r
- ReadRealMem (addr, realBase + (WORD)&pktTemp, sizeof(*addr));\r
-\r
-#elif (DOSX & DJGPP)\r
- dosmemget (realBase+pktTemp, sizeof(*addr), addr);\r
-\r
-#elif (DOSX & DOS4GW)\r
- memcpy (addr, (void*)(realBase+pktTemp), sizeof(*addr));\r
-\r
-#else\r
- memcpy ((void*)addr, &pktTemp, sizeof(*addr));\r
-#endif\r
-\r
- return (TRUE);\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-PUBLIC BOOL PktSetAddress (const ETHER *addr)\r
-{\r
- /* copy addr to real-mode scrath area */\r
-\r
-#if (DOSX & PHARLAP)\r
- WriteRealMem (realBase + (WORD)&pktTemp, (void*)addr, sizeof(*addr));\r
-\r
-#elif (DOSX & DJGPP)\r
- dosmemput (addr, sizeof(*addr), realBase+pktTemp);\r
-\r
-#elif (DOSX & DOS4GW)\r
- memcpy ((void*)(realBase+pktTemp), addr, sizeof(*addr));\r
-\r
-#else\r
- memcpy (&pktTemp, (void*)addr, sizeof(*addr));\r
-#endif\r
-\r
- reg.r_ax = 0x1900;\r
- reg.r_cx = sizeof (*addr); /* address length */\r
-\r
-#if (DOSX & DJGPP)\r
- reg.x.es = rm_mem.rm_segment; /* DOS offset to param */\r
- reg.x.di = pktTemp; /* DOS segment to param */\r
-#elif (DOSX & DOS4GW)\r
- reg.r_es = rm_base_seg;\r
- reg.r_di = pktTemp;\r
-#else\r
- reg.r_es = FP_SEG (&pktTemp);\r
- reg.r_di = FP_OFF (&pktTemp);\r
-#endif\r
-\r
- return PktInterrupt();\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-PUBLIC BOOL PktGetDriverInfo (void)\r
-{\r
- pktInfo.majVer = 0;\r
- pktInfo.minVer = 0;\r
- memset (&pktInfo.name, 0, sizeof(pktInfo.name));\r
- reg.r_ax = 0x01FF;\r
- reg.r_bx = 0;\r
-\r
- if (!PktInterrupt())\r
- return (FALSE);\r
-\r
- pktInfo.number = reg.r_cx & 0xFF;\r
- pktInfo.class = reg.r_cx >> 8;\r
-#if 0\r
- pktInfo.minVer = reg.r_bx % 10;\r
- pktInfo.majVer = reg.r_bx / 10;\r
-#else\r
- pktInfo.majVer = reg.r_bx; // !!\r
-#endif\r
- pktInfo.funcs = reg.r_ax & 0xFF;\r
- pktInfo.type = reg.r_dx & 0xFF;\r
-\r
-#if (DOSX & PHARLAP)\r
- ReadRealMem (&pktInfo.name, DOS_ADDR(reg.ds,reg.esi), sizeof(pktInfo.name));\r
-\r
-#elif (DOSX & DJGPP)\r
- dosmemget (DOS_ADDR(reg.x.ds,reg.x.si), sizeof(pktInfo.name), &pktInfo.name);\r
-\r
-#elif (DOSX & DOS4GW)\r
- memcpy (&pktInfo.name, (void*)DOS_ADDR(reg.r_ds,reg.r_si), sizeof(pktInfo.name));\r
-\r
-#else\r
- _fmemcpy (&pktInfo.name, MK_FP(reg.r_ds,reg.r_si), sizeof(pktInfo.name));\r
-#endif\r
- return (TRUE);\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-PUBLIC BOOL PktGetDriverParam (void)\r
-{\r
- reg.r_ax = 0x0A00;\r
-\r
- if (!PktInterrupt())\r
- return (FALSE);\r
-\r
-#if (DOSX & PHARLAP)\r
- ReadRealMem (&pktInfo.majVer, DOS_ADDR(reg.es,reg.edi), PKT_PARAM_SIZE);\r
-\r
-#elif (DOSX & DJGPP)\r
- dosmemget (DOS_ADDR(reg.x.es,reg.x.di), PKT_PARAM_SIZE, &pktInfo.majVer);\r
-\r
-#elif (DOSX & DOS4GW)\r
- memcpy (&pktInfo.majVer, (void*)DOS_ADDR(reg.r_es,reg.r_di), PKT_PARAM_SIZE);\r
-\r
-#else\r
- _fmemcpy (&pktInfo.majVer, MK_FP(reg.r_es,reg.r_di), PKT_PARAM_SIZE);\r
-#endif\r
- return (TRUE);\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-#if (DOSX & PHARLAP)\r
- PUBLIC int PktReceive (BYTE *buf, int max)\r
- {\r
- WORD inOfs = *rxInOfsFp;\r
- WORD outOfs = *rxOutOfsFp;\r
-\r
- if (outOfs != inOfs)\r
- {\r
- RX_ELEMENT _far *head = (RX_ELEMENT _far*)(protBase+outOfs);\r
- int size, len = max;\r
-\r
- if (CheckElement(head))\r
- {\r
- size = min (head->firstCount, sizeof(RX_ELEMENT));\r
- len = min (size, max);\r
- _fmemcpy (buf, &head->destin, len);\r
- }\r
- else\r
- size = -1;\r
-\r
- outOfs += sizeof (RX_ELEMENT);\r
- if (outOfs > LAST_RX_BUF)\r
- outOfs = FIRST_RX_BUF;\r
- *rxOutOfsFp = outOfs;\r
- return (size);\r
- }\r
- return (0);\r
- }\r
-\r
- PUBLIC void PktQueueBusy (BOOL busy)\r
- {\r
- *rxOutOfsFp = busy ? (*rxInOfsFp + sizeof(RX_ELEMENT)) : *rxInOfsFp;\r
- if (*rxOutOfsFp > LAST_RX_BUF)\r
- *rxOutOfsFp = FIRST_RX_BUF;\r
- *(DWORD _far*)(protBase + (WORD)&pktDrop) = 0;\r
- }\r
-\r
- PUBLIC WORD PktBuffersUsed (void)\r
- {\r
- WORD inOfs = *rxInOfsFp;\r
- WORD outOfs = *rxOutOfsFp;\r
-\r
- if (inOfs >= outOfs)\r
- return (inOfs - outOfs) / sizeof(RX_ELEMENT);\r
- return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));\r
- }\r
-\r
- PUBLIC DWORD PktRxDropped (void)\r
- {\r
- return (*(DWORD _far*)(protBase + (WORD)&pktDrop));\r
- }\r
-\r
-#elif (DOSX & DJGPP)\r
- PUBLIC int PktReceive (BYTE *buf, int max)\r
- {\r
- WORD ofs = _farpeekw (_dos_ds, realBase+rxOutOfs);\r
-\r
- if (ofs != _farpeekw (_dos_ds, realBase+rxInOfs))\r
- {\r
- RX_ELEMENT head;\r
- int size, len = max;\r
-\r
- head.firstCount = _farpeekw (_dos_ds, realBase+ofs);\r
- head.secondCount = _farpeekw (_dos_ds, realBase+ofs+2);\r
- head.handle = _farpeekw (_dos_ds, realBase+ofs+4);\r
-\r
- if (CheckElement(&head))\r
- {\r
- size = min (head.firstCount, sizeof(RX_ELEMENT));\r
- len = min (size, max);\r
- dosmemget (realBase+ofs+6, len, buf);\r
- }\r
- else\r
- size = -1;\r
-\r
- ofs += sizeof (RX_ELEMENT);\r
- if (ofs > LAST_RX_BUF)\r
- _farpokew (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);\r
- else _farpokew (_dos_ds, realBase+rxOutOfs, ofs);\r
- return (size);\r
- }\r
- return (0);\r
- }\r
-\r
- PUBLIC void PktQueueBusy (BOOL busy)\r
- {\r
- WORD ofs;\r
-\r
- disable();\r
- ofs = _farpeekw (_dos_ds, realBase+rxInOfs);\r
- if (busy)\r
- ofs += sizeof (RX_ELEMENT);\r
-\r
- if (ofs > LAST_RX_BUF)\r
- _farpokew (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);\r
- else _farpokew (_dos_ds, realBase+rxOutOfs, ofs);\r
- _farpokel (_dos_ds, realBase+pktDrop, 0UL);\r
- enable();\r
- }\r
-\r
- PUBLIC WORD PktBuffersUsed (void)\r
- {\r
- WORD inOfs, outOfs;\r
-\r
- disable();\r
- inOfs = _farpeekw (_dos_ds, realBase+rxInOfs);\r
- outOfs = _farpeekw (_dos_ds, realBase+rxOutOfs);\r
- enable();\r
- if (inOfs >= outOfs)\r
- return (inOfs - outOfs) / sizeof(RX_ELEMENT);\r
- return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));\r
- }\r
-\r
- PUBLIC DWORD PktRxDropped (void)\r
- {\r
- return _farpeekl (_dos_ds, realBase+pktDrop);\r
- }\r
-\r
-#elif (DOSX & DOS4GW)\r
- PUBLIC int PktReceive (BYTE *buf, int max)\r
- {\r
- WORD ofs = *(WORD*) (realBase+rxOutOfs);\r
-\r
- if (ofs != *(WORD*) (realBase+rxInOfs))\r
- {\r
- RX_ELEMENT head;\r
- int size, len = max;\r
-\r
- head.firstCount = *(WORD*) (realBase+ofs);\r
- head.secondCount = *(WORD*) (realBase+ofs+2);\r
- head.handle = *(WORD*) (realBase+ofs+4);\r
-\r
- if (CheckElement(&head))\r
- {\r
- size = min (head.firstCount, sizeof(RX_ELEMENT));\r
- len = min (size, max);\r
- memcpy (buf, (const void*)(realBase+ofs+6), len);\r
- }\r
- else\r
- size = -1;\r
-\r
- ofs += sizeof (RX_ELEMENT);\r
- if (ofs > LAST_RX_BUF)\r
- *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;\r
- else *(WORD*) (realBase+rxOutOfs) = ofs;\r
- return (size);\r
- }\r
- return (0);\r
- }\r
-\r
- PUBLIC void PktQueueBusy (BOOL busy)\r
- {\r
- WORD ofs;\r
-\r
- _disable();\r
- ofs = *(WORD*) (realBase+rxInOfs);\r
- if (busy)\r
- ofs += sizeof (RX_ELEMENT);\r
-\r
- if (ofs > LAST_RX_BUF)\r
- *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;\r
- else *(WORD*) (realBase+rxOutOfs) = ofs;\r
- *(DWORD*) (realBase+pktDrop) = 0UL;\r
- _enable();\r
- }\r
-\r
- PUBLIC WORD PktBuffersUsed (void)\r
- {\r
- WORD inOfs, outOfs;\r
-\r
- _disable();\r
- inOfs = *(WORD*) (realBase+rxInOfs);\r
- outOfs = *(WORD*) (realBase+rxOutOfs);\r
- _enable();\r
- if (inOfs >= outOfs)\r
- return (inOfs - outOfs) / sizeof(RX_ELEMENT);\r
- return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));\r
- }\r
-\r
- PUBLIC DWORD PktRxDropped (void)\r
- {\r
- return *(DWORD*) (realBase+pktDrop);\r
- }\r
-\r
-#else /* real-mode small/large model */\r
-\r
- PUBLIC int PktReceive (BYTE *buf, int max)\r
- {\r
- if (rxOutOfs != rxInOfs)\r
- {\r
- RX_ELEMENT far *head = (RX_ELEMENT far*) MK_FP (_DS,rxOutOfs);\r
- int size, len = max;\r
-\r
- if (CheckElement(head))\r
- {\r
- size = min (head->firstCount, sizeof(RX_ELEMENT));\r
- len = min (size, max);\r
- _fmemcpy (buf, &head->destin, len);\r
- }\r
- else\r
- size = -1;\r
-\r
- rxOutOfs += sizeof (RX_ELEMENT);\r
- if (rxOutOfs > LAST_RX_BUF)\r
- rxOutOfs = FIRST_RX_BUF;\r
- return (size);\r
- }\r
- return (0);\r
- }\r
-\r
- PUBLIC void PktQueueBusy (BOOL busy)\r
- {\r
- rxOutOfs = busy ? (rxInOfs + sizeof(RX_ELEMENT)) : rxInOfs;\r
- if (rxOutOfs > LAST_RX_BUF)\r
- rxOutOfs = FIRST_RX_BUF;\r
- pktDrop = 0L;\r
- }\r
-\r
- PUBLIC WORD PktBuffersUsed (void)\r
- {\r
- WORD inOfs = rxInOfs;\r
- WORD outOfs = rxOutOfs;\r
-\r
- if (inOfs >= outOfs)\r
- return ((inOfs - outOfs) / sizeof(RX_ELEMENT));\r
- return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));\r
- }\r
-\r
- PUBLIC DWORD PktRxDropped (void)\r
- {\r
- return (pktDrop);\r
- }\r
-#endif\r
-\r
-/**************************************************************************/\r
-\r
-LOCAL __inline void PktFreeMem (void)\r
-{\r
-#if (DOSX & PHARLAP)\r
- if (realSeg)\r
- {\r
- _dx_real_free (realSeg);\r
- realSeg = 0;\r
- }\r
-#elif (DOSX & DJGPP)\r
- if (rm_mem.rm_segment)\r
- {\r
- unsigned ofs; /* clear the DOS-mem to prevent further upcalls */\r
-\r
- for (ofs = 0; ofs < 16 * rm_mem.size / 4; ofs += 4)\r
- _farpokel (_dos_ds, realBase + ofs, 0);\r
- _go32_dpmi_free_dos_memory (&rm_mem);\r
- rm_mem.rm_segment = 0;\r
- }\r
-#elif (DOSX & DOS4GW)\r
- if (rm_base_sel)\r
- {\r
- dpmi_real_free (rm_base_sel);\r
- rm_base_sel = 0;\r
- }\r
-#endif\r
-}\r
-\r
-/**************************************************************************/\r
-\r
-PUBLIC BOOL PktExitDriver (void)\r
-{ \r
- if (pktInfo.handle)\r
- {\r
- if (!PktSetReceiverMode(PDRX_BROADCAST))\r
- PUTS ("Error restoring receiver mode.");\r
-\r
- if (!PktReleaseHandle(pktInfo.handle))\r
- PUTS ("Error releasing PKT-DRVR handle.");\r
-\r
- PktFreeMem();\r
- pktInfo.handle = 0;\r
- }\r
-\r
- if (pcap_pkt_debug >= 1)\r
- printf ("Internal stats: too-small %lu, too-large %lu, bad-sync %lu, "\r
- "wrong-handle %lu\n",\r
- intStat.tooSmall, intStat.tooLarge,\r
- intStat.badSync, intStat.wrongHandle);\r
- return (TRUE);\r
-}\r
-\r
-#if (DOSX & (DJGPP|DOS4GW))\r
-static void dump_pkt_stub (void)\r
-{\r
- int i;\r
-\r
- fprintf (stderr, "PktReceiver %lu, pkt_stub[PktReceiver] =\n",\r
- PktReceiver);\r
- for (i = 0; i < 15; i++)\r
- fprintf (stderr, "%02X, ", real_stub_array[i+PktReceiver]);\r
- fputs ("\n", stderr);\r
-}\r
-#endif\r
-\r
-/*\r
- * Front end initialization routine\r
- */\r
-PUBLIC BOOL PktInitDriver (PKT_RX_MODE mode)\r
-{\r
- PKT_RX_MODE rxMode;\r
- BOOL writeInfo = (pcap_pkt_debug >= 3);\r
-\r
- pktInfo.quiet = (pcap_pkt_debug < 3);\r
-\r
-#if (DOSX & PHARLAP) && defined(__HIGHC__)\r
- if (_mwenv != 2)\r
- {\r
- fprintf (stderr, "Only Pharlap DOS extender supported.\n");\r
- return (FALSE);\r
- }\r
-#endif\r
-\r
-#if (DOSX & PHARLAP) && defined(__WATCOMC__)\r
- if (_Extender != 1)\r
- {\r
- fprintf (stderr, "Only DOS4GW style extenders supported.\n");\r
- return (FALSE);\r
- }\r
-#endif\r
-\r
- if (!PktSearchDriver())\r
- {\r
- PUTS ("Packet driver not found.");\r
- PktFreeMem();\r
- return (FALSE);\r
- }\r
-\r
- if (!PktGetDriverInfo())\r
- {\r
- PUTS ("Error getting pkt-drvr information.");\r
- PktFreeMem();\r
- return (FALSE);\r
- }\r
-\r
-#if (DOSX & PHARLAP)\r
- if (RealCopy((ULONG)&rxOutOfs, (ULONG)&pktRxEnd,\r
- &realBase, &protBase, (USHORT*)&realSeg))\r
- {\r
- rxOutOfsFp = (WORD _far *) (protBase + (WORD) &rxOutOfs);\r
- rxInOfsFp = (WORD _far *) (protBase + (WORD) &rxInOfs);\r
- *rxOutOfsFp = FIRST_RX_BUF;\r
- *rxInOfsFp = FIRST_RX_BUF;\r
- }\r
- else\r
- {\r
- PUTS ("Cannot allocate real-mode stub.");\r
- return (FALSE);\r
- }\r
-\r
-#elif (DOSX & (DJGPP|DOS4GW))\r
- if (sizeof(real_stub_array) > 0xFFFF)\r
- {\r
- fprintf (stderr, "`real_stub_array[]' too big.\n");\r
- return (FALSE);\r
- }\r
-#if (DOSX & DJGPP)\r
- rm_mem.size = (sizeof(real_stub_array) + 15) / 16;\r
-\r
- if (_go32_dpmi_allocate_dos_memory(&rm_mem) || rm_mem.rm_offset != 0)\r
- {\r
- PUTS ("real-mode init failed.");\r
- return (FALSE);\r
- }\r
- realBase = (rm_mem.rm_segment << 4);\r
- dosmemput (&real_stub_array, sizeof(real_stub_array), realBase);\r
- _farpokel (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);\r
- _farpokel (_dos_ds, realBase+rxInOfs, FIRST_RX_BUF);\r
-\r
-#elif (DOSX & DOS4GW)\r
- rm_base_seg = dpmi_real_malloc (sizeof(real_stub_array), &rm_base_sel);\r
- if (!rm_base_seg)\r
- {\r
- PUTS ("real-mode init failed.");\r
- return (FALSE);\r
- }\r
- realBase = (rm_base_seg << 4);\r
- memcpy ((void*)realBase, &real_stub_array, sizeof(real_stub_array));\r
- *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;\r
- *(WORD*) (realBase+rxInOfs) = FIRST_RX_BUF;\r
-\r
-#endif\r
- {\r
- int pushf = PktReceiver;\r
-\r
- while (real_stub_array[pushf++] != 0x9C && /* pushf */\r
- real_stub_array[pushf] != 0xFA) /* cli */\r
- {\r
- if (++para_skip > 16)\r
- {\r
- fprintf (stderr, "Something wrong with `pkt_stub.inc'.\n");\r
- para_skip = 0;\r
- dump_pkt_stub();\r
- return (FALSE);\r
- }\r
- }\r
- if (*(WORD*)(real_stub_array + offsetof(PktRealStub,_dummy)) != 0xB800)\r
- {\r
- fprintf (stderr, "`real_stub_array[]' is misaligned.\n");\r
- return (FALSE);\r
- }\r
- }\r
-\r
- if (pcap_pkt_debug > 2)\r
- dump_pkt_stub();\r
-\r
-#else\r
- rxOutOfs = FIRST_RX_BUF;\r
- rxInOfs = FIRST_RX_BUF;\r
-#endif\r
-\r
- if (!PktSetAccess())\r
- {\r
- PUTS ("Error setting pkt-drvr access.");\r
- PktFreeMem();\r
- return (FALSE);\r
- }\r
-\r
- if (!PktGetAddress(&myAddress))\r
- {\r
- PUTS ("Error fetching adapter address.");\r
- PktFreeMem();\r
- return (FALSE);\r
- }\r
-\r
- if (!PktSetReceiverMode(mode))\r
- {\r
- PUTS ("Error setting receiver mode.");\r
- PktFreeMem();\r
- return (FALSE);\r
- }\r
-\r
- if (!PktGetReceiverMode(&rxMode))\r
- {\r
- PUTS ("Error getting receiver mode.");\r
- PktFreeMem();\r
- return (FALSE);\r
- }\r
-\r
- if (writeInfo)\r
- printf ("Pkt-driver information:\n"\r
- " Version : %d.%d\n"\r
- " Name : %.15s\n"\r
- " Class : %u (%s)\n"\r
- " Type : %u\n"\r
- " Number : %u\n"\r
- " Funcs : %u\n"\r
- " Intr : %Xh\n"\r
- " Handle : %u\n"\r
- " Extended : %s\n"\r
- " Hi-perf : %s\n"\r
- " RX mode : %s\n"\r
- " Eth-addr : %02X:%02X:%02X:%02X:%02X:%02X\n",\r
-\r
- pktInfo.majVer, pktInfo.minVer, pktInfo.name,\r
- pktInfo.class, PktGetClassName(pktInfo.class),\r
- pktInfo.type, pktInfo.number,\r
- pktInfo.funcs, pktInfo.intr, pktInfo.handle,\r
- pktInfo.funcs == 2 || pktInfo.funcs == 6 ? "Yes" : "No",\r
- pktInfo.funcs == 5 || pktInfo.funcs == 6 ? "Yes" : "No",\r
- PktRXmodeStr(rxMode),\r
- myAddress[0], myAddress[1], myAddress[2],\r
- myAddress[3], myAddress[4], myAddress[5]);\r
-\r
-#if defined(DEBUG) && (DOSX & PHARLAP)\r
- if (writeInfo)\r
- {\r
- DWORD rAdr = realBase + (WORD)&PktReceiver;\r
- unsigned sel, ofs;\r
-\r
- printf ("\nReceiver at %04X:%04X\n", RP_SEG(rAdr), RP_OFF(rAdr));\r
- printf ("Realbase = %04X:%04X\n", RP_SEG(realBase),RP_OFF(realBase));\r
-\r
- sel = _FP_SEG (protBase);\r
- ofs = _FP_OFF (protBase);\r
- printf ("Protbase = %04X:%08X\n", sel,ofs);\r
- printf ("RealSeg = %04X\n", realSeg);\r
-\r
- sel = _FP_SEG (rxOutOfsFp);\r
- ofs = _FP_OFF (rxOutOfsFp);\r
- printf ("rxOutOfsFp = %04X:%08X\n", sel,ofs);\r
-\r
- sel = _FP_SEG (rxInOfsFp);\r
- ofs = _FP_OFF (rxInOfsFp);\r
- printf ("rxInOfsFp = %04X:%08X\n", sel,ofs);\r
-\r
- printf ("Ready: *rxOutOfsFp = %04X *rxInOfsFp = %04X\n",\r
- *rxOutOfsFp, *rxInOfsFp);\r
-\r
- PktQueueBusy (TRUE);\r
- printf ("Busy: *rxOutOfsFp = %04X *rxInOfsFp = %04X\n",\r
- *rxOutOfsFp, *rxInOfsFp);\r
- }\r
-#endif\r
-\r
- memset (&pktStat, 0, sizeof(pktStat)); /* clear statistics */\r
- PktQueueBusy (TRUE);\r
- return (TRUE);\r
-}\r
-\r
-\r
-/*\r
- * DPMI functions only for Watcom + DOS4GW extenders\r
- */\r
-#if (DOSX & DOS4GW)\r
-LOCAL DWORD dpmi_get_real_vector (int intr)\r
-{\r
- union REGS r;\r
-\r
- r.x.eax = 0x200;\r
- r.x.ebx = (DWORD) intr;\r
- int386 (0x31, &r, &r);\r
- return ((r.w.cx << 4) + r.w.dx);\r
-}\r
-\r
-LOCAL WORD dpmi_real_malloc (int size, WORD *selector)\r
-{\r
- union REGS r;\r
-\r
- r.x.eax = 0x0100; /* DPMI allocate DOS memory */\r
- r.x.ebx = (size + 15) / 16; /* Number of paragraphs requested */\r
- int386 (0x31, &r, &r);\r
- if (r.w.cflag & 1)\r
- return (0);\r
-\r
- *selector = r.w.dx;\r
- return (r.w.ax); /* Return segment address */\r
-}\r
-\r
-LOCAL void dpmi_real_free (WORD selector)\r
-{\r
- union REGS r;\r
-\r
- r.x.eax = 0x101; /* DPMI free DOS memory */\r
- r.x.ebx = selector; /* Selector to free */\r
- int386 (0x31, &r, &r);\r
-}\r
-#endif\r
-\r
-\r
-#if defined(DOSX) && (DOSX & PHARLAP)\r
-/*\r
- * Description:\r
- * This routine allocates conventional memory for the specified block\r
- * of code (which must be within the first 64K of the protected mode\r
- * program segment) and copies the code to it.\r
- *\r
- * The caller should free up the conventional memory block when it\r
- * is done with the conventional memory.\r
- *\r
- * NOTE THIS ROUTINE REQUIRES 386|DOS-EXTENDER 3.0 OR LATER.\r
- *\r
- * Calling arguments:\r
- * start_offs start of real mode code in program segment\r
- * end_offs 1 byte past end of real mode code in program segment\r
- * real_basep returned; real mode ptr to use as a base for the\r
- * real mode code (eg, to get the real mode FAR\r
- * addr of a function foo(), take\r
- * real_basep + (ULONG) foo).\r
- * This pointer is constructed such that\r
- * offsets within the real mode segment are\r
- * the same as the link-time offsets in the\r
- * protected mode program segment\r
- * prot_basep returned; prot mode ptr to use as a base for getting\r
- * to the conventional memory, also constructed\r
- * so that adding the prot mode offset of a\r
- * function or variable to the base gets you a\r
- * ptr to the function or variable in the\r
- * conventional memory block.\r
- * rmem_adrp returned; real mode para addr of allocated\r
- * conventional memory block, to be used to free\r
- * up the conventional memory when done. DO NOT\r
- * USE THIS TO CONSTRUCT A REAL MODE PTR, USE\r
- * REAL_BASEP INSTEAD SO THAT OFFSETS WORK OUT\r
- * CORRECTLY.\r
- *\r
- * Returned values:\r
- * 0 if error\r
- * 1 if success\r
- */\r
-int RealCopy (ULONG start_offs,\r
- ULONG end_offs,\r
- REALPTR *real_basep,\r
- FARPTR *prot_basep,\r
- USHORT *rmem_adrp)\r
-{\r
- ULONG rm_base; /* base real mode para addr for accessing */\r
- /* allocated conventional memory */\r
- UCHAR *source; /* source pointer for copy */\r
- FARPTR destin; /* destination pointer for copy */\r
- ULONG len; /* number of bytes to copy */\r
- ULONG temp;\r
- USHORT stemp;\r
-\r
- /* First check for valid inputs\r
- */\r
- if (start_offs >= end_offs || end_offs > 0x10000)\r
- return (FALSE);\r
-\r
- /* Round start_offs down to a paragraph (16-byte) boundary so we can set up\r
- * the real mode pointer easily. Round up end_offs to make sure we allocate\r
- * enough paragraphs\r
- */\r
- start_offs &= ~15;\r
- end_offs = (15 + (end_offs << 4)) >> 4;\r
-\r
- /* Allocate the conventional memory for our real mode code. Remember to\r
- * round byte count UP to 16-byte paragraph size. We alloc it\r
- * above the DOS data buffer so both the DOS data buffer and the appl\r
- * conventional mem block can still be resized.\r
- *\r
- * First just try to alloc it; if we can't get it, shrink the appl mem\r
- * block down to the minimum, try to alloc the memory again, then grow the\r
- * appl mem block back to the maximum. (Don't try to shrink the DOS data\r
- * buffer to free conventional memory; it wouldn't be good for this routine\r
- * to have the possible side effect of making file I/O run slower.)\r
- */\r
- len = ((end_offs - start_offs) + 15) >> 4;\r
- if (_dx_real_above(len, rmem_adrp, &stemp) != _DOSE_NONE)\r
- {\r
- if (_dx_cmem_usage(0, 0, &temp, &temp) != _DOSE_NONE)\r
- return (FALSE);\r
-\r
- if (_dx_real_above(len, rmem_adrp, &stemp) != _DOSE_NONE)\r
- *rmem_adrp = 0;\r
-\r
- if (_dx_cmem_usage(0, 1, &temp, &temp) != _DOSE_NONE)\r
- {\r
- if (*rmem_adrp != 0)\r
- _dx_real_free (*rmem_adrp);\r
- return (FALSE);\r
- }\r
-\r
- if (*rmem_adrp == 0)\r
- return (FALSE);\r
- }\r
-\r
- /* Construct real mode & protected mode pointers to access the allocated\r
- * memory. Note we know start_offs is aligned on a paragraph (16-byte)\r
- * boundary, because we rounded it down.\r
- *\r
- * We make the offsets come out rights by backing off the real mode selector\r
- * by start_offs.\r
- */\r
- rm_base = ((ULONG) *rmem_adrp) - (start_offs >> 4);\r
- RP_SET (*real_basep, 0, rm_base);\r
- FP_SET (*prot_basep, rm_base << 4, SS_DOSMEM);\r
-\r
- /* Copy the real mode code/data to the allocated memory\r
- */\r
- source = (UCHAR *) start_offs;\r
- destin = *prot_basep;\r
- FP_SET (destin, FP_OFF(*prot_basep) + start_offs, FP_SEL(*prot_basep));\r
- len = end_offs - start_offs;\r
- WriteFarMem (destin, source, len);\r
-\r
- return (TRUE);\r
-}\r
-#endif /* DOSX && (DOSX & PHARLAP) */\r
+/*
+ * File.........: pktdrvr.c
+ *
+ *
+ * Created......: 26.Sept 1995
+ *
+ * Description..: Packet-driver interface for 16/32-bit C :
+ * Borland C/C++ 3.0+ small/large model
+ * Watcom C/C++ 11+, DOS4GW flat model
+ * Metaware HighC 3.1+ and PharLap 386|DosX
+ * GNU C/C++ 2.7+ and djgpp 2.x extender
+ *
+ * References...: PC/TCP Packet driver Specification. rev 1.09
+ * FTP Software Inc.
+ *
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dos.h>
+
+#include "pcap-dos.h"
+#include "pcap-int.h"
+#include "msdos/pktdrvr.h"
+
+#if (DOSX)
+#define NUM_RX_BUF 32 /* # of buffers in Rx FIFO queue */
+#else
+#define NUM_RX_BUF 10
+#endif
+
+#define DIM(x) (sizeof((x)) / sizeof(x[0]))
+#define PUTS(s) do { \
+ if (!pktInfo.quiet) \
+ pktInfo.error ? \
+ printf ("%s: %s\n", s, pktInfo.error) : \
+ printf ("%s\n", pktInfo.error = s); \
+ } while (0)
+
+#if defined(__HIGHC__)
+ extern UINT _mwenv;
+
+#elif defined(__DJGPP__)
+ #include <stddef.h>
+ #include <dpmi.h>
+ #include <go32.h>
+ #include <pc.h>
+ #include <sys/farptr.h>
+
+#elif defined(__WATCOMC__)
+ #include <i86.h>
+ #include <stddef.h>
+ extern char _Extender;
+
+#else
+ extern void far PktReceiver (void);
+#endif
+
+
+#if (DOSX & (DJGPP|DOS4GW))
+ #include <sys/pack_on.h>
+
+ struct DPMI_regs {
+ DWORD r_di;
+ DWORD r_si;
+ DWORD r_bp;
+ DWORD reserved;
+ DWORD r_bx;
+ DWORD r_dx;
+ DWORD r_cx;
+ DWORD r_ax;
+ WORD r_flags;
+ WORD r_es, r_ds, r_fs, r_gs;
+ WORD r_ip, r_cs, r_sp, r_ss;
+ };
+
+ /* Data located in a real-mode segment. This becomes far at runtime
+ */
+ typedef struct { /* must match data/code in pkt_rx1.s */
+ WORD _rxOutOfs;
+ WORD _rxInOfs;
+ DWORD _pktDrop;
+ BYTE _pktTemp [20];
+ TX_ELEMENT _pktTxBuf[1];
+ RX_ELEMENT _pktRxBuf[NUM_RX_BUF];
+ WORD _dummy[2]; /* screenSeg,newInOffset */
+ BYTE _fanChars[4];
+ WORD _fanIndex;
+ BYTE _PktReceiver[15]; /* starts on a paragraph (16byte) */
+ } PktRealStub;
+ #include <sys/pack_off.h>
+
+ static BYTE real_stub_array [] = {
+ #include "pkt_stub.inc" /* generated opcode array */
+ };
+
+ #define rxOutOfs offsetof (PktRealStub,_rxOutOfs)
+ #define rxInOfs offsetof (PktRealStub,_rxInOfs)
+ #define PktReceiver offsetof (PktRealStub,_PktReceiver [para_skip])
+ #define pktDrop offsetof (PktRealStub,_pktDrop)
+ #define pktTemp offsetof (PktRealStub,_pktTemp)
+ #define pktTxBuf offsetof (PktRealStub,_pktTxBuf)
+ #define FIRST_RX_BUF offsetof (PktRealStub,_pktRxBuf [0])
+ #define LAST_RX_BUF offsetof (PktRealStub,_pktRxBuf [NUM_RX_BUF-1])
+
+#else
+ extern WORD rxOutOfs; /* offsets into pktRxBuf FIFO queue */
+ extern WORD rxInOfs;
+ extern DWORD pktDrop; /* # packets dropped in PktReceiver() */
+ extern BYTE pktRxEnd; /* marks the end of r-mode code/data */
+
+ extern RX_ELEMENT pktRxBuf [NUM_RX_BUF]; /* PktDrvr Rx buffers */
+ extern TX_ELEMENT pktTxBuf; /* PktDrvr Tx buffer */
+ extern char pktTemp[20]; /* PktDrvr temp area */
+
+ #define FIRST_RX_BUF (WORD) &pktRxBuf [0]
+ #define LAST_RX_BUF (WORD) &pktRxBuf [NUM_RX_BUF-1]
+#endif
+
+
+#ifdef __BORLANDC__ /* Use Borland's inline functions */
+ #define memcpy __memcpy__
+ #define memcmp __memcmp__
+ #define memset __memset__
+#endif
+
+
+#if (DOSX & PHARLAP)
+ extern void PktReceiver (void); /* in pkt_rx0.asm */
+ static int RealCopy (ULONG, ULONG, REALPTR*, FARPTR*, USHORT*);
+
+ #undef FP_SEG
+ #undef FP_OFF
+ #define FP_OFF(x) ((WORD)(x))
+ #define FP_SEG(x) ((WORD)(realBase >> 16))
+ #define DOS_ADDR(s,o) (((DWORD)(s) << 16) + (WORD)(o))
+ #define r_ax eax
+ #define r_bx ebx
+ #define r_dx edx
+ #define r_cx ecx
+ #define r_si esi
+ #define r_di edi
+ #define r_ds ds
+ #define r_es es
+ LOCAL FARPTR protBase;
+ LOCAL REALPTR realBase;
+ LOCAL WORD realSeg; /* DOS para-address of allocated area */
+ LOCAL SWI_REGS reg;
+
+ static WORD _far *rxOutOfsFp, *rxInOfsFp;
+
+#elif (DOSX & DJGPP)
+ static _go32_dpmi_seginfo rm_mem;
+ static __dpmi_regs reg;
+ static DWORD realBase;
+ static int para_skip = 0;
+
+ #define DOS_ADDR(s,o) (((WORD)(s) << 4) + (o))
+ #define r_ax x.ax
+ #define r_bx x.bx
+ #define r_dx x.dx
+ #define r_cx x.cx
+ #define r_si x.si
+ #define r_di x.di
+ #define r_ds x.ds
+ #define r_es x.es
+
+#elif (DOSX & DOS4GW)
+ LOCAL struct DPMI_regs reg;
+ LOCAL WORD rm_base_seg, rm_base_sel;
+ LOCAL DWORD realBase;
+ LOCAL int para_skip = 0;
+
+ LOCAL DWORD dpmi_get_real_vector (int intr);
+ LOCAL WORD dpmi_real_malloc (int size, WORD *selector);
+ LOCAL void dpmi_real_free (WORD selector);
+ #define DOS_ADDR(s,o) (((DWORD)(s) << 4) + (WORD)(o))
+
+#else /* real-mode Borland etc. */
+ static struct {
+ WORD r_ax, r_bx, r_cx, r_dx, r_bp;
+ WORD r_si, r_di, r_ds, r_es, r_flags;
+ } reg;
+#endif
+
+#ifdef __HIGHC__
+ #pragma Alias (pktDrop, "_pktDrop")
+ #pragma Alias (pktRxBuf, "_pktRxBuf")
+ #pragma Alias (pktTxBuf, "_pktTxBuf")
+ #pragma Alias (pktTemp, "_pktTemp")
+ #pragma Alias (rxOutOfs, "_rxOutOfs")
+ #pragma Alias (rxInOfs, "_rxInOfs")
+ #pragma Alias (pktRxEnd, "_pktRxEnd")
+ #pragma Alias (PktReceiver,"_PktReceiver")
+#endif
+
+
+PUBLIC PKT_STAT pktStat; /* statistics for packets */
+PUBLIC PKT_INFO pktInfo; /* packet-driver information */
+
+PUBLIC PKT_RX_MODE receiveMode = PDRX_DIRECT;
+PUBLIC ETHER myAddress = { 0, 0, 0, 0, 0, 0 };
+PUBLIC ETHER ethBroadcast = { 255,255,255,255,255,255 };
+
+LOCAL struct { /* internal statistics */
+ DWORD tooSmall; /* size < ETH_MIN */
+ DWORD tooLarge; /* size > ETH_MAX */
+ DWORD badSync; /* count_1 != count_2 */
+ DWORD wrongHandle; /* upcall to wrong handle */
+ } intStat;
+
+/***************************************************************************/
+
+PUBLIC const char *PktGetErrorStr (int errNum)
+{
+ static const char *errStr[] = {
+ "",
+ "Invalid handle number",
+ "No interfaces of specified class found",
+ "No interfaces of specified type found",
+ "No interfaces of specified number found",
+ "Bad packet type specified",
+ "Interface does not support multicast",
+ "Packet driver cannot terminate",
+ "Invalid receiver mode specified",
+ "Insufficient memory space",
+ "Type previously accessed, and not released",
+ "Command out of range, or not implemented",
+ "Cannot send packet (usually hardware error)",
+ "Cannot change hardware address ( > 1 handle open)",
+ "Hardware address has bad length or format",
+ "Cannot reset interface (more than 1 handle open)",
+ "Bad Check-sum",
+ "Bad size",
+ "Bad sync" ,
+ "Source hit"
+ };
+
+ if (errNum < 0 || errNum >= DIM(errStr))
+ return ("Unknown driver error.");
+ return (errStr [errNum]);
+}
+
+/**************************************************************************/
+
+PUBLIC const char *PktGetClassName (WORD class)
+{
+ switch (class)
+ {
+ case PD_ETHER:
+ return ("DIX-Ether");
+ case PD_PRONET10:
+ return ("ProNET-10");
+ case PD_IEEE8025:
+ return ("IEEE 802.5");
+ case PD_OMNINET:
+ return ("OmniNet");
+ case PD_APPLETALK:
+ return ("AppleTalk");
+ case PD_SLIP:
+ return ("SLIP");
+ case PD_STARTLAN:
+ return ("StartLAN");
+ case PD_ARCNET:
+ return ("ArcNet");
+ case PD_AX25:
+ return ("AX.25");
+ case PD_KISS:
+ return ("KISS");
+ case PD_IEEE8023_2:
+ return ("IEEE 802.3 w/802.2 hdr");
+ case PD_FDDI8022:
+ return ("FDDI w/802.2 hdr");
+ case PD_X25:
+ return ("X.25");
+ case PD_LANstar:
+ return ("LANstar");
+ case PD_PPP:
+ return ("PPP");
+ default:
+ return ("unknown");
+ }
+}
+
+/**************************************************************************/
+
+PUBLIC char const *PktRXmodeStr (PKT_RX_MODE mode)
+{
+ static const char *modeStr [] = {
+ "Receiver turned off",
+ "Receive only directly addressed packets",
+ "Receive direct & broadcast packets",
+ "Receive direct,broadcast and limited multicast packets",
+ "Receive direct,broadcast and all multicast packets",
+ "Receive all packets (promiscuouos mode)"
+ };
+
+ if (mode > DIM(modeStr))
+ return ("??");
+ return (modeStr [mode-1]);
+}
+
+/**************************************************************************/
+
+LOCAL __inline BOOL PktInterrupt (void)
+{
+ BOOL okay;
+
+#if (DOSX & PHARLAP)
+ _dx_real_int ((UINT)pktInfo.intr, ®);
+ okay = ((reg.flags & 1) == 0); /* OK if carry clear */
+
+#elif (DOSX & DJGPP)
+ __dpmi_int ((int)pktInfo.intr, ®);
+ okay = ((reg.x.flags & 1) == 0);
+
+#elif (DOSX & DOS4GW)
+ union REGS r;
+ struct SREGS s;
+
+ memset (&r, 0, sizeof(r));
+ segread (&s);
+ r.w.ax = 0x300;
+ r.x.ebx = pktInfo.intr;
+ r.w.cx = 0;
+ s.es = FP_SEG (®);
+ r.x.edi = FP_OFF (®);
+ reg.r_flags = 0;
+ reg.r_ss = reg.r_sp = 0; /* DPMI host provides stack */
+
+ int386x (0x31, &r, &r, &s);
+ okay = (!r.w.cflag);
+
+#else
+ reg.r_flags = 0;
+ intr (pktInfo.intr, (struct REGPACK*)®);
+ okay = ((reg.r_flags & 1) == 0);
+#endif
+
+ if (okay)
+ pktInfo.error = NULL;
+ else pktInfo.error = PktGetErrorStr (reg.r_dx >> 8);
+ return (okay);
+}
+
+/**************************************************************************/
+
+/*
+ * Search for packet driver at interrupt 60h through 80h. If ASCIIZ
+ * string "PKT DRVR" found at offset 3 in the interrupt handler, return
+ * interrupt number, else return zero in pktInfo.intr
+ */
+PUBLIC BOOL PktSearchDriver (void)
+{
+ BYTE intr = 0x20;
+ BOOL found = FALSE;
+
+ while (!found && intr < 0xFF)
+ {
+ static char str[12]; /* 3 + strlen("PKT DRVR") */
+ static char pktStr[9] = "PKT DRVR"; /* ASCIIZ string at ofs 3 */
+ DWORD rp; /* in interrupt routine */
+
+#if (DOSX & PHARLAP)
+ _dx_rmiv_get (intr, &rp);
+ ReadRealMem (&str, (REALPTR)rp, sizeof(str));
+
+#elif (DOSX & DJGPP)
+ __dpmi_raddr realAdr;
+ __dpmi_get_real_mode_interrupt_vector (intr, &realAdr);
+ rp = (realAdr.segment << 4) + realAdr.offset16;
+ dosmemget (rp, sizeof(str), &str);
+
+#elif (DOSX & DOS4GW)
+ rp = dpmi_get_real_vector (intr);
+ memcpy (&str, (void*)rp, sizeof(str));
+
+#else
+ _fmemcpy (&str, getvect(intr), sizeof(str));
+#endif
+
+ found = memcmp (&str[3],&pktStr,sizeof(pktStr)) == 0;
+ intr++;
+ }
+ pktInfo.intr = (found ? intr-1 : 0);
+ return (found);
+}
+
+
+/**************************************************************************/
+
+static BOOL PktSetAccess (void)
+{
+ reg.r_ax = 0x0200 + pktInfo.class;
+ reg.r_bx = 0xFFFF;
+ reg.r_dx = 0;
+ reg.r_cx = 0;
+
+#if (DOSX & PHARLAP)
+ reg.ds = 0;
+ reg.esi = 0;
+ reg.es = RP_SEG (realBase);
+ reg.edi = (WORD) &PktReceiver;
+
+#elif (DOSX & DJGPP)
+ reg.x.ds = 0;
+ reg.x.si = 0;
+ reg.x.es = rm_mem.rm_segment;
+ reg.x.di = PktReceiver;
+
+#elif (DOSX & DOS4GW)
+ reg.r_ds = 0;
+ reg.r_si = 0;
+ reg.r_es = rm_base_seg;
+ reg.r_di = PktReceiver;
+
+#else
+ reg.r_ds = 0;
+ reg.r_si = 0;
+ reg.r_es = FP_SEG (&PktReceiver);
+ reg.r_di = FP_OFF (&PktReceiver);
+#endif
+
+ if (!PktInterrupt())
+ return (FALSE);
+
+ pktInfo.handle = reg.r_ax;
+ return (TRUE);
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktReleaseHandle (WORD handle)
+{
+ reg.r_ax = 0x0300;
+ reg.r_bx = handle;
+ return PktInterrupt();
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktTransmit (const void *eth, int len)
+{
+ if (len > ETH_MTU)
+ return (FALSE);
+
+ reg.r_ax = 0x0400; /* Function 4, send pkt */
+ reg.r_cx = len; /* total size of frame */
+
+#if (DOSX & DJGPP)
+ dosmemput (eth, len, realBase+pktTxBuf);
+ reg.x.ds = rm_mem.rm_segment; /* DOS data segment and */
+ reg.x.si = pktTxBuf; /* DOS offset to buffer */
+
+#elif (DOSX & DOS4GW)
+ memcpy ((void*)(realBase+pktTxBuf), eth, len);
+ reg.r_ds = rm_base_seg;
+ reg.r_si = pktTxBuf;
+
+#elif (DOSX & PHARLAP)
+ memcpy (&pktTxBuf, eth, len);
+ reg.r_ds = FP_SEG (&pktTxBuf);
+ reg.r_si = FP_OFF (&pktTxBuf);
+
+#else
+ reg.r_ds = FP_SEG (eth);
+ reg.r_si = FP_OFF (eth);
+#endif
+
+ return PktInterrupt();
+}
+
+/**************************************************************************/
+
+#if (DOSX & (DJGPP|DOS4GW))
+LOCAL __inline BOOL CheckElement (RX_ELEMENT *rx)
+#else
+LOCAL __inline BOOL CheckElement (RX_ELEMENT _far *rx)
+#endif
+{
+ WORD count_1, count_2;
+
+ /*
+ * We got an upcall to the same RMCB with wrong handle.
+ * This can happen if we failed to release handle at program exit
+ */
+ if (rx->handle != pktInfo.handle)
+ {
+ pktInfo.error = "Wrong handle";
+ intStat.wrongHandle++;
+ PktReleaseHandle (rx->handle);
+ return (FALSE);
+ }
+ count_1 = rx->firstCount;
+ count_2 = rx->secondCount;
+
+ if (count_1 != count_2)
+ {
+ pktInfo.error = "Bad sync";
+ intStat.badSync++;
+ return (FALSE);
+ }
+ if (count_1 > ETH_MAX)
+ {
+ pktInfo.error = "Large esize";
+ intStat.tooLarge++;
+ return (FALSE);
+ }
+#if 0
+ if (count_1 < ETH_MIN)
+ {
+ pktInfo.error = "Small esize";
+ intStat.tooSmall++;
+ return (FALSE);
+ }
+#endif
+ return (TRUE);
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktTerminHandle (WORD handle)
+{
+ reg.r_ax = 0x0500;
+ reg.r_bx = handle;
+ return PktInterrupt();
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktResetInterface (WORD handle)
+{
+ reg.r_ax = 0x0700;
+ reg.r_bx = handle;
+ return PktInterrupt();
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktSetReceiverMode (PKT_RX_MODE mode)
+{
+ if (pktInfo.class == PD_SLIP || pktInfo.class == PD_PPP)
+ return (TRUE);
+
+ reg.r_ax = 0x1400;
+ reg.r_bx = pktInfo.handle;
+ reg.r_cx = (WORD)mode;
+
+ if (!PktInterrupt())
+ return (FALSE);
+
+ receiveMode = mode;
+ return (TRUE);
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktGetReceiverMode (PKT_RX_MODE *mode)
+{
+ reg.r_ax = 0x1500;
+ reg.r_bx = pktInfo.handle;
+
+ if (!PktInterrupt())
+ return (FALSE);
+
+ *mode = reg.r_ax;
+ return (TRUE);
+}
+
+/**************************************************************************/
+
+static PKT_STAT initialStat; /* statistics at startup */
+static BOOL resetStat = FALSE; /* statistics reset ? */
+
+PUBLIC BOOL PktGetStatistics (WORD handle)
+{
+ reg.r_ax = 0x1800;
+ reg.r_bx = handle;
+
+ if (!PktInterrupt())
+ return (FALSE);
+
+#if (DOSX & PHARLAP)
+ ReadRealMem (&pktStat, DOS_ADDR(reg.ds,reg.esi), sizeof(pktStat));
+
+#elif (DOSX & DJGPP)
+ dosmemget (DOS_ADDR(reg.x.ds,reg.x.si), sizeof(pktStat), &pktStat);
+
+#elif (DOSX & DOS4GW)
+ memcpy (&pktStat, (void*)DOS_ADDR(reg.r_ds,reg.r_si), sizeof(pktStat));
+
+#else
+ _fmemcpy (&pktStat, MK_FP(reg.r_ds,reg.r_si), sizeof(pktStat));
+#endif
+
+ return (TRUE);
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktSessStatistics (WORD handle)
+{
+ if (!PktGetStatistics(pktInfo.handle))
+ return (FALSE);
+
+ if (resetStat)
+ {
+ pktStat.inPackets -= initialStat.inPackets;
+ pktStat.outPackets -= initialStat.outPackets;
+ pktStat.inBytes -= initialStat.inBytes;
+ pktStat.outBytes -= initialStat.outBytes;
+ pktStat.inErrors -= initialStat.inErrors;
+ pktStat.outErrors -= initialStat.outErrors;
+ pktStat.outErrors -= initialStat.outErrors;
+ pktStat.lost -= initialStat.lost;
+ }
+ return (TRUE);
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktResetStatistics (WORD handle)
+{
+ if (!PktGetStatistics(pktInfo.handle))
+ return (FALSE);
+
+ memcpy (&initialStat, &pktStat, sizeof(initialStat));
+ resetStat = TRUE;
+ return (TRUE);
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktGetAddress (ETHER *addr)
+{
+ reg.r_ax = 0x0600;
+ reg.r_bx = pktInfo.handle;
+ reg.r_cx = sizeof (*addr);
+
+#if (DOSX & DJGPP)
+ reg.x.es = rm_mem.rm_segment;
+ reg.x.di = pktTemp;
+#elif (DOSX & DOS4GW)
+ reg.r_es = rm_base_seg;
+ reg.r_di = pktTemp;
+#else
+ reg.r_es = FP_SEG (&pktTemp);
+ reg.r_di = FP_OFF (&pktTemp); /* ES:DI = address for result */
+#endif
+
+ if (!PktInterrupt())
+ return (FALSE);
+
+#if (DOSX & PHARLAP)
+ ReadRealMem (addr, realBase + (WORD)&pktTemp, sizeof(*addr));
+
+#elif (DOSX & DJGPP)
+ dosmemget (realBase+pktTemp, sizeof(*addr), addr);
+
+#elif (DOSX & DOS4GW)
+ memcpy (addr, (void*)(realBase+pktTemp), sizeof(*addr));
+
+#else
+ memcpy ((void*)addr, &pktTemp, sizeof(*addr));
+#endif
+
+ return (TRUE);
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktSetAddress (const ETHER *addr)
+{
+ /* copy addr to real-mode scrath area */
+
+#if (DOSX & PHARLAP)
+ WriteRealMem (realBase + (WORD)&pktTemp, (void*)addr, sizeof(*addr));
+
+#elif (DOSX & DJGPP)
+ dosmemput (addr, sizeof(*addr), realBase+pktTemp);
+
+#elif (DOSX & DOS4GW)
+ memcpy ((void*)(realBase+pktTemp), addr, sizeof(*addr));
+
+#else
+ memcpy (&pktTemp, (void*)addr, sizeof(*addr));
+#endif
+
+ reg.r_ax = 0x1900;
+ reg.r_cx = sizeof (*addr); /* address length */
+
+#if (DOSX & DJGPP)
+ reg.x.es = rm_mem.rm_segment; /* DOS offset to param */
+ reg.x.di = pktTemp; /* DOS segment to param */
+#elif (DOSX & DOS4GW)
+ reg.r_es = rm_base_seg;
+ reg.r_di = pktTemp;
+#else
+ reg.r_es = FP_SEG (&pktTemp);
+ reg.r_di = FP_OFF (&pktTemp);
+#endif
+
+ return PktInterrupt();
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktGetDriverInfo (void)
+{
+ pktInfo.majVer = 0;
+ pktInfo.minVer = 0;
+ memset (&pktInfo.name, 0, sizeof(pktInfo.name));
+ reg.r_ax = 0x01FF;
+ reg.r_bx = 0;
+
+ if (!PktInterrupt())
+ return (FALSE);
+
+ pktInfo.number = reg.r_cx & 0xFF;
+ pktInfo.class = reg.r_cx >> 8;
+#if 0
+ pktInfo.minVer = reg.r_bx % 10;
+ pktInfo.majVer = reg.r_bx / 10;
+#else
+ pktInfo.majVer = reg.r_bx; // !!
+#endif
+ pktInfo.funcs = reg.r_ax & 0xFF;
+ pktInfo.type = reg.r_dx & 0xFF;
+
+#if (DOSX & PHARLAP)
+ ReadRealMem (&pktInfo.name, DOS_ADDR(reg.ds,reg.esi), sizeof(pktInfo.name));
+
+#elif (DOSX & DJGPP)
+ dosmemget (DOS_ADDR(reg.x.ds,reg.x.si), sizeof(pktInfo.name), &pktInfo.name);
+
+#elif (DOSX & DOS4GW)
+ memcpy (&pktInfo.name, (void*)DOS_ADDR(reg.r_ds,reg.r_si), sizeof(pktInfo.name));
+
+#else
+ _fmemcpy (&pktInfo.name, MK_FP(reg.r_ds,reg.r_si), sizeof(pktInfo.name));
+#endif
+ return (TRUE);
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktGetDriverParam (void)
+{
+ reg.r_ax = 0x0A00;
+
+ if (!PktInterrupt())
+ return (FALSE);
+
+#if (DOSX & PHARLAP)
+ ReadRealMem (&pktInfo.majVer, DOS_ADDR(reg.es,reg.edi), PKT_PARAM_SIZE);
+
+#elif (DOSX & DJGPP)
+ dosmemget (DOS_ADDR(reg.x.es,reg.x.di), PKT_PARAM_SIZE, &pktInfo.majVer);
+
+#elif (DOSX & DOS4GW)
+ memcpy (&pktInfo.majVer, (void*)DOS_ADDR(reg.r_es,reg.r_di), PKT_PARAM_SIZE);
+
+#else
+ _fmemcpy (&pktInfo.majVer, MK_FP(reg.r_es,reg.r_di), PKT_PARAM_SIZE);
+#endif
+ return (TRUE);
+}
+
+/**************************************************************************/
+
+#if (DOSX & PHARLAP)
+ PUBLIC int PktReceive (BYTE *buf, int max)
+ {
+ WORD inOfs = *rxInOfsFp;
+ WORD outOfs = *rxOutOfsFp;
+
+ if (outOfs != inOfs)
+ {
+ RX_ELEMENT _far *head = (RX_ELEMENT _far*)(protBase+outOfs);
+ int size, len = max;
+
+ if (CheckElement(head))
+ {
+ size = min (head->firstCount, sizeof(RX_ELEMENT));
+ len = min (size, max);
+ _fmemcpy (buf, &head->destin, len);
+ }
+ else
+ size = -1;
+
+ outOfs += sizeof (RX_ELEMENT);
+ if (outOfs > LAST_RX_BUF)
+ outOfs = FIRST_RX_BUF;
+ *rxOutOfsFp = outOfs;
+ return (size);
+ }
+ return (0);
+ }
+
+ PUBLIC void PktQueueBusy (BOOL busy)
+ {
+ *rxOutOfsFp = busy ? (*rxInOfsFp + sizeof(RX_ELEMENT)) : *rxInOfsFp;
+ if (*rxOutOfsFp > LAST_RX_BUF)
+ *rxOutOfsFp = FIRST_RX_BUF;
+ *(DWORD _far*)(protBase + (WORD)&pktDrop) = 0;
+ }
+
+ PUBLIC WORD PktBuffersUsed (void)
+ {
+ WORD inOfs = *rxInOfsFp;
+ WORD outOfs = *rxOutOfsFp;
+
+ if (inOfs >= outOfs)
+ return (inOfs - outOfs) / sizeof(RX_ELEMENT);
+ return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));
+ }
+
+ PUBLIC DWORD PktRxDropped (void)
+ {
+ return (*(DWORD _far*)(protBase + (WORD)&pktDrop));
+ }
+
+#elif (DOSX & DJGPP)
+ PUBLIC int PktReceive (BYTE *buf, int max)
+ {
+ WORD ofs = _farpeekw (_dos_ds, realBase+rxOutOfs);
+
+ if (ofs != _farpeekw (_dos_ds, realBase+rxInOfs))
+ {
+ RX_ELEMENT head;
+ int size, len = max;
+
+ head.firstCount = _farpeekw (_dos_ds, realBase+ofs);
+ head.secondCount = _farpeekw (_dos_ds, realBase+ofs+2);
+ head.handle = _farpeekw (_dos_ds, realBase+ofs+4);
+
+ if (CheckElement(&head))
+ {
+ size = min (head.firstCount, sizeof(RX_ELEMENT));
+ len = min (size, max);
+ dosmemget (realBase+ofs+6, len, buf);
+ }
+ else
+ size = -1;
+
+ ofs += sizeof (RX_ELEMENT);
+ if (ofs > LAST_RX_BUF)
+ _farpokew (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);
+ else _farpokew (_dos_ds, realBase+rxOutOfs, ofs);
+ return (size);
+ }
+ return (0);
+ }
+
+ PUBLIC void PktQueueBusy (BOOL busy)
+ {
+ WORD ofs;
+
+ disable();
+ ofs = _farpeekw (_dos_ds, realBase+rxInOfs);
+ if (busy)
+ ofs += sizeof (RX_ELEMENT);
+
+ if (ofs > LAST_RX_BUF)
+ _farpokew (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);
+ else _farpokew (_dos_ds, realBase+rxOutOfs, ofs);
+ _farpokel (_dos_ds, realBase+pktDrop, 0UL);
+ enable();
+ }
+
+ PUBLIC WORD PktBuffersUsed (void)
+ {
+ WORD inOfs, outOfs;
+
+ disable();
+ inOfs = _farpeekw (_dos_ds, realBase+rxInOfs);
+ outOfs = _farpeekw (_dos_ds, realBase+rxOutOfs);
+ enable();
+ if (inOfs >= outOfs)
+ return (inOfs - outOfs) / sizeof(RX_ELEMENT);
+ return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));
+ }
+
+ PUBLIC DWORD PktRxDropped (void)
+ {
+ return _farpeekl (_dos_ds, realBase+pktDrop);
+ }
+
+#elif (DOSX & DOS4GW)
+ PUBLIC int PktReceive (BYTE *buf, int max)
+ {
+ WORD ofs = *(WORD*) (realBase+rxOutOfs);
+
+ if (ofs != *(WORD*) (realBase+rxInOfs))
+ {
+ RX_ELEMENT head;
+ int size, len = max;
+
+ head.firstCount = *(WORD*) (realBase+ofs);
+ head.secondCount = *(WORD*) (realBase+ofs+2);
+ head.handle = *(WORD*) (realBase+ofs+4);
+
+ if (CheckElement(&head))
+ {
+ size = min (head.firstCount, sizeof(RX_ELEMENT));
+ len = min (size, max);
+ memcpy (buf, (const void*)(realBase+ofs+6), len);
+ }
+ else
+ size = -1;
+
+ ofs += sizeof (RX_ELEMENT);
+ if (ofs > LAST_RX_BUF)
+ *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;
+ else *(WORD*) (realBase+rxOutOfs) = ofs;
+ return (size);
+ }
+ return (0);
+ }
+
+ PUBLIC void PktQueueBusy (BOOL busy)
+ {
+ WORD ofs;
+
+ _disable();
+ ofs = *(WORD*) (realBase+rxInOfs);
+ if (busy)
+ ofs += sizeof (RX_ELEMENT);
+
+ if (ofs > LAST_RX_BUF)
+ *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;
+ else *(WORD*) (realBase+rxOutOfs) = ofs;
+ *(DWORD*) (realBase+pktDrop) = 0UL;
+ _enable();
+ }
+
+ PUBLIC WORD PktBuffersUsed (void)
+ {
+ WORD inOfs, outOfs;
+
+ _disable();
+ inOfs = *(WORD*) (realBase+rxInOfs);
+ outOfs = *(WORD*) (realBase+rxOutOfs);
+ _enable();
+ if (inOfs >= outOfs)
+ return (inOfs - outOfs) / sizeof(RX_ELEMENT);
+ return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));
+ }
+
+ PUBLIC DWORD PktRxDropped (void)
+ {
+ return *(DWORD*) (realBase+pktDrop);
+ }
+
+#else /* real-mode small/large model */
+
+ PUBLIC int PktReceive (BYTE *buf, int max)
+ {
+ if (rxOutOfs != rxInOfs)
+ {
+ RX_ELEMENT far *head = (RX_ELEMENT far*) MK_FP (_DS,rxOutOfs);
+ int size, len = max;
+
+ if (CheckElement(head))
+ {
+ size = min (head->firstCount, sizeof(RX_ELEMENT));
+ len = min (size, max);
+ _fmemcpy (buf, &head->destin, len);
+ }
+ else
+ size = -1;
+
+ rxOutOfs += sizeof (RX_ELEMENT);
+ if (rxOutOfs > LAST_RX_BUF)
+ rxOutOfs = FIRST_RX_BUF;
+ return (size);
+ }
+ return (0);
+ }
+
+ PUBLIC void PktQueueBusy (BOOL busy)
+ {
+ rxOutOfs = busy ? (rxInOfs + sizeof(RX_ELEMENT)) : rxInOfs;
+ if (rxOutOfs > LAST_RX_BUF)
+ rxOutOfs = FIRST_RX_BUF;
+ pktDrop = 0L;
+ }
+
+ PUBLIC WORD PktBuffersUsed (void)
+ {
+ WORD inOfs = rxInOfs;
+ WORD outOfs = rxOutOfs;
+
+ if (inOfs >= outOfs)
+ return ((inOfs - outOfs) / sizeof(RX_ELEMENT));
+ return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));
+ }
+
+ PUBLIC DWORD PktRxDropped (void)
+ {
+ return (pktDrop);
+ }
+#endif
+
+/**************************************************************************/
+
+LOCAL __inline void PktFreeMem (void)
+{
+#if (DOSX & PHARLAP)
+ if (realSeg)
+ {
+ _dx_real_free (realSeg);
+ realSeg = 0;
+ }
+#elif (DOSX & DJGPP)
+ if (rm_mem.rm_segment)
+ {
+ unsigned ofs; /* clear the DOS-mem to prevent further upcalls */
+
+ for (ofs = 0; ofs < 16 * rm_mem.size / 4; ofs += 4)
+ _farpokel (_dos_ds, realBase + ofs, 0);
+ _go32_dpmi_free_dos_memory (&rm_mem);
+ rm_mem.rm_segment = 0;
+ }
+#elif (DOSX & DOS4GW)
+ if (rm_base_sel)
+ {
+ dpmi_real_free (rm_base_sel);
+ rm_base_sel = 0;
+ }
+#endif
+}
+
+/**************************************************************************/
+
+PUBLIC BOOL PktExitDriver (void)
+{
+ if (pktInfo.handle)
+ {
+ if (!PktSetReceiverMode(PDRX_BROADCAST))
+ PUTS ("Error restoring receiver mode.");
+
+ if (!PktReleaseHandle(pktInfo.handle))
+ PUTS ("Error releasing PKT-DRVR handle.");
+
+ PktFreeMem();
+ pktInfo.handle = 0;
+ }
+
+ if (pcap_pkt_debug >= 1)
+ printf ("Internal stats: too-small %lu, too-large %lu, bad-sync %lu, "
+ "wrong-handle %lu\n",
+ intStat.tooSmall, intStat.tooLarge,
+ intStat.badSync, intStat.wrongHandle);
+ return (TRUE);
+}
+
+#if (DOSX & (DJGPP|DOS4GW))
+static void dump_pkt_stub (void)
+{
+ int i;
+
+ fprintf (stderr, "PktReceiver %lu, pkt_stub[PktReceiver] =\n",
+ PktReceiver);
+ for (i = 0; i < 15; i++)
+ fprintf (stderr, "%02X, ", real_stub_array[i+PktReceiver]);
+ fputs ("\n", stderr);
+}
+#endif
+
+/*
+ * Front end initialization routine
+ */
+PUBLIC BOOL PktInitDriver (PKT_RX_MODE mode)
+{
+ PKT_RX_MODE rxMode;
+ BOOL writeInfo = (pcap_pkt_debug >= 3);
+
+ pktInfo.quiet = (pcap_pkt_debug < 3);
+
+#if (DOSX & PHARLAP) && defined(__HIGHC__)
+ if (_mwenv != 2)
+ {
+ fprintf (stderr, "Only Pharlap DOS extender supported.\n");
+ return (FALSE);
+ }
+#endif
+
+#if (DOSX & PHARLAP) && defined(__WATCOMC__)
+ if (_Extender != 1)
+ {
+ fprintf (stderr, "Only DOS4GW style extenders supported.\n");
+ return (FALSE);
+ }
+#endif
+
+ if (!PktSearchDriver())
+ {
+ PUTS ("Packet driver not found.");
+ PktFreeMem();
+ return (FALSE);
+ }
+
+ if (!PktGetDriverInfo())
+ {
+ PUTS ("Error getting pkt-drvr information.");
+ PktFreeMem();
+ return (FALSE);
+ }
+
+#if (DOSX & PHARLAP)
+ if (RealCopy((ULONG)&rxOutOfs, (ULONG)&pktRxEnd,
+ &realBase, &protBase, (USHORT*)&realSeg))
+ {
+ rxOutOfsFp = (WORD _far *) (protBase + (WORD) &rxOutOfs);
+ rxInOfsFp = (WORD _far *) (protBase + (WORD) &rxInOfs);
+ *rxOutOfsFp = FIRST_RX_BUF;
+ *rxInOfsFp = FIRST_RX_BUF;
+ }
+ else
+ {
+ PUTS ("Cannot allocate real-mode stub.");
+ return (FALSE);
+ }
+
+#elif (DOSX & (DJGPP|DOS4GW))
+ if (sizeof(real_stub_array) > 0xFFFF)
+ {
+ fprintf (stderr, "`real_stub_array[]' too big.\n");
+ return (FALSE);
+ }
+#if (DOSX & DJGPP)
+ rm_mem.size = (sizeof(real_stub_array) + 15) / 16;
+
+ if (_go32_dpmi_allocate_dos_memory(&rm_mem) || rm_mem.rm_offset != 0)
+ {
+ PUTS ("real-mode init failed.");
+ return (FALSE);
+ }
+ realBase = (rm_mem.rm_segment << 4);
+ dosmemput (&real_stub_array, sizeof(real_stub_array), realBase);
+ _farpokel (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);
+ _farpokel (_dos_ds, realBase+rxInOfs, FIRST_RX_BUF);
+
+#elif (DOSX & DOS4GW)
+ rm_base_seg = dpmi_real_malloc (sizeof(real_stub_array), &rm_base_sel);
+ if (!rm_base_seg)
+ {
+ PUTS ("real-mode init failed.");
+ return (FALSE);
+ }
+ realBase = (rm_base_seg << 4);
+ memcpy ((void*)realBase, &real_stub_array, sizeof(real_stub_array));
+ *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;
+ *(WORD*) (realBase+rxInOfs) = FIRST_RX_BUF;
+
+#endif
+ {
+ int pushf = PktReceiver;
+
+ while (real_stub_array[pushf++] != 0x9C && /* pushf */
+ real_stub_array[pushf] != 0xFA) /* cli */
+ {
+ if (++para_skip > 16)
+ {
+ fprintf (stderr, "Something wrong with `pkt_stub.inc'.\n");
+ para_skip = 0;
+ dump_pkt_stub();
+ return (FALSE);
+ }
+ }
+ if (*(WORD*)(real_stub_array + offsetof(PktRealStub,_dummy)) != 0xB800)
+ {
+ fprintf (stderr, "`real_stub_array[]' is misaligned.\n");
+ return (FALSE);
+ }
+ }
+
+ if (pcap_pkt_debug > 2)
+ dump_pkt_stub();
+
+#else
+ rxOutOfs = FIRST_RX_BUF;
+ rxInOfs = FIRST_RX_BUF;
+#endif
+
+ if (!PktSetAccess())
+ {
+ PUTS ("Error setting pkt-drvr access.");
+ PktFreeMem();
+ return (FALSE);
+ }
+
+ if (!PktGetAddress(&myAddress))
+ {
+ PUTS ("Error fetching adapter address.");
+ PktFreeMem();
+ return (FALSE);
+ }
+
+ if (!PktSetReceiverMode(mode))
+ {
+ PUTS ("Error setting receiver mode.");
+ PktFreeMem();
+ return (FALSE);
+ }
+
+ if (!PktGetReceiverMode(&rxMode))
+ {
+ PUTS ("Error getting receiver mode.");
+ PktFreeMem();
+ return (FALSE);
+ }
+
+ if (writeInfo)
+ printf ("Pkt-driver information:\n"
+ " Version : %d.%d\n"
+ " Name : %.15s\n"
+ " Class : %u (%s)\n"
+ " Type : %u\n"
+ " Number : %u\n"
+ " Funcs : %u\n"
+ " Intr : %Xh\n"
+ " Handle : %u\n"
+ " Extended : %s\n"
+ " Hi-perf : %s\n"
+ " RX mode : %s\n"
+ " Eth-addr : %02X:%02X:%02X:%02X:%02X:%02X\n",
+
+ pktInfo.majVer, pktInfo.minVer, pktInfo.name,
+ pktInfo.class, PktGetClassName(pktInfo.class),
+ pktInfo.type, pktInfo.number,
+ pktInfo.funcs, pktInfo.intr, pktInfo.handle,
+ pktInfo.funcs == 2 || pktInfo.funcs == 6 ? "Yes" : "No",
+ pktInfo.funcs == 5 || pktInfo.funcs == 6 ? "Yes" : "No",
+ PktRXmodeStr(rxMode),
+ myAddress[0], myAddress[1], myAddress[2],
+ myAddress[3], myAddress[4], myAddress[5]);
+
+#if defined(DEBUG) && (DOSX & PHARLAP)
+ if (writeInfo)
+ {
+ DWORD rAdr = realBase + (WORD)&PktReceiver;
+ unsigned sel, ofs;
+
+ printf ("\nReceiver at %04X:%04X\n", RP_SEG(rAdr), RP_OFF(rAdr));
+ printf ("Realbase = %04X:%04X\n", RP_SEG(realBase),RP_OFF(realBase));
+
+ sel = _FP_SEG (protBase);
+ ofs = _FP_OFF (protBase);
+ printf ("Protbase = %04X:%08X\n", sel,ofs);
+ printf ("RealSeg = %04X\n", realSeg);
+
+ sel = _FP_SEG (rxOutOfsFp);
+ ofs = _FP_OFF (rxOutOfsFp);
+ printf ("rxOutOfsFp = %04X:%08X\n", sel,ofs);
+
+ sel = _FP_SEG (rxInOfsFp);
+ ofs = _FP_OFF (rxInOfsFp);
+ printf ("rxInOfsFp = %04X:%08X\n", sel,ofs);
+
+ printf ("Ready: *rxOutOfsFp = %04X *rxInOfsFp = %04X\n",
+ *rxOutOfsFp, *rxInOfsFp);
+
+ PktQueueBusy (TRUE);
+ printf ("Busy: *rxOutOfsFp = %04X *rxInOfsFp = %04X\n",
+ *rxOutOfsFp, *rxInOfsFp);
+ }
+#endif
+
+ memset (&pktStat, 0, sizeof(pktStat)); /* clear statistics */
+ PktQueueBusy (TRUE);
+ return (TRUE);
+}
+
+
+/*
+ * DPMI functions only for Watcom + DOS4GW extenders
+ */
+#if (DOSX & DOS4GW)
+LOCAL DWORD dpmi_get_real_vector (int intr)
+{
+ union REGS r;
+
+ r.x.eax = 0x200;
+ r.x.ebx = (DWORD) intr;
+ int386 (0x31, &r, &r);
+ return ((r.w.cx << 4) + r.w.dx);
+}
+
+LOCAL WORD dpmi_real_malloc (int size, WORD *selector)
+{
+ union REGS r;
+
+ r.x.eax = 0x0100; /* DPMI allocate DOS memory */
+ r.x.ebx = (size + 15) / 16; /* Number of paragraphs requested */
+ int386 (0x31, &r, &r);
+ if (r.w.cflag & 1)
+ return (0);
+
+ *selector = r.w.dx;
+ return (r.w.ax); /* Return segment address */
+}
+
+LOCAL void dpmi_real_free (WORD selector)
+{
+ union REGS r;
+
+ r.x.eax = 0x101; /* DPMI free DOS memory */
+ r.x.ebx = selector; /* Selector to free */
+ int386 (0x31, &r, &r);
+}
+#endif
+
+
+#if defined(DOSX) && (DOSX & PHARLAP)
+/*
+ * Description:
+ * This routine allocates conventional memory for the specified block
+ * of code (which must be within the first 64K of the protected mode
+ * program segment) and copies the code to it.
+ *
+ * The caller should free up the conventional memory block when it
+ * is done with the conventional memory.
+ *
+ * NOTE THIS ROUTINE REQUIRES 386|DOS-EXTENDER 3.0 OR LATER.
+ *
+ * Calling arguments:
+ * start_offs start of real mode code in program segment
+ * end_offs 1 byte past end of real mode code in program segment
+ * real_basep returned; real mode ptr to use as a base for the
+ * real mode code (eg, to get the real mode FAR
+ * addr of a function foo(), take
+ * real_basep + (ULONG) foo).
+ * This pointer is constructed such that
+ * offsets within the real mode segment are
+ * the same as the link-time offsets in the
+ * protected mode program segment
+ * prot_basep returned; prot mode ptr to use as a base for getting
+ * to the conventional memory, also constructed
+ * so that adding the prot mode offset of a
+ * function or variable to the base gets you a
+ * ptr to the function or variable in the
+ * conventional memory block.
+ * rmem_adrp returned; real mode para addr of allocated
+ * conventional memory block, to be used to free
+ * up the conventional memory when done. DO NOT
+ * USE THIS TO CONSTRUCT A REAL MODE PTR, USE
+ * REAL_BASEP INSTEAD SO THAT OFFSETS WORK OUT
+ * CORRECTLY.
+ *
+ * Returned values:
+ * 0 if error
+ * 1 if success
+ */
+int RealCopy (ULONG start_offs,
+ ULONG end_offs,
+ REALPTR *real_basep,
+ FARPTR *prot_basep,
+ USHORT *rmem_adrp)
+{
+ ULONG rm_base; /* base real mode para addr for accessing */
+ /* allocated conventional memory */
+ UCHAR *source; /* source pointer for copy */
+ FARPTR destin; /* destination pointer for copy */
+ ULONG len; /* number of bytes to copy */
+ ULONG temp;
+ USHORT stemp;
+
+ /* First check for valid inputs
+ */
+ if (start_offs >= end_offs || end_offs > 0x10000)
+ return (FALSE);
+
+ /* Round start_offs down to a paragraph (16-byte) boundary so we can set up
+ * the real mode pointer easily. Round up end_offs to make sure we allocate
+ * enough paragraphs
+ */
+ start_offs &= ~15;
+ end_offs = (15 + (end_offs << 4)) >> 4;
+
+ /* Allocate the conventional memory for our real mode code. Remember to
+ * round byte count UP to 16-byte paragraph size. We alloc it
+ * above the DOS data buffer so both the DOS data buffer and the appl
+ * conventional mem block can still be resized.
+ *
+ * First just try to alloc it; if we can't get it, shrink the appl mem
+ * block down to the minimum, try to alloc the memory again, then grow the
+ * appl mem block back to the maximum. (Don't try to shrink the DOS data
+ * buffer to free conventional memory; it wouldn't be good for this routine
+ * to have the possible side effect of making file I/O run slower.)
+ */
+ len = ((end_offs - start_offs) + 15) >> 4;
+ if (_dx_real_above(len, rmem_adrp, &stemp) != _DOSE_NONE)
+ {
+ if (_dx_cmem_usage(0, 0, &temp, &temp) != _DOSE_NONE)
+ return (FALSE);
+
+ if (_dx_real_above(len, rmem_adrp, &stemp) != _DOSE_NONE)
+ *rmem_adrp = 0;
+
+ if (_dx_cmem_usage(0, 1, &temp, &temp) != _DOSE_NONE)
+ {
+ if (*rmem_adrp != 0)
+ _dx_real_free (*rmem_adrp);
+ return (FALSE);
+ }
+
+ if (*rmem_adrp == 0)
+ return (FALSE);
+ }
+
+ /* Construct real mode & protected mode pointers to access the allocated
+ * memory. Note we know start_offs is aligned on a paragraph (16-byte)
+ * boundary, because we rounded it down.
+ *
+ * We make the offsets come out rights by backing off the real mode selector
+ * by start_offs.
+ */
+ rm_base = ((ULONG) *rmem_adrp) - (start_offs >> 4);
+ RP_SET (*real_basep, 0, rm_base);
+ FP_SET (*prot_basep, rm_base << 4, SS_DOSMEM);
+
+ /* Copy the real mode code/data to the allocated memory
+ */
+ source = (UCHAR *) start_offs;
+ destin = *prot_basep;
+ FP_SET (destin, FP_OFF(*prot_basep) + start_offs, FP_SEL(*prot_basep));
+ len = end_offs - start_offs;
+ WriteFarMem (destin, source, len);
+
+ return (TRUE);
+}
+#endif /* DOSX && (DOSX & PHARLAP) */