⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcpkt.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
/*
 *  Packet Driver interface for WatTCP/Watt-32
 *
 *  Heavily modified and extended for DOSX by
 *  G.Vanem <giva@bgnett.no>
 */

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <string.h>
#include <assert.h>
#include <dos.h>

#include "copyrigh.h"
#include "wattcp.h"
#include "wdpmi.h"
#include "asmpkt.h"
#include "strings.h"
#include "language.h"
#include "misc.h"
#include "profile.h"
#include "pcsed.h"
#include "pcstat.h"
#include "pcconfig.h"
#include "pcmulti.h"
#include "pcqueue.h"

#define DEFINE_IREGS
#include "pcpkt.h"
#include "pcpkt32.h"

/*@-usedef@*/

WORD _pktdevclass = PD_ETHER;     /* Ethernet, Token, FDDI etc.       */
WORD _pkt_ip_ofs  = 0;            /* ofs from link-layer head to ip   */
BYTE _pktserial   = FALSE;        /* using serial driver, SLIP/PPP    */
BYTE _pktdevlevel = 1;            /* basic unless otherwise specified */
BYTE _pkterror    = 0;            /* error code set in pcpkt.c API    */
BYTE _pktretries  = 2;            /* # of retries in pkt_send loop    */

struct pkt_info *_pkt_inf = NULL; /* module data that will be locked. */

static BYTE eth_addr[6]   = { 0,0,0,0,0,0 };
static char pkt_sign[8]   = "PKT DRVR";
static WORD pkt_interrupt = 0;

#if (DOSX & PHARLAP)
  #include <mw/exc.h>
  #ifndef __FLAT__
  #include <pldos32.h>
  #endif
  static REALPTR rm_base;

  /*
   * real-data is organised as follows: PKT_TMP at rm_base + 0x40
   *                                    TX_BUF  at PKT_TMP + 30
   *                                    RX_BUF  at TX_BUF + IP_SIZE
   */
  #define PKT_TMP()   (WORD)0x40
  #define TX_BUF()    (PKT_TMP() + 30)
  #define RX_BUF()    (TX_BUF() + IP_SIZE)
  #define RDATA_SIZE  (RX_BUF() + IP_SIZE)

#elif (DOSX & DJGPP)
  static _go32_dpmi_seginfo rm_cb;
  static __dpmi_regs  rm_reg;
  static DWORD        rm_base;

  /*
   * real-data is organised as follows: PKT_TMP at rm_base + 0
   *                                    TX_BUF  at PKT_TMP + 30
   *                                    RX_BUF  at TX_BUF  + IP_SIZE
   */
  #define PKT_TMP()     0
  #define TX_BUF()      (PKT_TMP() + 30)
  #define RX_BUF()      (TX_BUF() + IP_SIZE)
  #define RDATA_SIZE    (RX_BUF() + IP_SIZE)
  #define RP_SEG()      _pkt_inf->rm_mem.rm_segment

#elif (DOSX & DOS4GW)         /* All DOS4GW type extenders (not WDOSX) */

  static BYTE *rm_base;       /* Linear address (in DOS) for allocated area */
  static WORD  rm_base_seg;   /* DOS-segment for allocated area */
  static WORD  pkt_inf_sel;   /* selector returned from `_pkt_inf' allocation */
  static WORD  pkt_rcv_sel;   /* ditto, from `rm_base' allocation */

  /*
   * The DOS-area (0-1MB) is automagically mapped into application
   * data.  This eases communication with packet-driver, but clean
   * crashes can not be expected. i.e. bugs (dereferencing null-ptr)
   * in application will most likely hang the machine.
   *
   * Real-mode code/data is organised like this:
   *   pkt_receiver4_start copied to allocated area at rm_base
   *   PKT_TMP   at rm_base + (pkt_receiver4_end - pkt_receiver4_start)
   *   TX_BUF    at PKT_TMP + 30
   *   end area  at TX_BUF + IP_SIZE
   *   RX_BUF is in DOS-allocated `_pkt_inf' structure.
   */
  #define PKT_TMP()     ((DWORD)&pkt_receiver4_end -  \
                         (DWORD)&pkt_receiver4_start)
  #define TX_BUF()      (PKT_TMP() + 30)
  #define RCV_OFS()     ((DWORD)&pkt_receiver4_rm - \
                         (DWORD)&pkt_receiver4_start)
  #define RP_SEG()      rm_base_seg

