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

📄 pcpkt.c

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 C
📖 第 1 页 / 共 4 页
字号:
      {
        r->r_es = 0;
        r->r_di = 0;
      }
      else
      {
        r->r_es = RP_SEG();
        r->r_di = RX_BUF();
      }
    }
    else if (_pkt_inf && r->r_si)
    {
      static UINT stack [256];  /* !!fix-me: not locked */

      stackset (stack[256-1]);
      pkt_enqueue (RX_BUF(), r->r_cx, r->r_bx);
      stackrestore();
    }
    __asm {   /* make IRET from this near function */
      pop ebp
      iret
    }
    /* not reached */
  }

#elif (DOSX & POWERPAK)
  static void pkt_receiver_pm (IREGS *r)
  {
    UNFINISHED();

    if ((BYTE)r->r_ax == 0)
    {
      if (!_pkt_inf || r->r_cx > ETH_MAX)
      {
        r->r_es = 0;
        r->r_di = 0;
      }
      else
      {
        r->r_es = RP_SEG();
        r->r_di = RX_BUF();
      }
    }
    else if (r->r_si && _pkt_inf)
            pkt_enqueue (RX_BUF(), r->r_cx, r->r_bx);
  }
#endif

void _pkt_end (void) {}

#endif  /* !(DOSX & DOS4GW) */

/* Restore default stack checking and tracing
 */
#if defined(__HIGHC__)   
#pragma pop(check_stack)
#pragma pop(call_trace)
#pragma pop(prolog_trace)
#pragma pop(epilog_trace)
#endif

#if defined(__WATCOMC__)
#pragma pop(check_stack)
#endif

#if defined(_MSC_VER_)
#pragma pop(check_stack)
#endif

#if (defined(__TURBOC__) || defined(__BORLANDC__)) && !defined(OLD_TURBOC)
#pragma option -N.
#endif


/*
 * Send a link-layer frame. For PPP/SLIP 'tx' contains no MAC-header.
 * For EtherNet, Token-Ring and FDDI, 'tx' contains the complete frame.
 */
int pkt_send (const void *tx, int length)
{
  IREGS regs;
  WORD  seg, ofs;
  int   tx_cnt;

  START_PROFILE ("pkt_send");

  ASSERT_PKT_INF (0);

#if (DOSX & PHARLAP)
  seg = RP_SEG (rm_base);
  ofs = TX_BUF();
  WriteRealMem (rm_base + ofs, (void*)tx, length);

#elif (DOSX & DJGPP)
  seg = RP_SEG();
  ofs = TX_BUF();
  dosmemput (tx, length, rm_base + ofs);

#elif (DOSX & (DOS4GW|WDOSX))
  seg = RP_SEG();
  ofs = TX_BUF();
  memcpy (rm_base + ofs, tx, length);

#elif (DOSX & POWERPAK)
  UNFINISHED();

#else
  seg = FP_SEG (tx);
  ofs = FP_OFF (tx);
  /* it's no need to copy anything
   */
#endif

  tx_cnt = 1 + _pktretries;

  while (tx_cnt--)
  {
    regs.r_ax = PD_SEND;
    regs.r_ds = seg;
    regs.r_si = ofs;
    regs.r_cx = length;
    if (!PKT_API(&regs))
       continue;

    STOP_PROFILE();
    return (length);
  }
  STOP_PROFILE();
  STAT (macstats.num_tx_err++);
  return (0);
}

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

int pkt_get_addr (eth_address *eth)
{
  IREGS regs;

  ASSERT_PKT_INF (0);

  regs.r_ax = PD_GET_ADDRESS;
  regs.r_bx = _pkt_inf->ip_handle;
  regs.r_cx = sizeof (*eth);

#if (DOSX & PHARLAP)
  regs.r_es = RP_SEG (rm_base);
  regs.r_di = PKT_TMP();

#elif (DOSX & (DJGPP|DOS4GW|WDOSX))
  regs.r_es = RP_SEG();
  regs.r_di = PKT_TMP();

#elif (DOSX & POWERPAK)
  UNFINISHED();

#else
  regs.r_es = FP_SEG (eth);
  regs.r_di = FP_OFF (eth);
#endif

  if (!PKT_API(&regs))
  {
    outsnl (_LANG("ERROR: Cannot read ethernet address"));
    return (0);
  }

#if (DOSX & PHARLAP)
  ReadRealMem (eth, rm_base + PKT_TMP(), sizeof(*eth));

#elif (DOSX & DJGPP)
  dosmemget (rm_base + PKT_TMP(), sizeof(*eth), eth);

#elif (DOSX & (DOS4GW|WDOSX))
  memcpy (eth, rm_base + PKT_TMP(), sizeof(*eth));

#elif (DOSX & POWERPAK)
  UNFINISHED();
#endif
  return (1);
}

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

