Blame msdos/pktdrvr.c

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