📄 pcpkt.c
字号:
/*
* 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 (®s, 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 (®s2, ®s, sizeof(regs2)); /* make copy for ARP type */
regs2.r_si += tlen;
memcpy (®s3, ®s, sizeof(regs3)); /* make copy for RARP type */
regs3.r_si += sizeof(WORD)*tlen;
memcpy (®s4, ®s, sizeof(regs4)); /* make copy for PPPoE type */
regs4.r_si += sizeof(WORD)*tlen;
memcpy (®s5, ®s, 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 (®s2, ®s, sizeof(regs2));
regs2.r_si += tlen;
memcpy (®s3, ®s, sizeof(regs3));
regs3.r_si += sizeof(WORD)*tlen;
memcpy (®s4, ®s, sizeof(regs4));
regs4.r_si += sizeof(WORD)*tlen;
memcpy (®s5, ®s, 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 (®s2, ®s, sizeof(regs2));
regs2.r_si += tlen;
memcpy (®s3, ®s, sizeof(regs3));
regs3.r_si += sizeof(WORD)*tlen;
memcpy (®s4, ®s, sizeof(regs4));
regs4.r_si += sizeof(WORD)*tlen;
memcpy (®s5, ®s, 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 (®s2, ®s, sizeof(regs2));
regs2.r_si += tlen;
memcpy (®s3, ®s, sizeof(regs3));
regs3.r_si += sizeof(WORD)*tlen;
memcpy (®s4, ®s, sizeof(regs4));
regs4.r_si += sizeof(WORD)*tlen;
memcpy (®s5, ®s, 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 (®s2, ®s, sizeof(regs2));
regs2.r_si += tlen;
memcpy (®s3, ®s, sizeof(regs3));
regs3.r_si += sizeof(WORD)*tlen;
memcpy (®s4, ®s, sizeof(regs4));
regs4.r_si += sizeof(WORD)*tlen;
memcpy (®s5, ®s, sizeof(regs5));
regs5.r_si += sizeof(WORD)*tlen;
#endif
if (!PKT_API(®s))
{
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(®s2))
{
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(®s3))
{
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(®s4))
{
PKT_ERR ("Error allocating PPPoE discovery handle: ", regs4.r_dx);
return (0);
}
_pkt_inf->pppoe_disc_handle = regs4.r_ax;
if (!PKT_API(®s5))
{
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(®s))
{
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(®s))
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 (®s);
}
}
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 + -