int pkt_set_addr (eth_address *eth)
{
  IREGS regs;

  ASSERT_PKT_INF (0);

  regs.r_ax = PD_SET_ADDR;
  regs.r_cx = sizeof (*eth);

#if (DOSX & PHARLAP)
  WriteRealMem (rm_base + PKT_TMP(), (void*)eth, sizeof(*eth));
  regs.r_es = RP_SEG (rm_base);
  regs.r_di = PKT_TMP();

#elif (DOSX & DJGPP)
  dosmemput ((void*)eth, sizeof(*eth), rm_base + PKT_TMP());
  regs.r_es = RP_SEG();
  regs.r_di = PKT_TMP();

#elif (DOSX & (DOS4GW|WDOSX))
  memcpy (rm_base + PKT_TMP(), eth, sizeof(*eth));
  regs.r_es = RP_SEG();
  regs.r_di = PKT_TMP();

#elif (DOSX & POWERPAK)
  UNFINISHED();

#else
  regs.r_es = FP_SEG (eth);
  regs.r_di = FP_OFF (eth);
#endif

  if (!PKT_API(&regs))
     return (0);

  memcpy (&eth_addr, eth, sizeof(*eth));
  return (1);
}

/*
 *  Clear both the IP and ARP queues.
 */
int pkt_buf_wipe (void)
{
  ASSERT_PKT_INF (0);
  pktq_clear (&_pkt_inf->ip_queue);
  pktq_clear (&_pkt_inf->arp_queue);
  return (1);
}

/*
 *  Release an IP or ARP/RARP packet.
 */
void pkt_free_pkt (const void *pkt, BOOL is_ip)
{
  struct pkt_ringbuf *q;

  if (!_pkt_inf || !pkt)
     return;

  q = is_ip ? &_pkt_inf->ip_queue : &_pkt_inf->arp_queue;

  if (pkt != (const void*) (pktq_out_buf(q) + _pkt_ip_ofs))
  {
#if defined(USE_DEBUG)
    (*_printf) ("%s: freeing illegal %s packet %ph.\r\n",
                __FILE__, is_ip ? "IP" : "ARP/RARP", pkt);
#endif
    pktq_clear (q);
  }
  else
    pktq_inc_out (q);
}


/*
 *  Return number of packets waiting in queues
 */
int pkt_waiting_ip (void)
{
  if (_pkt_inf)
     return pktq_queued (&_pkt_inf->ip_queue);
  return (-1);
}

int pkt_waiting_arp (void)
{
  if (_pkt_inf)
     return pktq_queued (&_pkt_inf->arp_queue);
  return (-1);
}

int pkt_waiting (void)
{
  if (_pkt_inf)
     return pktq_queued (&_pkt_inf->ip_queue) +
            pktq_queued (&_pkt_inf->arp_queue);
  return (-1);
}

/*
 *  Return number of packets dropped.
 *  Reset counter afterwards.
 */
int pkt_dropped_ip (void)
{
  int n = -1;

  if (_pkt_inf)
  {
    n = (int)_pkt_inf->ip_queue.num_drop;
    _pkt_inf->ip_queue.num_drop = 0;
  }
  return (n);
}

int pkt_dropped_arp (void)
{
  int n = -1;

  if (_pkt_inf)
  {
    n = (int)_pkt_inf->arp_queue.num_drop;
    _pkt_inf->arp_queue.num_drop = 0;
  }
  return (n);
}

int pkt_dropped (void)
{
  return pkt_dropped_ip() + pkt_dropped_arp();
}

/*
 *  Initialise Packet driver interface. First determine vector to use;
 *  if env. vars WATTCP.VEC or TCP_PKTINT is specified, use that vector,
 *  else search for PKTDRVR between PKT_FIRST_VEC and PKT_LAST_VEC
 *  (0x60 - 0x80).
 *
 *  Note: Env-var "TCP_PKTINT" is for compatibility with
 *        tcplib for djgpp.
 *
 *  If DOSX, probe and initialise protected-mode driver.
 *  Call pkt_init() to initialise API.
 */
BOOL pkt_eth_init (eth_address *eth)
{
  char *rm_vector = getenv ("WATTCP.VEC");
  int   drvr_ok   = 0;

  if (rm_vector)
  {
    pkt_interrupt = atox (rm_vector);
    if (pkt_interrupt < PKT_FIRST_VEC || pkt_interrupt > PKT_LAST_VEC)
        pkt_interrupt = 0;  /* discard illegal value */
  }
  else if ((rm_vector = getenv ("TCP_PKTINT")) != NULL)
  {
    pkt_interrupt = atox (rm_vector);
    if (pkt_interrupt < PKT_FIRST_VEC || pkt_interrupt > PKT_LAST_VEC)
        pkt_interrupt = 0;  /* discard illegal value */
  }
  else
    pkt_interrupt = 0;


  {
#if (DOSX)
    int pm_driver = pkt32_drvr_probe (pm_driver_list);

    drvr_ok = (pm_driver > 0 && pkt32_drvr_init(pm_driver) != 0);

#if defined(USE_DEBUG)
    if (pm_driver)
       (*_printf) ("Using Pmode `%s' driver at %08lX",
                   pkt32_drvr_name(pm_driver), (DWORD)_pkt32_drvr);
#endif

    if (!drvr_ok)  /* pmode driver failed, try rmode driver */
#endif
      drvr_ok = (pkt_init() != 0);

    if (!drvr_ok)
       return (FALSE);  /* no suitable driver found */
  }
  memcpy (eth, &eth_addr, sizeof(*eth));
  return (TRUE);
}