#elif (DOSX & WDOSX)
  static struct DPMI_callback rm_cb;
  static BYTE                *rm_base;
  static WORD                 rm_base_seg;
  static WORD                 rm_base_sel;

  /*
   * real-data is organised as follows: PKT_TMP at rm_base + 0
   *                                    TX_BUF  at PKT_TMP + 30
   *                                    RX_BUF  at TX_BUF  + IP_SIZE
   */
  #define PKT_TMP()     0
  #define TX_BUF()      (PKT_TMP() + 30)
  #define RX_BUF()      (TX_BUF() + IP_SIZE)
  #define RDATA_SIZE    (RX_BUF() + IP_SIZE)
  #define RP_SEG()      rm_base_seg
  #define RCV_OFS()     rm_cb.cb_offset

#elif (DOSX & POWERPAK)    /* to-do !! */
  #define PKT_TMP()     0  /* for now */
  #define TX_BUF()      (PKT_TMP() + 30)
  #define RX_BUF()      (TX_BUF() + IP_SIZE)
  #define RDATA_SIZE    (RX_BUF() + IP_SIZE)
  #define RP_SEG()      0

#else  /* r-mode targets */

  void (_cdecl _far * pkt_enque_ptr) (BYTE _far *buf, WORD len, WORD handle);
  void (_cdecl _far *_pkt_enque_ptr) (BYTE _far *buf, WORD len, WORD handle);

  #ifdef _MSC_VER       /* 16-bit Microsoft C compilers (v6+) */
    #undef  FP_SEG
    #undef  FP_OFF
  //#define FP_SEG(p) (WORD)((DWORD)(p) >> 16)
  //#define FP_OFF(p) (WORD)((DWORD)(p) & 0xFFFF)
    #define FP_SEG(p) ((unsigned)(_segment)(void _far *)(p))
    #define FP_OFF(p) ((unsigned)(p))
  #endif
#endif

#if (DOSX)
  static int setup_rmode_callback (void);
  static int lock_code_and_data   (void);
  static int unlock_code_and_data (void);
#endif
        
static int  release_handles (BOOL quiet);
static WORD find_vector (int first, int num);
static int  setup_pkt_inf (void);
static int  pkt_api_entry (IREGS *reg, unsigned called_from_line);

#define PKT_API(reg)     pkt_api_entry (reg, __LINE__)
#define CARRY_BIT        1   /* carry bit in flags register */

#define PKT_ERR(str,dx)  do {                                              \
                           const char *s = pkt_errStr ((BYTE)((dx) >> 8)); \
                           outs (_LANG(str));                              \
                           outsnl (s);                                     \
                         } while (0)


/*
 * Return textual error representing error-code.
 */
static const char * pkt_errStr (BYTE code)
{
  static char  buf[50];
  static const char *err[] = {
              __LANG("Unknown driver error \0(0x--)"),
              __LANG("Invalid handle number"),
              __LANG("No interfaces of specified class found"),
              __LANG("No interfaces of specified type found"),
              __LANG("No interfaces of specified number found"),
              __LANG("Bad packet type specified"),
              __LANG("This interface does not support multicast"),
              __LANG("This packet driver cannot terminate"),
              __LANG("An invalid receiver mode was specified"),
              __LANG("Operation failed because of insufficient space"),
              __LANG("Type previously accessed, and not released"),
              __LANG("The command was out of range, or not implemented"),
              __LANG("Cannot send packet (hardware error)"),
              __LANG("Cannot change hardware address"),
              __LANG("Hardware address has bad length/format"),
              __LANG("Could not reset interface"),
              __LANG("Extended driver needed")
            };
  char *p;

  _pkterror = code;
  if (code && code < DIM(err))
     return (_LANG (err[code]));

  p = strchr (err[0], 0);
  *(p+4) = hex_CHARS [code >> 4];
  *(p+5) = hex_CHARS [code & 15];
  strcpy (buf, _LANG (err[0]));
  return strcat (buf, p+1);
}


