diff options
Diffstat (limited to 'msdos/pktdrvr.c')
-rw-r--r-- | msdos/pktdrvr.c | 2872 |
1 files changed, 1436 insertions, 1436 deletions
diff --git a/msdos/pktdrvr.c b/msdos/pktdrvr.c index cd22ee6..37fc8a4 100644 --- a/msdos/pktdrvr.c +++ b/msdos/pktdrvr.c @@ -1,1436 +1,1436 @@ -/*
- * File.........: pktdrvr.c
- *
- * Responsible..: Gisle Vanem, giva@bgnett.no
- *
- * 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) */
+/* + * File.........: pktdrvr.c + * + * Responsible..: Gisle Vanem, giva@bgnett.no + * + * 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) */ |