/*
 *  Find the interrupt for the PKTDRVR by searching interrupt handler
 *  entries (at vector+3) for signature string "PKT DRVR".
 */
#if (DOSX & PHARLAP)
  static WORD find_vector (int first, int num)
  {
    WORD vector;

    for (vector = first; vector < first+num; vector++)
    {
      char    temp[16];
      REALPTR rp;

      _dx_rmiv_get ((UINT)vector, &rp);
      if (rp)
      {
        ReadRealMem (&temp, rp, sizeof(temp));
        if (!memcmp(temp+3, &pkt_sign, sizeof(pkt_sign)))
           return (vector);
      }
    }
    return (0);
  }

#elif (DOSX & DJGPP)
  static WORD find_vector (int first, int num)
  {
    WORD vector;

    for (vector = first; vector < first+num; vector++)
    {
      char  temp[16];
      DWORD rp;
      __dpmi_raddr realAdr;

      __dpmi_get_real_mode_interrupt_vector (vector, &realAdr);
      rp = (realAdr.segment << 4) + realAdr.offset16;
      if (rp)
      {
        dosmemget (rp, sizeof(temp), &temp);
        if (!memcmp(temp+3, &pkt_sign, sizeof(pkt_sign)))
           return (vector);
      }
    }
    return (0);
  }

#elif (DOSX & (DOS4GW|WDOSX))
  static WORD find_vector (int first, int num)
  {
    WORD vector;

    for (vector = first; vector < first+num; vector++)
    {
      BYTE *addr = (BYTE*) dpmi_get_real_vector (vector);

      if (addr && !memcmp(addr+3, &pkt_sign, sizeof(pkt_sign)))
         return (vector);
    }
    return (0);
  }

#elif (DOSX & POWERPAK)
  static WORD find_vector (int first, int num)
  {
    UNFINISHED();
    return (0);
  }

#else       /* real-mode version */
  static WORD find_vector (int first, int num)
  {
    WORD vector;

     pkt_enque_ptr = pkt_enqueue;
    _pkt_enque_ptr = pkt_enqueue;

    for (vector = first; vector < first+num; vector++)
    {
      char _far *addr = (char _far*) getvect(vector);

      if (addr && !_fmemcmp (addr+3, &pkt_sign, sizeof(pkt_sign)))
         return (vector);
    }
    return (0);
  }
#endif


/*
 *  DOS-extender functions for allocation a real-mode callback that
 *  the real-mode PKTDRVR will call when a packet is received.
 *  Lock down all code and data that is touched in this callback.
 */
#if (DOSX & PHARLAP)
  static int setup_rmode_callback (void)
  {
    rm_base = _dx_alloc_rmode_wrapper_retf (pkt_receiver_pm, NULL,
                                            RDATA_SIZE, 1024);
    if (!rm_base)
       return (-1);
    return (0);
  }

  static int lock_code_and_data (void) /* Needed for 386|VMM only (?) */
  {
    UINT size = (UINT)&_pkt_end - (UINT)&pkt_enqueue;

    _dx_lock_pgsn ((void*)&pkt_enqueue, size);
    _dx_lock_pgsn ((void*)&ReadRealMem, 100);
    _dx_lock_pgsn ((void*)_pkt_inf, sizeof(*_pkt_inf));
    return (0);
  }

  static int unlock_code_and_data (void)
  {
    UINT size = (UINT)&_pkt_end - (UINT)&pkt_enqueue;

    _dx_ulock_pgsn ((void*)&pkt_enqueue, size);
    _dx_ulock_pgsn ((void*)&ReadRealMem, 100);
    _dx_ulock_pgsn ((void*)_pkt_inf, sizeof(*_pkt_inf));
    return (0);
  }

#elif (DOSX & DJGPP)
  static int setup_rmode_callback (void)
  {
    int i;

    rm_cb.pm_offset       = (DWORD) &pkt_receiver_pm;
    _pkt_inf->rm_mem.size = (RDATA_SIZE + 15) / 16;

    if (_go32_dpmi_allocate_dos_memory(&_pkt_inf->rm_mem))
       return (-2);

    if (_go32_dpmi_allocate_real_mode_callback_retf(&rm_cb,&rm_reg))
       return (-1);

    if (_pkt_inf->rm_mem.rm_offset != 0)
       return (-2);

    rm_base = (_pkt_inf->rm_mem.rm_segment << 4);
    for (i = 0; i < RDATA_SIZE/4; i++)
        _farpokel (_dos_ds, rm_base + 4*i, 0L);

  #if 0  /* test */
    (*_printf) ("rm_mem = %04X:%04X  rmode call-back %04X:%04X\r\n",
                _pkt_inf->rm_mem.rm_segment, _pkt_inf->rm_mem.rm_offset,
                rm_cb.rm_segment, rm_cb.rm_offset);
  #endif
    return (0);
  }

  static int lock_code_and_data (void)
  {

⌨️ 快捷键说明

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