#if (DOSX & DOS4GW) && 0     /* test asmpkt4.asm !! */
static void dump_asm4 (void)
{
  BYTE *p = rm_base;
  int   i;

  printf ("PKT_INF %08lX, HEAD %08lX, QUEUE %08lX, INDEX %04X, XYPOS %d\n",
          *(DWORD*)p, *(DWORD*)(p+4), *(DWORD*)(p+8), *(WORD*)(p+12),
          *(WORD*)(p+14));

  printf ("rm_base %08lX, ip_handle %04X, arp_handle %04X, is_serial %d\n",
          rm_base, _pkt_inf->ip_handle, _pkt_inf->arp_handle,
          _pkt_inf->is_serial);

  printf ("VAR_1-14: ");
  for (i = 16; i <= 42; i += 2)
     printf ("%04X ", *(WORD*)(p+i));

#if 0
  printf ("PKT_RECV: ");
  for (i = RCV_OFS(); i < RCV_OFS()+10; i++)
     printf ("%02X ", p[i]);

  printf ("\nPKT_TMP:  ");
  for (i = PKT_TMP(); i < PKT_TMP()+30; i++)
     printf ("%02X ", p[i]);
#endif
  fflush (stdout);
}
#endif


/*
 * Return array specifying what MAC framing to use for all supported
 * protocols (IP/ARP/RARP). 'len' is size of one array element (2, 4 or 8).
 */
static BYTE *get_access_types (int *len, int *num)
{
  static BYTE eth_types [5*2];
  static BYTE llc_types [3*8] = { TR_DSAP, TR_SSAP, TR_CTRL, 0,0,0,0,0,
                                  TR_DSAP, TR_SSAP, TR_CTRL, 0,0,0,0,0,
                                  TR_DSAP, TR_SSAP, TR_CTRL, 0,0,0,0,0
                                };
  if (_pktserial)  /* Serial driver don't need this */
  {
    *len = 0;
    *num = 0;
    return (NULL);
  }
  if (_pktdevclass == PD_TOKEN ||
      _pktdevclass == PD_FDDI)     /* correct? */
  {
    *(WORD*) (llc_types+ 6) = IP_TYPE;
    *(WORD*) (llc_types+12) = ARP_TYPE;
    *(WORD*) (llc_types+18) = RARP_TYPE;
    *len = 8;
    *num = 3;
    return (llc_types);
  }

  /* PD_ETHER
   */
  *(WORD*) (eth_types+0) = IP_TYPE;
  *(WORD*) (eth_types+2) = ARP_TYPE;
  *(WORD*) (eth_types+4) = RARP_TYPE;
  *(WORD*) (eth_types+6) = PPPOE_DISC_TYPE;
  *(WORD*) (eth_types+8) = PPPOE_SESS_TYPE;
  *num = 5;
  *len = 2;
  return (eth_types);
}

/**************************************************************************/

