📄 pcpkt.c
字号:
{
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(®s))
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(®s))
{
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(®s))
return (0);
memcpy (ð_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, ð_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 + -