static int pkt_set_access (void)
{
  IREGS regs, regs2, regs3, regs4, regs5;

  BYTE *types;
  int   tlen = 0;
  int   num_types;

  ASSERT_PKT_INF (0);

  memset (&regs, 0, sizeof(regs));

  types = get_access_types (&tlen, &num_types);

  regs.r_ax  = PD_ACCESS | _pktdevclass;
  regs.r_bx  = 0xFFFF;                   /* any type          */
  regs.r_dx  = 0;                        /* generic interface */
  regs.r_cx  = tlen;

#if (DOSX & PHARLAP)
  if (types)
     WriteRealMem (rm_base + PKT_TMP(), types, num_types*tlen);

  /* if CX is 0, there should be no harm setting DS:DI
   */
  regs.r_ds = RP_SEG (rm_base);
  regs.r_si = PKT_TMP();
  regs.r_es = RP_SEG (rm_base);          
  regs.r_di = 0;                         /* RMCB aligned at para address */
  memcpy (&regs2, &regs, sizeof(regs2)); /* make copy for ARP type */
  regs2.r_si += tlen;
  memcpy (&regs3, &regs, sizeof(regs3)); /* make copy for RARP type */
  regs3.r_si += sizeof(WORD)*tlen;
  memcpy (&regs4, &regs, sizeof(regs4)); /* make copy for PPPoE type */
  regs4.r_si += sizeof(WORD)*tlen;
  memcpy (&regs5, &regs, sizeof(regs5)); /* make copy for PPPoE type */
  regs5.r_si += sizeof(WORD)*tlen;

#elif (DOSX & DJGPP)
  if (tlen)
     dosmemput (types, num_types*tlen, rm_base + PKT_TMP());

  regs.r_ds = RP_SEG();
  regs.r_si = PKT_TMP();
  regs.r_es = rm_cb.rm_segment;
  regs.r_di = rm_cb.rm_offset;
  memcpy (&regs2, &regs, sizeof(regs2));
  regs2.r_si += tlen;
  memcpy (&regs3, &regs, sizeof(regs3));
  regs3.r_si += sizeof(WORD)*tlen;
  memcpy (&regs4, &regs, sizeof(regs4));
  regs4.r_si += sizeof(WORD)*tlen;
  memcpy (&regs5, &regs, sizeof(regs5));
  regs5.r_si += sizeof(WORD)*tlen;

#elif (DOSX & DOS4GW)
  if (tlen)
     memcpy ((void*)(rm_base + PKT_TMP()), types, num_types*tlen);

  regs.r_ds = RP_SEG();
  regs.r_si = PKT_TMP();
  regs.r_es = RP_SEG();
  regs.r_di = RCV_OFS();
  memcpy (&regs2, &regs, sizeof(regs2));
  regs2.r_si += tlen;
  memcpy (&regs3, &regs, sizeof(regs3));
  regs3.r_si += sizeof(WORD)*tlen;
  memcpy (&regs4, &regs, sizeof(regs4));
  regs4.r_si += sizeof(WORD)*tlen;
  memcpy (&regs5, &regs, sizeof(regs5));
  regs5.r_si += sizeof(WORD)*tlen;

#elif (DOSX & WDOSX)
  if (tlen)
     memcpy ((void*)(rm_base + PKT_TMP()), types, num_types*tlen);

  regs.r_ds = RP_SEG();
  regs.r_si = PKT_TMP();
  regs.r_es = rm_cb.cb_segment;
  regs.r_di = rm_cb.cb_offset;
  memcpy (&regs2, &regs, sizeof(regs2));
  regs2.r_si += tlen;
  memcpy (&regs3, &regs, sizeof(regs3));
  regs3.r_si += sizeof(WORD)*tlen;
  memcpy (&regs4, &regs, sizeof(regs4));
  regs4.r_si += sizeof(WORD)*tlen;
  memcpy (&regs5, &regs, sizeof(regs5));
  regs5.r_si += sizeof(WORD)*tlen;

#elif (DOSX & POWERPAK)
  UNFINISHED();

#else /* real-mode targets */
  if (types)
  {
    regs.r_ds = FP_SEG (&types[0]);       /* = global DS */
    regs.r_si = FP_OFF (&types[0]);
  }
  regs.r_es = FP_SEG (pkt_receiver_rm);   /* = this CS */
  regs.r_di = FP_OFF (pkt_receiver_rm);

  memcpy (&regs2, &regs, sizeof(regs2));
  regs2.r_si += tlen;
  memcpy (&regs3, &regs, sizeof(regs3));
  regs3.r_si += sizeof(WORD)*tlen;
  memcpy (&regs4, &regs, sizeof(regs4));
  regs4.r_si += sizeof(WORD)*tlen;
  memcpy (&regs5, &regs, sizeof(regs5));
  regs5.r_si += sizeof(WORD)*tlen;
#endif

  if (!PKT_API(&regs))
  {
    PKT_ERR ("Error allocating IP handle: ", regs.r_dx);
    return (0);
  }
  _pkt_inf->ip_handle = regs.r_ax;

  if (_pktserial)
     return (1);

  if (!PKT_API(&regs2))
  {
    PKT_ERR ("Error allocating ARP handle: ", regs2.r_dx);
    return (0);
  }
  _pkt_inf->arp_handle = regs2.r_ax;

#if defined(USE_RARP)
  if (!PKT_API(&regs3))
  {
    PKT_ERR ("Error allocating RARP handle: ", regs3.r_dx);
    return (0);
  }
  _pkt_inf->rarp_handle = regs3.r_ax;
#endif

#if defined(USE_PPPOE)
  if (!PKT_API(&regs4))
  {
    PKT_ERR ("Error allocating PPPoE discovery handle: ", regs4.r_dx);
    return (0);
  }
  _pkt_inf->pppoe_disc_handle = regs4.r_ax;

  if (!PKT_API(&regs5))
  {
    PKT_ERR ("Error allocating PPPoE session handle: ", regs5.r_dx);
    return (0);
  }
  _pkt_inf->pppoe_sess_handle = regs5.r_ax;
#endif

  return (1);
}

/**************************************************************************/

static int pkt_drvr_info (void)
{
  IREGS regs;

  ASSERT_PKT_INF (0);

  /* Lets find out about the driver
   */
  regs.r_ax = PD_DRIVER_INFO;  

  /* Handle old versions, assume a class and just keep trying
   * This method will fail for Token-Ring
   */
  if (!PKT_API(&regs))
  {
    int class;
  
    for (class = 0; class < 2; class++)   /* test for SLIP/Ether */
    {
      static WORD ip_type = IP_TYPE;
      int    max_type = 128;
      int    type;

      _pktdevclass = (class ? PD_SLIP : PD_ETHER);

      for (type = 1; type < max_type; type++)
      {
        regs.r_ax = PD_ACCESS | _pktdevclass;  /* ETH, SLIP */
        regs.r_bx = type;                      /* pkt type  */
        regs.r_dx = 0;                         /* iface num */
        regs.r_cx = class ? sizeof(ip_type) : 0;
#if (DOSX & PHARLAP)
        PokeRealWord (rm_base + PKT_TMP(), ip_type);
        regs.r_ds = RP_SEG (rm_base);
        regs.r_si = PKT_TMP();
        regs.r_es = RP_SEG (rm_base);
        regs.r_di = 0;
#elif (DOSX & DJGPP)
        _farpokew (_dos_ds, rm_base + PKT_TMP(), ip_type);
        regs.r_ds = RP_SEG();
        regs.r_si = PKT_TMP();
        regs.r_es = rm_cb.rm_segment;
        regs.r_di = rm_cb.rm_offset;
#elif (DOSX & DOS4GW)
        *(WORD*) (rm_base + PKT_TMP()) = ip_type;
        regs.r_ds = RP_SEG();
        regs.r_si = PKT_TMP();
        regs.r_es = RP_SEG();
        regs.r_di = RCV_OFS();
#elif (DOSX & WDOSX)
        *(WORD*) (rm_base + PKT_TMP()) = ip_type;
        regs.r_ds = RP_SEG();
        regs.r_si = PKT_TMP();
        regs.r_es = rm_cb.cb_segment;
        regs.r_di = rm_cb.cb_offset;
#elif (DOSX & POWERPAK)
        UNFINISHED();
#else
        regs.r_ds = FP_SEG (&ip_type);
        regs.r_si = FP_OFF (&ip_type);
        regs.r_es = FP_SEG (pkt_receiver_rm);
        regs.r_di = FP_OFF (pkt_receiver_rm);
#endif
        if (PKT_API(&regs))
           break;
      }

      if (type == max_type)
      {
        outsnl (_LANG("Error initializing packet driver"));
        return (0);
      }
      /* we have found a working type, so kill it
       */
      regs.r_bx = regs.r_ax;      /* handle */
      regs.r_ax = PD_RELEASE;
      PKT_API (&regs);
    }
  }
  else          /* new Packet-Driver (1.09+) */
  {
    _pktdevlevel = (regs.r_ax & 0xFF);
    _pktdevclass = (BYTE)(regs.r_cx >> 8);

    switch (_pktdevclass)
    {
      case PD_TOKEN:
           _pkt_ip_ofs = sizeof(tok_Header);
           break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -