00001
00009
#include <stdio.h>
00010
#include <stdlib.h>
00011
#include <stddef.h>
00012
#include <string.h>
00013
#include <limits.h>
00014
00015
00016
00017
00018
#if !defined(WIN32) && !defined(_WIN32)
00019
00020
#if defined(__DJGPP__)
00021
#include <sys/exceptn.h>
00022
#include <sys/nearptr.h>
00023
#include <crt0.h>
00024
#endif
00025
00026
#include "copyrigh.h"
00027
#include "wattcp.h"
00028
#include "wdpmi.h"
00029
#include "x32vm.h"
00030
#include "powerpak.h"
00031
#include "asmpkt.h"
00032
#include "strings.h"
00033
#include "language.h"
00034
#include "sock_ini.h"
00035
#include "cpumodel.h"
00036
#include "misc.h"
00037
#include "timer.h"
00038
#include "profile.h"
00039
#include "pcsed.h"
00040
#include "pcstat.h"
00041
#include "pcconfig.h"
00042
#include "pcdbug.h"
00043
#include "pcmulti.h"
00044
#include "pcqueue.h"
00045
#include "pcpkt.h"
00046
#include "pcpkt32.h"
00047
00048
00049
00050
00051 WORD _pktdevclass = PDCLASS_UNKNOWN;
00052 WORD _pkt_ip_ofs = 0;
00053 WORD _pkt_type_ofs = 0;
00054 BOOL
_pktserial = FALSE;
00055 BYTE _pktdevlevel = 1;
00056 int _pkt_rxmode =
RXMODE_BROADCAST;
00057 int _pkt_rxmode0 = -1;
00058 int _pkt_errno = 0;
00059 const char *
pkt_error = NULL;
00061
int _pkt_forced_rxmode = -1;
00062
char _pktdrvrname[20] =
"unknown";
00063
00064 struct pkt_info *
_pkt_inf = NULL;
00066
static char pkt_sign[] =
"PKT DRVR";
00067
static WORD pkt_interrupt = 0;
00068
static DWORD pkt_drop_cnt = 0;
00069
static BYTE pkt_txretries = 2;
00070
static int pkt_txwait = 0;
00071
static BOOL pkt_use_near = FALSE;
00072
static BOOL pkt_do_reset = FALSE;
00073
static int pkt_drvr_ver = 0;
00074
static int pkt_num_rx_bufs = RX_BUFS;
00075
00076
#if defined(USE_STATISTICS)
00077
static struct PktStats init_stats;
00078
static void get_init_stats (
void);
00079
#endif
00080
00081
static struct PktParameters pkt_params;
00082
static BOOL got_params = FALSE;
00083
00088
#define PKT_FIRST_VEC 0x60
00089
#define PKT_LAST_VEC 0x80
00090
#define PKT_FIRST_VEC_11 0x20
00091
#define PKT_LAST_VEC_11 0xFF
00092
00093
00094
#if (DOSX & PHARLAP)
00095
#include <mw/exc.h>
00096
00097 REALPTR rm_base;
00098
00099
00100
00101
00102
00103
00104
#define PKT_TMP() (WORD) 0x40
00105
#define TX_BUF() (PKT_TMP() + PKT_TMP_SIZE)
00106
#define RX_BUF() (TX_BUF() + RX_SIZE)
00107
#define RDATA_SIZE (RX_BUF() + RX_SIZE)
00108
#define RP_SEGM() RP_SEG (rm_base)
00109
00110
#elif (DOSX & X32VM)
00111 REALPTR rm_base;
00112
00113
#define PKT_TMP() (WORD) 0x40
00114
#define TX_BUF() (PKT_TMP() + PKT_TMP_SIZE)
00115
#define RX_BUF() (TX_BUF() + RX_SIZE)
00116
#define RDATA_SIZE (RX_BUF() + RX_SIZE)
00117
#define RP_SEGM() RP_SEG (rm_base)
00118
00119
#elif (DOSX & DJGPP)
00120
#if !defined(USE_FAST_PKT)
00121
static _go32_dpmi_seginfo rm_cb;
00122
#endif
00123
00124
static DWORD rm_base;
00125
00126
00127
00128
00129
00130
00131
#define PKT_TMP() 0
00132
#define TX_BUF() (PKT_TMP() + PKT_TMP_SIZE)
00133
#define RX_BUF() (TX_BUF() + RX_SIZE)
00134
#define RDATA_SIZE (RX_BUF() + RX_SIZE)
00135
#define RP_SEGM() _pkt_inf->rm_seg
00136
00137
#elif (DOSX & DOS4GW)
00138
00139
static DWORD rm_base;
00140
#if !defined(USE_FAST_PKT)
00141
static WORD pkt_inf_sel;
00142
#endif
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
#define PKT_TMP() ((DWORD)pkt_receiver4_end - \
00158
(DWORD)pkt_receiver4_start)
00159
#define TX_BUF() (PKT_TMP() + PKT_TMP_SIZE)
00160
#define RCV_OFS() ((DWORD)pkt_receiver4_rm - \
00161
(DWORD)pkt_receiver4_start)
00162
#define RP_SEGM() _pkt_inf->rm_seg
00163
00164
#elif (DOSX & POWERPAK)
00165
static REALPTR rm_base;
00166
#if !defined(USE_FAST_PKT)
00167
static DPMI_callback rm_cb;
00168
#endif
00169
00170
#define PKT_TMP() 0
00171
#define TX_BUF() (PKT_TMP() + PKT_TMP_SIZE)
00172
#define RX_BUF() (TX_BUF() + RX_SIZE)
00173
#define RDATA_SIZE (RX_BUF() + RX_SIZE)
00174
#define RP_SEGM() _pkt_inf->rm_seg
00175
00176
#elif (DOSX == 0)
00177
void (__cdecl _far * pkt_enque_ptr) (
BYTE _far *buf,
WORD len);
00178 void (__cdecl _far *_pkt_enque_ptr) (
BYTE _far *buf,
WORD len);
00179
00180
#else
00181
#error Help me!
00182
#endif
00183
00184
00185
#if defined(USE_FAST_PKT)
00186
#include "pcpkt2.c"
00187
00188
#elif (DOSX)
00189
static int setup_rmode_callback (
void);
00190
static int lock_code_and_data (
void);
00191
static int unlock_code_and_data (
void);
00192
#endif
00193
00194
static int find_vector (
int first,
int num);
00195
static int setup_pkt_inf (
void);
00196
static void get_rmode_data (
void *dest,
unsigned size,
WORD seg,
WORD ofs);
00197
static BOOL
pkt_api_entry (IREGS *reg,
unsigned called_from_line);
00198
00199
#define PKT_API(reg) pkt_api_entry (reg, __LINE__)
00200
#define CARRY_BIT 1
00201
00202
#define PKT_ERR(str,code) do { \
00203
const char *err = pkt_strerror (code); \
00204
outs (_LANG(str)); \
00205
outsnl (err); \
00206
} while (0)
00207
00211 const char *
pkt_strerror (
int code)
00212 {
00213
static char buf[50];
00214
static const char *errors[] = {
00215 __LANG(
"Unknown driver error (0x--)"),
00216 __LANG(
"Invalid handle number"),
00217 __LANG(
"No interfaces of specified class found"),
00218 __LANG(
"No interfaces of specified type found"),
00219 __LANG(
"No interfaces of specified number found"),
00220 __LANG(
"Bad packet type specified"),
00221 __LANG(
"This interface does not support multicast"),
00222 __LANG(
"This packet driver cannot terminate"),
00223 __LANG(
"An invalid receiver mode was specified"),
00224 __LANG(
"Operation failed because of insufficient space"),
00225 __LANG(
"Type previously accessed, and not released"),
00226 __LANG(
"The command was out of range, or not implemented"),
00227 __LANG(
"Cannot send packet (hardware error)"),
00228 __LANG(
"Cannot change hardware address"),
00229 __LANG(
"Hardware address has bad length/format"),
00230 __LANG(
"Could not reset interface"),
00231 __LANG(
"Extended driver needed")
00232 };
00233
const char *rc;
00234
char *p;
00235
00236
if (code > 0 && code < DIM(errors))
00237
return (_LANG(errors[code]));
00238
00239 rc =
StrLcpy (buf, _LANG(errors[0]),
sizeof(buf));
00240 p = strchr (rc,
'(');
00241
if (p && strlen(p) >= 5)
00242 {
00243 code &= 0xFF;
00244 p[3] = hex_chars_upper [code >> 4];
00245 p[4] = hex_chars_upper [code & 15];
00246 }
00247
return (buf);
00248 }
00249
00250
00251
00252
00253
#if (DOSX & DOS4GW) && 0
00254
static void dump_asm4 (
void)
00255 {
00256
const BYTE *p = (
const BYTE*) rm_base;
00257
int i;
00258
00259 printf (
"PKT_INF %08lX, HEAD %08lX, QUEUE %08lX, INDEX %04X, XYPOS %d\n",
00260 *(
DWORD*)p, *(
DWORD*)(p+4), *(
DWORD*)(p+8), *(
WORD*)(p+12),
00261 *(
WORD*)(p+14));
00262
00263 printf (
"rm_base %08lX, handle %04X, is_serial %d\n",
00264 rm_base,
_pkt_inf->
handle,
_pkt_inf->
is_serial);
00265
00266 printf (
"VAR_1-14: ");
00267
for (i = 16; i <= 42; i += 2)
00268 printf (
"%04X ", *(
WORD*)(p+i));
00269
00270
#if 0
00271
printf (
"PKT_RECV: ");
00272
for (i = RCV_OFS(); i < RCV_OFS()+10; i++)
00273 printf (
"%02X ", p[i]);
00274
00275 printf (
"\nPKT_TMP: ");
00276
for (i = PKT_TMP(); i < PKT_TMP()+PKT_TMP_SIZE; i++)
00277 printf (
"%02X ", p[i]);
00278
#endif
00279
fflush (stdout);
00280 }
00281
#endif
00282
00283
00289
#if (DOSX & DOS4GW)
00290 void *
pkt_tx_buf (
void)
00291 {
00292
return (
void*)(rm_base + TX_BUF());
00293 }
00294
00295
#elif (DOSX & DJGPP)
00296
void *
pkt_tx_buf (
void)
00297 {
00298
if (
_pkt_inf &&
_pkt_inf->
use_near_ptr)
00299
return (
void*)(rm_base + TX_BUF() + __djgpp_conventional_base);
00300 fprintf (stderr,
"%s (%d): wrong usage of pkt_tx_buf()\n",
00301 __FILE__, __LINE__);
00302 exit (-1);
00303
00304
return (NULL);
00305 }
00306
00307
#elif (DOSX & X32VM)
00308
void *
pkt_tx_buf (
void)
00309 {
00310
return (
void*) ((RP_SEG(rm_base) << 4) + RP_OFF(rm_base) +
00311 (
DWORD)_x386_zero_base_ptr + TX_BUF());
00312 }
00313
#endif
00314
00320 static int pkt_set_access (
void)
00321 {
00322 IREGS regs;
00323
00324 ASSERT_PKT_INF (0);
00325
00326 memset (®s, 0,
sizeof(regs));
00327
00328 regs.r_ax = PD_ACCESS |
_pktdevclass;
00329 regs.r_bx = 0xFFFF;
00330 regs.r_dx = 0;
00331 regs.r_cx = 0;
00332
00333
#if defined(USE_FAST_PKT)
00334
regs.r_es =
_pkt_inf->
rm_seg;
00335 regs.r_di = PktReceiver;
00336
00337
#elif (DOSX & DJGPP)
00338
regs.r_es = rm_cb.rm_segment;
00339 regs.r_di = rm_cb.rm_offset;
00340
00341
#elif (DOSX & (PHARLAP|X32VM))
00342
regs.r_es = RP_SEGM();
00343 regs.r_di = 0;
00344
00345
#elif (DOSX & POWERPAK)
00346
regs.r_es = RP_SEG (rm_cb.rm_addr);
00347 regs.r_di = RP_OFF (rm_cb.rm_addr);
00348
00349
#elif (DOSX & DOS4GW)
00350
regs.r_es = RP_SEGM();
00351 regs.r_di = RCV_OFS();
00352
00353
#else
00354 regs.r_es = FP_SEG (pkt_receiver_rm);
00355 regs.r_di = FP_OFF (pkt_receiver_rm);
00356
#endif
00357
00358
if (!PKT_API(®s))
00359 {
00360 PKT_ERR (
"Error allocating handle: ",
_pkt_errno);
00361
return (0);
00362 }
00363
_pkt_inf->
handle = (
WORD) regs.r_ax;
00364
return (1);
00365 }
00366
00370 static int pkt_drvr_info (
void)
00371 {
00372 IREGS regs;
00373
int rc = 1;
00374
00375 ASSERT_PKT_INF (0);
00376
00377
00378
00379 memset (®s, 0,
sizeof(regs));
00380 regs.r_ax = PD_DRIVER_INFO;
00381
00382
if (!PKT_API(®s))
00383 {
00384 TCP_CONSOLE_MSG (0, (
"Warning: old-type PKTDRVR\n"));
00385
_pktdevclass = PDCLASS_ETHER;
00386
_pkt_ip_ofs =
sizeof(
eth_Header);
00387
_pkt_type_ofs = offsetof (
struct eth_Header, type);
00388
_pkt_errno = 0;
00389 }
00390
else
00391 {
00392
_pktdevlevel = loBYTE (regs.r_ax);
00393
_pktdevclass = hiBYTE (regs.r_cx);
00394 pkt_drvr_ver = regs.r_bx & 0xFFFF;
00395
00396
switch (
_pktdevclass)
00397 {
00398
case PDCLASS_TOKEN:
00399
case PDCLASS_TOKEN_RIF:
00400
_pkt_ip_ofs =
sizeof(
tok_Header);
00401
_pkt_type_ofs = offsetof (
struct tok_Header, type);
00402
break;
00403
00404
case PDCLASS_ETHER:
00405
_pkt_ip_ofs =
sizeof(
eth_Header);
00406
_pkt_type_ofs = offsetof (
struct eth_Header, type);
00407
break;
00408
00409
case PDCLASS_FDDI:
00410
_pkt_ip_ofs =
sizeof(
fddi_Header);
00411
_pkt_type_ofs = offsetof (
struct fddi_Header, type);
00412
break;
00413
00414
case PDCLASS_ARCNET:
00415
_pkt_ip_ofs = ARC_HDRLEN;
00416
_pkt_type_ofs = ARC_TYPE_OFS;
00417
break;
00418
00419
case PDCLASS_SLIP:
00420
case PDCLASS_PPP:
00421
case PDCLASS_AX25:
00422
_pkt_ip_ofs = 0;
00423
_pkt_type_ofs = 0;
00424
break;
00425
00426
default:
00427 outs (_LANG(
"PKT-ERROR: Unsupported driver class "));
00428 outhex ((
char)
_pktdevclass);
00429 outsnl (
"h");
00430
_pkt_errno = PDERR_NO_CLASS;
00431 rc = 0;
00432 }
00433
get_rmode_data (_pktdrvrname,
sizeof(_pktdrvrname), regs.r_ds, regs.r_si);
00434 _pktdrvrname [
sizeof(_pktdrvrname)-1] =
'\0';
00435
00436
if (pkt_txwait == 0 &&
00437 !strcmp(_pktdrvrname,
"NDIS3PKT"))
00438 pkt_txwait = 1;
00439 }
00440
00441
_pktserial = (
_pktdevclass == PDCLASS_SLIP ||
00442
_pktdevclass == PDCLASS_PPP ||
00443
_pktdevclass == PDCLASS_AX25);
00444
00445
_pkt_inf->
is_serial =
_pktserial;
00446
_pkt_inf->
pkt_ip_ofs =
_pkt_ip_ofs;
00447
_pkt_inf->
pkt_type_ofs =
_pkt_type_ofs;
00448
return (rc);
00449 }
00450
00454 int pkt_get_params (
struct PktParameters *params)
00455 {
00456 IREGS regs;
00457
int rc = 0;
00458
00459 memset (®s, 0,
sizeof(regs));
00460 regs.r_ax = PD_GET_PARAM;
00461
00462 DISABLE();
00463
if (PKT_API(®s))
00464 {
00465
get_rmode_data (params,
sizeof(*params), regs.r_es, regs.r_di);
00466 got_params = TRUE;
00467 rc = 1;
00468 }
00469 ENABLE();
00470
return (rc);
00471 }
00472
00477 int pkt_get_mtu (
void)
00478 {
00479
if (
_pktdevclass == PDCLASS_ARCNET)
00480
return (ARCNET_MAX_DATA - 8);
00481
00482
if (got_params)
00483
return (pkt_params.mtu);
00484
return (-1);
00485 }
00486
00487
#ifdef NOT_USED
00488
00492 int pkt_get_mac_len (
void)
00493 {
00494
if (
_pktdevclass == PDCLASS_ARCNET)
00495
return (
sizeof(
arcnet_address));
00496
if (got_params)
00497
return (pkt_params.addr_len);
00498
return (-1);
00499 }
00500
#endif
00501
00507 int pkt_get_api_ver (
DWORD *ver)
00508 {
00509
if (got_params)
00510 {
00511 *ver = ((pkt_params.major_rev << 8) + pkt_params.minor_rev);
00512
return (1);
00513 }
00514
return (0);
00515 }
00516
00520 int pkt_get_drvr_ver (
WORD *major,
WORD *minor)
00521 {
00522
if (!pkt_drvr_ver)
00523
return (0);
00524 *major = pkt_drvr_ver >> 8;
00525 *minor = pkt_drvr_ver & 255;
00526
return (1);
00527 }
00528
00532 int pkt_get_vector (
void)
00533 {
00534
return (pkt_interrupt);
00535 }
00536
00548 static int pkt16_drvr_init (mac_address *mac_addr)
00549 {
00550
00551
00552
00553
00554
if (pkt_interrupt)
00555 pkt_interrupt = find_vector (pkt_interrupt, 1);
00556
else pkt_interrupt = find_vector (PKT_FIRST_VEC,
00557 PKT_LAST_VEC - PKT_FIRST_VEC + 1);
00558
00559
if (pkt_interrupt == 0)
00560 {
00561 outsnl (_LANG(
"NO PACKET DRIVER FOUND."));
00562
return (WERR_NO_DRIVER);
00563 }
00564
00565
if (!
setup_pkt_inf())
00566 {
00567 outsnl (_LANG(
"Failed to allocate PACKET DRIVER data."));
00568
return (WERR_NO_MEM);
00569 }
00570
00571
#if defined(USE_FAST_PKT)
00572
switch (setup_rmode_receiver())
00573 {
00574
case -1:
00575 outsnl (_LANG(
"Error in PACKET DRIVER stub code."));
00576
return (WERR_PKT_ERROR);
00577 }
00578
#elif (DOSX)
00579
switch (setup_rmode_callback())
00580 {
00581
case -1:
00582 outsnl (_LANG(
"Failed to allocate callback for PACKET DRIVER."));
00583
return (WERR_NO_MEM);
00584
case -2:
00585 outsnl (_LANG(
"Failed to allocate DOS-mem for PACKET DRIVER."));
00586
case -3:
00587
return (WERR_NO_MEM);
00588 }
00589
00590
if (lock_code_and_data() < 0)
00591 {
00592 outsnl (_LANG(
"Failed to lock code/data for PACKET DRIVER."));
00593
return (WERR_PKT_ERROR);
00594 }
00595
#endif
00596
00597
if (!
pkt_drvr_info())
00598
return (WERR_PKT_ERROR);
00599
00600
if (!
pkt_set_access())
00601 {
00602
pkt_release();
00603
return (WERR_PKT_ERROR);
00604 }
00605
00606
if (!
pkt_get_addr(mac_addr))
00607 {
00608
pkt_release();
00609
return (WERR_PKT_ERROR);
00610 }
00611
00612 memset (&pkt_params, 0,
sizeof(pkt_params));
00613 got_params = FALSE;
00614
00615
if (
_pktdevlevel >= 5 &&
_pktdevlevel < 255)
00616 {
00617
if (!
pkt_get_params(&pkt_params))
00618 TCP_CONSOLE_MSG (1, (
"Failed to get PKTDRVR params; %s\n",
00619
pkt_strerror(
_pkt_errno)));
00620 }
00621
00622
#if defined(USE_STATISTICS)
00623
if (
_pktdevlevel >= 2 &&
_pktdevlevel < 255)
00624 get_init_stats();
00625
#endif
00626
00627
if (
_pktserial)
00628
return (0);
00629
00630
00631
00632
if (_pkt_forced_rxmode != -1 &&
00633 (_pkt_forced_rxmode < -1 ||
00634 _pkt_forced_rxmode >
RXMODE_PROMISCOUS))
00635 {
00636 TCP_CONSOLE_MSG (0, (
"Illegal Rx-mode (%d) specified\n",
00637 _pkt_forced_rxmode));
00638 _pkt_forced_rxmode = -1;
00639 }
00640
00641
if (
pkt_get_rcv_mode())
00642
_pkt_rxmode0 =
_pkt_rxmode;
00643
00644
if (_pkt_forced_rxmode != -1 &&
00645 _pkt_forced_rxmode !=
_pkt_rxmode0)
00646
pkt_set_rcv_mode (_pkt_forced_rxmode);
00647
00648
00649
00650
return (0);
00651 }
00652
00653
00654
00655
00656
00657
00658
00659
00660
00661
00662
00663
00664
#if defined(__HIGHC__)
00665
#pragma off(Call_trace)
00666
#pragma off(Prolog_trace)
00667
#pragma off(Epilog_trace)
00668
#endif
00669
00670
#if defined(WATCOM386)
00671
00672
00673
#endif
00674
00675
#include "nochkstk.h"
00676
00677
00681 int pkt_release_handle (
WORD handle)
00682 {
00683
static IREGS regs;
00684
00685 memset (®s, 0,
sizeof(regs));
00686 regs.r_ax = PD_RELEASE;
00687 regs.r_bx = handle;
00688
00689
if (!PKT_API(®s) && !
_watt_fatal_error)
00690 PKT_ERR (
"Error releasing handle: ",
_pkt_errno);
00691
return (1);
00692 }
00693
00697 int pkt_reset_handle (
WORD handle)
00698 {
00699
static IREGS regs;
00700
00701 memset (®s, 0,
sizeof(regs));
00702 regs.r_ax = PD_RESET;
00703 regs.r_bx = handle;
00704
00705
if (!PKT_API(®s))
00706 PKT_ERR (
"Error resetting handle: ",
_pkt_errno);
00707
return (1);
00708 }
00709
00710
#if (DOSX) && !defined(USE_FAST_PKT)
00711
static void release_callback (
void)
00712 {
00713
#if (DOSX & (PHARLAP|X32VM))
00714
if (rm_base)
00715 _dx_free_rmode_wrapper (rm_base);
00716 rm_base = 0;
00717
00718
#elif (DOSX & POWERPAK)
00719
if (rm_cb.pm_func)
00720 dpmi_free_callback_retf (&rm_cb);
00721 rm_cb.pm_func = 0;
00722
00723
#elif (DOSX & DJGPP)
00724
if (rm_cb.pm_offset)
00725 _pkt_dpmi_free_real_mode_callback (&rm_cb);
00726 rm_cb.pm_offset = 0;
00727
#endif
00728
}
00729
#endif
00730
00731
00735
#if (DOSX) && defined(USE_FAST_PKT)
00736 static void release_real_mem (
void)
00737 {
00738
#if (DOSX & PHARLAP)
00739
if (
_pkt_inf &&
_pkt_inf->
rm_seg)
00740 _dx_real_free (
_pkt_inf->
rm_seg);
00741 rm_base = 0;
00742
00743
#elif (DOSX & X32VM)
00744
if (rm_base)
00745 _x32_real_free (rm_base);
00746 rm_base = 0;
00747
00748
#elif (DOSX & POWERPAK)
00749
if (
_pkt_inf &&
_pkt_inf->
rm_sel)
00750 dpmi_real_free (
_pkt_inf->
rm_sel);
00751
00752
#elif (DOSX & DJGPP)
00753
if (
_pkt_inf &&
_pkt_inf->
rm_sel)
00754 {
00755 __dpmi_error = 0;
00756 __dpmi_free_dos_memory (
_pkt_inf->
rm_sel);
00757
if (__dpmi_error)
00758 {
00759 (*_printf) (
"%s (%u): DPMI/DOS error %04Xh\n",
00760 __FILE__, __LINE__, __dpmi_error);
00761 TCP_TRACE_MSG ((
"release_real_mem: dpmi_error %u\n", __dpmi_error));
00762 }
00763 }
00764 rm_base = (
DWORD)-1;
00765
00766
#elif (DOSX & DOS4GW)
00767
if (!
_watt_fatal_error &&
_pkt_inf)
00768 {
00769
if (
_pkt_inf->
rm_sel)
00770 dpmi_real_free (
_pkt_inf->
rm_sel);
00771
00772
#if !defined(USE_FAST_PKT)
00773
if (pkt_inf_sel)
00774 dpmi_real_free (pkt_inf_sel);
00775 pkt_inf_sel = 0;
00776
#endif
00777
}
00778
#endif
00779
00780
if (
_pkt_inf)
00781
_pkt_inf->
rm_sel =
_pkt_inf->
rm_seg = 0;
00782
00783
#if !defined(USE_FAST_PKT)
00784
_pkt_inf = NULL;
00785
#endif
00786
}
00787
#endif
00788
00789
00798
#ifdef __WATCOMC__
00799
#pragma aux pkt_release loadds;
00800
#endif
00801
00802
#ifdef __GNUC__
00803
#define DTOR __attribute__((destructor))
00804
#else
00805
#define DTOR
00806
#endif
00807
00808 int DTOR
pkt_release (
void)
00809 {
00810 DISABLE();
00811
00812
if (
_pkt_inf)
00813 {
00814
00815
00816
00817
if (pkt_do_reset)
00818
pkt_reset_handle (
_pkt_inf->
handle);
00819
pkt_release_handle (
_pkt_inf->
handle);
00820 }
00821
00822
00823
00831
#if (DOSX) && !defined(USE_FAST_PKT)
00832
unlock_code_and_data();
00833 release_callback();
00834
#endif
00835
00836
#if (DOSX) && defined(USE_FAST_PKT)
00837
release_real_mem();
00838
#endif
00839
00840
if (
_pkt_inf && !
_watt_fatal_error)
00841 free (
_pkt_inf);
00842
00843
_pkt_inf = NULL;
00844
00845 ENABLE();
00846
return (1);
00847 }
00848
00849
#if defined(__BORLANDC__)
00850
#pragma exit pkt_release 100
00851
#elif defined(__CCDL__)
00852
#pragma rundown pkt_release 110
00853
#endif
00854
00855
00856
#if !defined(USE_FAST_PKT) && !(DOSX & DOS4GW)
00857
00885
#if (DOSX)
00886
static void pkt_enqueue (
unsigned rxBuf,
WORD rxLen)
00887 #
else
00888
static void __cdecl _far
pkt_enqueue (
BYTE _far *rxBuf,
WORD rxLen)
00889 #endif
00890 {
00891
struct pkt_ringbuf *q = &
_pkt_inf->
pkt_queue;
00892
int index;
00893
00894
00895
00896
00897 index = q->
in_index + 1;
00898
if (index >= q->num_buf)
00899 index = 0;
00900
00901
if (index != q->out_index)
00902 {
00903
char *head = (
char*)q->buf_start + (q->buf_size * q->in_index);
00904
int padLen = q->buf_size - 4 - rxLen;
00905
00906
if (rxLen > q->buf_size - 4)
00907 {
00908 rxLen = q->buf_size - 4;
00909 padLen = 0;
00910 }
00911
00912
#if (DOSX & (PHARLAP|X32VM|POWERPAK))
00913
ReadRealMem (head, rm_base + rxBuf, rxLen);
00914
00915
#elif (DOSX & DJGPP)
00916
if (
_pkt_inf->
use_near_ptr)
00917 memcpy (head, (
void*)(rm_base+rxBuf+__djgpp_conventional_base), rxLen);
00918
else DOSMEMGETL (rm_base + rxBuf, (rxLen+3)/4, head);
00919
00920
#else
00921 _fmemcpy (head, rxBuf, rxLen);
00922
#endif
00923
00924
00925
00926 head += rxLen;
00927
while (padLen--)
00928 *head++ =
'\0';
00929 q->in_index = index;
00930 }
00931
else
00932 q->num_drop++;
00933 }
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
#if (DOSX & (PHARLAP|X32VM))
00954
static void cdecl pkt_receiver_pm (SWI_REGS *r)
00955 {
00956 PUSHF_CLI();
00957
00958
if ((
BYTE)r->r_ax == 0)
00959 {
00960
if (!
_pkt_inf || (
WORD)r->r_cx > ETH_MAX)
00961 {
00962 r->r_es = 0;
00963 r->r_di = 0;
00964 }
00965
else
00966 {
00967 r->r_es = RP_SEGM();
00968 r->r_di = RX_BUF();
00969 }
00970 }
00971
else if ((
WORD)r->r_si &&
_pkt_inf)
00972 {
00973
pkt_enqueue (RX_BUF(), (
WORD)r->r_cx);
00974 }
00975 POPF();
00976 }
00977
00978
#elif (DOSX & DJGPP)
00979
static void cdecl pkt_receiver_pm (__dpmi_regs *r)
00980 {
00981
WORD fs, gs;
00982
00983 PUSHF_CLI();
00984
00985 fs = get_fs_reg();
00986 gs = get_gs_reg();
00987
00988
if (r->h.al == 0)
00989 {
00990
if (!
_pkt_inf || r->x.cx > ETH_MAX)
00991 {
00992 r->x.es = 0;
00993 r->x.di = 0;
00994 }
00995
else
00996 {
00997 r->x.es = RP_SEGM();
00998 r->x.di = RX_BUF();
00999 }
01000 }
01001
else if (r->x.si &&
_pkt_inf)
01002 {
01003
pkt_enqueue (RX_BUF(), r->x.cx);
01004 }
01005
01006 set_fs_reg (fs);
01007 set_gs_reg (gs);
01008
01009 POPF();
01010 }
01011
01012
#elif (DOSX & POWERPAK)
01013
static void cdecl pkt_receiver_pm (
void)
01014 {
01015 REAL_regs *r;
01016
01017 PUSHF_CLI();
01018 r = &rm_cb.rm_regs;
01019
01020
if ((
BYTE)r->r_ax == 0)
01021 {
01022
if (!
_pkt_inf || (
WORD)r->r_cx > ETH_MAX)
01023 {
01024 r->r_es = 0;
01025 r->r_di = 0;
01026 }
01027
else
01028 {
01029 r->r_es = RP_SEGM();
01030 r->r_di = RX_BUF();
01031 }
01032 }
01033
else if (r->r_si &&
_pkt_inf)
01034 {
01035
pkt_enqueue (RX_BUF(), (
WORD)r->r_cx);
01036 }
01037 POPF();
01038 }
01039
#endif
01040
01041
void _pkt_end (
void) {}
01042
01043
#if defined(__WATCOMC__)
01044
#pragma alloc_text (pkt_lock_TEXT, pkt_enqueue, pkt_receiver_pm, _pkt_end);
01045
#endif
01046
01047
#endif
01048
01049
01060 int pkt_send (
const void *tx,
int length)
01061 {
01062 IREGS regs;
01063
WORD tx_seg, tx_ofs;
01064 BOOL fail = FALSE;
01065
int tx_cnt;
01066
01067
if (!
_pkt_inf)
01068
return (0);
01069
01070 PROFILE_START (
"pkt_send");
01071
01072 memset (®s, 0,
sizeof(regs));
01073
01074
#if (DOSX & (PHARLAP|POWERPAK))
01075
tx_seg = RP_SEGM();
01076 tx_ofs = TX_BUF();
01077 WriteRealMem (rm_base + tx_ofs, (
void*)tx, length);
01078
01079
#elif (DOSX & (DOS4GW|X32VM))
01080
tx_seg = RP_SEGM();
01081 tx_ofs = TX_BUF();
01082 WATT_ASSERT (tx ==
pkt_tx_buf());
01083
01084
#elif (DOSX & DJGPP)
01085
tx_seg = RP_SEGM();
01086 tx_ofs = TX_BUF();
01087
if (
_pkt_inf->
use_near_ptr)
01088 WATT_ASSERT (tx ==
pkt_tx_buf());
01089
else DOSMEMPUTL (tx, (length+3)/4, rm_base + tx_ofs);
01090
01091
#else
01092
tx_seg = FP_SEG (tx);
01093 tx_ofs = FP_OFF (tx);
01094
#endif
01095
01096
for (tx_cnt = 0; tx_cnt <= pkt_txretries; tx_cnt++)
01097 {
01098 regs.r_cx = length;
01099 regs.r_ax = PD_SEND;
01100 regs.r_ds = tx_seg;
01101 regs.r_si = tx_ofs;
01102
01103 fail = FALSE;
01104
01105
if (PKT_API(®s))
01106
break;
01107
01108 fail = TRUE;
01109
if (pkt_txwait > 0)
01110
Wait (pkt_txwait);
01111 }
01112
01113
if (tx_cnt > 0)
01114 STAT (macstats.
num_tx_retry += tx_cnt-1);
01115
01116
if (fail)
01117 length = 0;
01118
01119
if (length == 0)
01120 STAT (macstats.
num_tx_err++);
01121
01122 PROFILE_STOP();
01123
return (length);
01124 }
01125
01129 int pkt_get_addr (mac_address *mac)
01130 {
01131 IREGS regs;
01132
WORD seg, ofs;
01133
int rc;
01134
01135 ASSERT_PKT_INF (0);
01136
01137 PROFILE_START (
"pkt_get_addr");
01138
01139 regs.r_ax = PD_GET_ADDRESS;
01140 regs.r_bx =
_pkt_inf->
handle;
01141 regs.r_cx =
sizeof (*mac);
01142
01143
#if (DOSX)
01144
regs.r_es = seg = RP_SEGM();
01145 regs.r_di = ofs = PKT_TMP();
01146
#else
01147
regs.r_es = seg = FP_SEG (mac);
01148 regs.r_di = ofs = FP_OFF (mac);
01149
#endif
01150
01151
if (!PKT_API(®s))
01152 {
01153 PKT_ERR (
"Cannot read own MAC address: ",
_pkt_errno);
01154 rc = 0;
01155 }
01156
else
01157 {
01158
get_rmode_data (mac,
sizeof(*mac), seg, ofs);
01159 rc = 1;
01160 }
01161 PROFILE_STOP();
01162
return (rc);
01163 }
01164
01168 int pkt_set_addr (
const void *addr)
01169 {
01170 IREGS regs;
01171
01172 ASSERT_PKT_INF (0);
01173
01174 regs.r_ax = PD_SET_ADDR;
01175 regs.r_cx =
sizeof (mac_address);
01176
01177
#if (DOSX & DJGPP)
01178
DOSMEMPUT (addr,
sizeof(mac_address), rm_base + PKT_TMP());
01179 regs.r_es = RP_SEGM();
01180 regs.r_di = PKT_TMP();
01181
01182
#elif (DOSX & DOS4GW)
01183
memcpy ((
void*)(rm_base + PKT_TMP()), addr,
sizeof(mac_address));
01184 regs.r_es = RP_SEGM();
01185 regs.r_di = PKT_TMP();
01186
01187
#elif (DOSX & (PHARLAP|X32VM|POWERPAK))
01188
WriteRealMem (rm_base + PKT_TMP(), (
void*)addr,
sizeof(mac_address));
01189 regs.r_es = RP_SEGM();
01190 regs.r_di = PKT_TMP();
01191
01192
#else
01193
{
01194 mac_address tmp;
01195 memcpy (&tmp, addr,
sizeof(tmp));
01196 regs.r_es = FP_SEG (&tmp);
01197 regs.r_di = FP_OFF (&tmp);
01198 }
01199
#endif
01200
01201
if (!PKT_API(®s))
01202
return (0);
01203
return (1);
01204 }
01205
01206
#if defined(USE_STATISTICS)
01207
01213 int pkt_get_stats (
struct PktStats *stats,
struct PktStats *total)
01214 {
01215 IREGS regs;
01216
int rc = 0;
01217
01218 PROFILE_START (
"pkt_get_stats");
01219 DISABLE();
01220
01221
01222
01223 regs.r_bx =
_pkt_inf ?
_pkt_inf->
handle : 0;
01224 regs.r_ax = PD_GET_STATS;
01225
01226
if (!PKT_API(®s))
01227
goto fail;
01228
01229 rc = 1;
01230
get_rmode_data (stats,
sizeof(*stats), regs.r_ds, regs.r_si);
01231
01232
if (total)
01233 *total = *stats;
01234
01235 stats->in_packets -= init_stats.in_packets;
01236 stats->out_packets -= init_stats.out_packets;
01237 stats->in_bytes -= init_stats.in_bytes;
01238 stats->out_bytes -= init_stats.out_bytes;
01239 stats->in_errors -= init_stats.in_errors;
01240 stats->out_errors -= init_stats.out_errors;
01241 stats->lost -= init_stats.lost;
01242 fail:
01243 ENABLE();
01244 PROFILE_STOP();
01245
return (rc);
01246 }
01247
01248
static void get_init_stats (
void)
01249 {
01250 IREGS regs;
01251
01252 regs.r_ax = PD_GET_STATS;
01253 regs.r_bx =
_pkt_inf->
handle;
01254 memset (&init_stats, 0,
sizeof(init_stats));
01255
01256 DISABLE();
01257
if (PKT_API(®s))
01258
get_rmode_data (&init_stats,
sizeof(init_stats), regs.r_ds, regs.r_si);
01259 ENABLE();
01260 }
01261
01262
01267 static WORD cstate_dseg = 0;
01268
01269
int pkt_get_vjstats (
struct slcompress *vjstats)
01270 {
01271 IREGS regs;
01272
int rc = 0;
01273
01274 regs.r_ax = PD_GET_VJSTATS;
01275 regs.r_bx =
sizeof (*vjstats);
01276
01277 DISABLE();
01278
if (PKT_API(®s))
01279 {
01280
get_rmode_data (vjstats,
sizeof(*vjstats), regs.r_ds, regs.r_si);
01281
cstate_dseg = regs.r_ds;
01282 rc = 1;
01283 }
01284 ENABLE();
01285
return (rc);
01286 }
01287
01288
int pkt_get_cstate (
struct cstate *cs,
WORD cstate_ofs)
01289 {
01290
if (
cstate_dseg == 0 || cstate_ofs == 0)
01291
return (0);
01292
01293 DISABLE();
01294
get_rmode_data (cs,
sizeof(*cs), cstate_dseg, cstate_ofs);
01295 ENABLE();
01296
return (1);
01297 }
01298
#endif
01299
01300
01304 int pkt_buf_wipe (
void)
01305 {
01306
#if defined(USE_FAST_PKT)
01307
pktq_clear (NULL);
01308
#else
01309
ASSERT_PKT_INF (0);
01310 pktq_clear (&
_pkt_inf->
pkt_queue);
01311
#endif
01312
return (1);
01313 }
01314
01319 void pkt_free_pkt (
const void *pkt)
01320 {
01321
#if !defined(USE_FAST_PKT)
01322
struct pkt_ringbuf *q;
01323
01324
if (!
_pkt_inf || !pkt)
01325
return;
01326
01327 q = &
_pkt_inf->
pkt_queue;
01328 pkt_drop_cnt = q->num_drop;
01329
01330
if (pkt != (
const void*) (pktq_out_buf(q) +
_pkt_ip_ofs))
01331 {
01332 TCP_CONSOLE_MSG (0, (
"%s: freeing illegal packet 0x%p.\n", __FILE__, pkt));
01333 pktq_clear (q);
01334 }
01335
else
01336 pktq_inc_out (q);
01337
#else
01338
if (rm_base && rm_base < (
DWORD)-1)
01339 pkt_drop_cnt = FAR_PEEK_DWORD (
struct pkt_info, pkt_queue.num_drop);
01340 ARGSUSED (pkt);
01341
#endif
01342
}
01343
01344
01348 int pkt_waiting (
void)
01349 {
01350
#if defined(USE_FAST_PKT)
01351
if (rm_base && rm_base < (
DWORD)-1)
01352
return pkt_buffers_used();
01353
return (-1);
01354
#else
01355
if (
_pkt_inf)
01356
return pktq_queued (&
_pkt_inf->
pkt_queue);
01357
return (-1);
01358
#endif
01359
}
01360
01364 DWORD pkt_dropped (
void)
01365 {
01366
#if defined(USE_FAST_PKT)
01367
if (rm_base && rm_base < (
DWORD)-1)
01368
return pkt_rx_dropped();
01369
#else
01370
if (
_pkt_inf)
01371
return (
_pkt_inf->
pkt_queue.
num_drop);
01372
#endif
01373
return (pkt_drop_cnt);
01374 }
01375
01380 static int parse_config_pass_1 (
void)
01381 {
01382
static int vect = 0;
01383
static const struct config_table pkt_init_cfg[] = {
01384 {
"PKT.VECTOR",
ARG_ATOX_B, (
void*)&vect },
01385 {
"PKT.TXRETRIES",
ARG_ATOB, (
void*)&pkt_txretries },
01386 {
"PKT.TXWAIT",
ARG_ATOI, (
void*)&pkt_txwait },
01387 {
"PKT.RXMODE",
ARG_ATOI, (
void*)&_pkt_forced_rxmode },
01388 {
"PKT.RXBUFS",
ARG_ATOI, (
void*)&pkt_num_rx_bufs },
01389 {
"PKT.NEAR_PTR",
ARG_ATOI, (
void*)&pkt_use_near },
01390 {
"PKT.RESET",
ARG_ATOI, (
void*)&pkt_do_reset },
01391 { NULL, 0, NULL }
01392 };
01393
const struct config_table *cfg_save = watt_init_cfg;
01394 void (*init_save) (
const char*,
const char*) = usr_init;
01395
int rc;
01396
01397 watt_init_cfg = pkt_init_cfg;
01398 usr_init = NULL;
01399 rc = tcp_config (NULL);
01400 usr_init = init_save;
01401 watt_init_cfg = cfg_save;
01402
if (!rc)
01403
return (0);
01404
return (vect);
01405 }
01406
01419 int pkt_eth_init (mac_address *addr)
01420 {
01421
int vector, rc = -1;
01422
01423
if (
_watt_no_config && !_watt_user_config_fn)
01424 vector = 0;
01425
else vector =
parse_config_pass_1();
01426
01427
if (vector)
01428 {
01429 pkt_interrupt = vector;
01430
if (pkt_interrupt < PKT_FIRST_VEC_11 ||
01431 pkt_interrupt > PKT_LAST_VEC_11)
01432 pkt_interrupt = 0;
01433 }
01434
else
01435 pkt_interrupt = 0;
01436
01437 {
01438
#if (DOSX)
01439
int pm_driver = pkt32_drvr_probe (pm_driver_list);
01440
01441
if (pm_driver > -1)
01442 {
01443 rc = pkt32_drvr_init (pm_driver, addr);
01444
if (rc == 0)
01445 TCP_CONSOLE_MSG (2, (
"Using Pmode `%s' driver at %08lX\n",
01446 pkt32_drvr_name(pm_driver), (
DWORD)_pkt32_drvr));
01447 }
01448
if (rc)
01449
#endif
01450
rc =
pkt16_drvr_init (addr);
01451
01452
if (rc)
01453
return (rc);
01454 }
01455
01456
#if defined(USE_FAST_PKT)
01457
FAR_POKE_WORD (
struct pkt_info, handle,
_pkt_inf->
handle);
01458 FAR_POKE_WORD (
struct pkt_info, is_serial,
_pkt_inf->
is_serial);
01459 FAR_POKE_WORD (
struct pkt_info, pkt_ip_ofs,
_pkt_inf->
pkt_ip_ofs);
01460 FAR_POKE_WORD (
struct pkt_info, pkt_type_ofs,
_pkt_inf->
pkt_type_ofs);
01461
01462
#if (DOSX & X32VM) && 0
01463
if (!pkt_test_upcall())
01464 {
01465
pkt_release();
01466
return (-1);
01467 }
01468
#endif
01469
#endif
01470
01471
return (0);
01472 }
01473
01477
#if (DOSX & (PHARLAP|X32VM))
01478 static BOOL
check_intr_num (
WORD intr_num)
01479 {
01480 REALPTR rp;
01481
char temp[16];
01482
01483 _dx_rmiv_get (intr_num, &rp);
01484
if (rp)
01485 {
01486 ReadRealMem (&temp, rp,
sizeof(temp));
01487
if (!memcmp(temp+3, pkt_sign, strlen(pkt_sign)))
01488
return (TRUE);
01489 }
01490
return (FALSE);
01491 }
01492
01493
#elif (DOSX & DJGPP)
01494
static BOOL
check_intr_num (
WORD intr_num)
01495 {
01496
char temp[16];
01497
DWORD rp;
01498 __dpmi_raddr realAdr;
01499
01500 __dpmi_get_real_mode_interrupt_vector (intr_num, &realAdr);
01501 rp = (realAdr.segment << 4) + realAdr.offset16;
01502
if (rp)
01503 {
01504 dosmemget (rp,
sizeof(temp), &temp);
01505
if (!memcmp(temp+3, pkt_sign, strlen(pkt_sign)))
01506
return (TRUE);
01507 }
01508
return (FALSE);
01509 }
01510
01511
#elif (DOSX & DOS4GW)
01512
static BOOL
check_intr_num (
WORD intr_num)
01513 {
01514
const BYTE *addr = (
const BYTE*) dpmi_get_real_vector (intr_num);
01515
01516
if (addr && !memcmp(addr+3, pkt_sign, strlen(pkt_sign)))
01517
return (TRUE);
01518
return (FALSE);
01519 }
01520
01521
#elif (DOSX & POWERPAK)
01522
static BOOL
check_intr_num (
WORD intr_num)
01523 {
01524
char temp[16];
01525
DWORD addr = (
DWORD) dpmi_get_real_vector (intr_num);
01526 REALPTR rp;
01527
01528 RP_SET (rp, addr & 0xF, addr >> 4);
01529 ReadRealMem (&temp, rp,
sizeof(temp));
01530
if (!memcmp(temp+3, pkt_sign, strlen(pkt_sign)))
01531
return (TRUE);
01532
return (FALSE);
01533 }
01534
01535
#else
01536
static BOOL
check_intr_num (
WORD intr_num)
01537 {
01538
char _far *addr = (
char _far*) getvect (intr_num);
01539
01540
#if !defined(USE_FAST_PKT)
01541
pkt_enque_ptr =
pkt_enqueue;
01542 _pkt_enque_ptr =
pkt_enqueue;
01543
#endif
01544
01545
if (addr && !_fmemcmp(addr+3, pkt_sign, strlen(pkt_sign)))
01546
return (TRUE);
01547
return (FALSE);
01548 }
01549
#endif
01550
01551
01552
01553
01554
01555
static int find_vector (
int first,
int num)
01556 {
01557
int inum;
01558
01559
for (inum = first; inum < first + num; inum++)
01560 {
01561
if (inum != 0x67 &&
01562
check_intr_num(inum))
01563
return (inum);
01564 }
01565
return (0);
01566 }
01567
01568
#if !defined(USE_FAST_PKT)
01569
01570
01571
01572
01573
01574
#if (DOSX & (PHARLAP|X32VM))
01575
static int setup_rmode_callback (
void)
01576 {
01577 rm_base = _dx_alloc_rmode_wrapper_retf (pkt_receiver_pm, NULL,
01578 RDATA_SIZE, 1024);
01579
if (!rm_base)
01580
return (-1);
01581
return (0);
01582 }
01583
01584
static int lock_code_and_data (
void)
01585 {
01586
UINT size = (
UINT)_pkt_end - (
UINT)
pkt_enqueue;
01587
01588 _dx_lock_pgsn ((
void*)pkt_enqueue, size);
01589 _dx_lock_pgsn ((
void*)ReadRealMem, 100);
01590 _dx_lock_pgsn ((
void*)_pkt_inf,
sizeof(*_pkt_inf));
01591 _dx_lock_pgsn ((
void*)&_pkt_inf,
sizeof(_pkt_inf));
01592
01593
#if (DOSX & X32VM)
01594
_dx_lock_pgsn ((
void*)memcpy, 200);
01595
#endif
01596
return (0);
01597 }
01598
01599
static int unlock_code_and_data (
void)
01600 {
01601
UINT size = (
UINT)_pkt_end - (
UINT)
pkt_enqueue;
01602
01603 _dx_ulock_pgsn ((
void*)pkt_enqueue, size);
01604 _dx_ulock_pgsn ((
void*)ReadRealMem, 100);
01605 _dx_ulock_pgsn ((
void*)_pkt_inf,
sizeof(*_pkt_inf));
01606 _dx_ulock_pgsn ((
void*)&_pkt_inf,
sizeof(_pkt_inf));
01607
01608
#if (DOSX & X32VM)
01609
_dx_ulock_pgsn ((
void*)memcpy, 200);
01610
#endif
01611
return (0);
01612 }
01613
01614
#elif (DOSX & DJGPP)
01615
static int setup_rmode_callback (
void)
01616 {
01617
static __dpmi_regs rm_reg;
01618
int seg = __dpmi_allocate_dos_memory ((RDATA_SIZE + 15) / 16,
01619 &
_pkt_inf->
rm_sel);
01620
if (seg < 0)
01621
return (-2);
01622
01623
_pkt_inf->
rm_seg = seg;
01624 rm_cb.pm_offset = (
DWORD) pkt_receiver_pm;
01625
01626 memset (&rm_reg, 0,
sizeof(rm_reg));
01627
if (_pkt_dpmi_allocate_real_mode_callback_retf (&rm_cb,&rm_reg))
01628
return (-1);
01629
01630 rm_base = (
_pkt_inf->
rm_seg << 4);
01631
01632 DOSMEMCLR (rm_base, RDATA_SIZE);
01633
return (0);
01634 }
01635
01636
static int lock_code_and_data (
void)
01637 {
01638
DWORD size = (
DWORD)_pkt_end - (
DWORD)
pkt_enqueue;
01639
01640 WATT_ASSERT ((
DWORD)_pkt_end > (
DWORD)pkt_enqueue);
01641
01642
if (_go32_dpmi_lock_code((
void*)pkt_enqueue, size) ||
01643 _go32_dpmi_lock_code((
void*)__movedata, 30) ||
01644 _go32_dpmi_lock_code((
void*)_movedatal, 30) ||
01645 _go32_dpmi_lock_code((
void*)__dj_movedata, 100) ||
01646 _go32_dpmi_lock_data(&_pkt_inf,
sizeof(_pkt_inf)) ||
01647 _go32_dpmi_lock_data(_pkt_inf,
sizeof(*_pkt_inf)))
01648
return (-1);
01649
01650
return (0);
01651 }
01652
01653
static void _unlock (
const void *addr,
DWORD size)
01654 {
01655 __dpmi_meminfo mem;
01656
DWORD base = 0;
01657
01658 __dpmi_get_segment_base_address (_my_ds(), &base);
01659 mem.address = base + (
DWORD)addr;
01660 mem.size = size;
01661 __dpmi_unlock_linear_region (&mem);
01662 }
01663
01664
static int unlock_code_and_data (
void)
01665 {
01666 _unlock ((
void*)pkt_enqueue, (
DWORD)_pkt_end - (
DWORD)pkt_enqueue);
01667 _unlock ((
void*)__movedata, 30);
01668 _unlock ((
void*)_movedatal, 30);
01669 _unlock ((
void*)__dj_movedata, 100);
01670 _unlock (_pkt_inf,
sizeof(*_pkt_inf));
01671 _unlock (&_pkt_inf,
sizeof(_pkt_inf));
01672
return (0);
01673 }
01674
01675
#elif (DOSX & DOS4GW)
01676
static int setup_rmode_callback (
void)
01677 {
01678
int length;
01679
01680
01681
01682
if (asmpkt_size_chk !=
sizeof(*_pkt_inf))
01683 {
01684
#ifdef USE_DEBUG
01685
fprintf (stderr,
01686
"%s (%u): Development error:\n"
01687
" sizeof(pkt_info) = %u pcpkt.h\n"
01688
" sizeof(pkt_info) = %u asmpkt4.asm, (diff %d)\n",
01689 __FILE__, __LINE__,
01690
sizeof(*_pkt_inf), asmpkt_size_chk,
01691
sizeof(*_pkt_inf) - asmpkt_size_chk);
01692
#endif
01693
return (-3);
01694 }
01695
01696
01697
01698 length = TX_BUF() + RX_SIZE;
01699
_pkt_inf->
rm_seg = dpmi_real_malloc (length, &
_pkt_inf->
rm_sel);
01700
if (!
_pkt_inf->
rm_seg)
01701
return (-2);
01702
01703 rm_base = ((
DWORD)
_pkt_inf->
rm_seg) << 4;
01704
01705
01706
01707 memset ((
void*)rm_base, 0, length);
01708 length = PKT_TMP() - 1;
01709 memcpy ((
void*)rm_base, pkt_receiver4_start, length);
01710
return (0);
01711 }
01712
01713
01714
01715
static int lock_code_and_data (
void)
01716 {
01717
return (0);
01718 }
01719
01720
static int unlock_code_and_data (
void)
01721 {
01722
return (0);
01723 }
01724
01725
#elif (DOSX & POWERPAK)
01726
static int setup_rmode_callback (
void)
01727 {
01728
01729
01730
_pkt_inf->
rm_seg = dpmi_real_malloc (RDATA_SIZE, &
_pkt_inf->
rm_sel);
01731
if (!
_pkt_inf->
rm_seg)
01732
return (-2);
01733
01734 rm_base = (REALPTR) ((
DWORD)
_pkt_inf->
rm_seg << 16);
01735
01736 rm_cb.pm_func = pkt_receiver_pm;
01737
if (!dpmi_alloc_callback_retf(&rm_cb))
01738
return (-1);
01739
return (0);
01740 }
01741
01742
static int lock_code_and_data (
void)
01743 {
01744
unsigned size = (
unsigned)_pkt_end - (
unsigned)
pkt_enqueue;
01745
01746
if (!dpmi_lock_region ((
void*)pkt_enqueue, size) ||
01747 !dpmi_lock_region ((
void*)ReadRealMem, 100) ||
01748 !dpmi_lock_region ((
void*)_pkt_inf,
sizeof(*_pkt_inf)) ||
01749 !dpmi_lock_region ((
void*)&_pkt_inf,
sizeof(_pkt_inf)))
01750
return (-1);
01751
return (0);
01752 }
01753
01754
static int unlock_code_and_data (
void)
01755 {
01756
unsigned size = (
unsigned)_pkt_end - (
unsigned)
pkt_enqueue;
01757
01758
if (!dpmi_unlock_region ((
void*)pkt_enqueue, size) ||
01759 !dpmi_unlock_region ((
void*)ReadRealMem, 100) ||
01760 !dpmi_unlock_region ((
void*)_pkt_inf,
sizeof(*_pkt_inf)) ||
01761 !dpmi_unlock_region ((
void*)&_pkt_inf,
sizeof(_pkt_inf)))
01762
return (-1);
01763
return (0);
01764 }
01765
#endif
01766
#endif
01767
01768
01769
01770
01771
01772
01773 static int setup_pkt_inf (
void)
01774 {
01779
int size =
sizeof (*_pkt_inf);
01780
01781
#if (DOSX & DOS4GW) && !defined(USE_FAST_PKT)
01782
DWORD seg;
01783
01784 WATT_ASSERT (size < USHRT_MAX);
01785
01786 seg = dpmi_real_malloc (size, &pkt_inf_sel);
01787
01788 asmpkt_inf = (
struct pkt_info*) (seg << 16);
01789
_pkt_inf = (
struct pkt_info*) (seg << 4);
01790
01791
#else
01792
_pkt_inf = malloc (size);
01793
#endif
01794
01795
if (!
_pkt_inf)
01796
return (0);
01797
01798 memset (
_pkt_inf, 0, size);
01799
01800
#if defined(USE_FAST_PKT)
01801
rm_base = setup_pkt_inf_fast();
01802
if (!rm_base)
01803
return (0);
01804
01805
#else
01806
pktq_init (&
_pkt_inf->
pkt_queue,
01807
sizeof(
_pkt_inf->
rx_buf[0]),
01808 DIM(
_pkt_inf->
rx_buf),
01809 (
char*)&
_pkt_inf->
rx_buf);
01810
#endif
01811
01812
#if (DOSX & DOS4GW) && !defined(USE_FAST_PKT)
01813
_pkt_inf->
pkt_queue.
dos_ofs = offsetof (
struct pkt_info, rx_buf[0]);
01814
#elif (DOSX & DJGPP)
01815
_pkt_inf->
dos_ds = _dos_ds;
01816
#endif
01817
01818
#if (DOSX & DJGPP)
01819
if (pkt_use_near)
01820 {
01821
if (!(_crt0_startup_flags & _CRT0_FLAG_NEARPTR))
01822 TCP_CONSOLE_MSG (1, (
"Near-pointers not enabled\n"));
01823
else
01824 {
01825
_pkt_inf->
use_near_ptr = TRUE;
01826 TCP_CONSOLE_MSG (1, (
"Near-pointers enabled\n"));
01827 }
01828 }
01829
else if (_crt0_startup_flags & _CRT0_FLAG_NEARPTR)
01830 TCP_CONSOLE_MSG (1, (
"Near-pointers on, but \"PKT.NEAR_PTR = 0\"\n"));
01831
#endif
01832
01833
return (1);
01834 }
01835
01836
01840 static void get_rmode_data (
void *dest,
unsigned size,
WORD seg,
WORD ofs)
01841 {
01842
#if (DOSX & (PHARLAP|X32VM|POWERPAK))
01843
REALPTR rp;
01844 RP_SET (rp, ofs, seg);
01845 ReadRealMem (dest, rp, size);
01846
01847
#elif (DOSX & DOS4GW)
01848
memcpy (dest, SEG_OFS_TO_LIN(seg,ofs), size);
01849
01850
#elif (DOSX & DJGPP)
01851
dosmemget (ofs + (seg << 4), size, dest);
01852
01853
#else
01854
_fmemcpy (dest, MK_FP(seg,ofs), size);
01855
#endif
01856
}
01857
01858
01866 static BOOL
pkt_api_entry (IREGS *reg,
unsigned line)
01867 {
01868
_pkt_errno = 0;
01869 reg->r_flags = 0;
01870
01871
#if (DOSX)
01872
01874
if (_pkt32_drvr)
01875 {
01876
if (!(*_pkt32_drvr)(reg))
01877 {
01878
01879 reg->r_flags |= CARRY_BIT;
01880
return (FALSE);
01881 }
01882
return (TRUE);
01883 }
01884
#endif
01885
01886
if (!pkt_interrupt)
01887 {
01888
#if defined(USE_DEBUG)
01889
fprintf (stderr,
"%s (%d): API called after deinit.\n", __FILE__, line);
01890
#endif
01891
reg->r_flags |= CARRY_BIT;
01892 ARGSUSED (line);
01893
_pkt_errno = PDERR_BAD_COMMAND;
01894
return (FALSE);
01895 }
01896
01897
01898
01899 GEN_INTERRUPT (pkt_interrupt, reg);
01900
01901
if (reg->r_flags & CARRY_BIT)
01902 {
01903
_pkt_errno = hiBYTE (reg->r_dx);
01904
return (FALSE);
01905 }
01906
return (TRUE);
01907 }
01908
01909
01924 int pkt_set_rcv_mode (
int mode)
01925 {
01926 IREGS regs;
01927
01928
if (!
_pkt_inf)
01929 {
01930
_pkt_errno = PDERR_BAD_HANDLE;
01931
return (0);
01932 }
01933
01934 regs.r_ax = PD_SET_RCV;
01935 regs.r_bx =
_pkt_inf->
handle;
01936 regs.r_cx = mode;
01937
01938
01939
01940
if (
_pktdevlevel < 2 ||
_pktserial)
01941 {
01942
_pkt_errno = PDERR_CANT_SET;
01943
return (0);
01944 }
01945
01946
if (!PKT_API(®s))
01947 {
01948 PKT_ERR (
"Error setting receiver mode: ",
_pkt_errno);
01949
return (0);
01950 }
01951
_pkt_rxmode = mode;
01952
return (1);
01953 }
01954
01968 int pkt_get_rcv_mode (
void)
01969 {
01970 IREGS regs;
01971
01972 ASSERT_PKT_INF (-1);
01973
01974 regs.r_ax = PD_GET_RCV;
01975 regs.r_bx =
_pkt_inf->
handle;
01976
01977
01978
01979
if (
_pktdevlevel < 2 ||
_pktserial)
01980 {
01981
_pkt_errno = PDERR_BAD_COMMAND;
01982
return (0);
01983 }
01984
01985
if (!PKT_API(®s))
01986 {
01987 PKT_ERR (
"Error getting receive mode: ",
_pkt_errno);
01988
return (0);
01989 }
01990
_pkt_rxmode = regs.r_ax;
01991
return (regs.r_ax);
01992 }
01993
01994
01995
#if defined(USE_MULTICAST)
01996
02006 int pkt_get_multicast_list (mac_address *listbuf,
int *lenp)
02007 {
02008 IREGS regs;
02009
int len = *lenp;
02010
02011 ASSERT_PKT_INF (0);
02012
02013 regs.r_ax = PD_GET_MULTI;
02014
_pkt_errno = PDERR_NO_MULTICAST;
02015
02016
02017
02018
if (
_pktdevlevel < 2 ||
_pktserial ||
02019 (got_params && pkt_params.multicast_avail == 0) ||
02020 !PKT_API(®s))
02021 {
02022
if (debug_on > 0)
02023 PKT_ERR (
"Error getting multicast list: ",
_pkt_errno);
02024
return (0);
02025 }
02026
02027
if ((
WORD)regs.r_cx == 0)
02028 {
02029 memset (listbuf, 0, len);
02030 *lenp = 0;
02031
return (1);
02032 }
02033
02034
02035
02036 DISABLE();
02037 len = min (len, (
WORD)regs.r_cx);
02038
get_rmode_data (listbuf, len, regs.r_es, regs.r_di);
02039 *lenp = len;
02040 ENABLE();
02041
return (1);
02042 }
02043
02053 int pkt_set_multicast_list (
const void *listbuf,
int len)
02054 {
02055 IREGS regs;
02056
WORD seg, ofs;
02057
02058 ASSERT_PKT_INF (0);
02059
02060
02061
02062
if (
_pktdevlevel < 2 ||
_pktserial ||
02063 (got_params && pkt_params.multicast_avail == 0))
02064 {
02065
_pkt_errno = PDERR_NO_MULTICAST;
02066
return (0);
02067 }
02068
02069
#if (DOSX)
02070
if (len > PKT_TMP_SIZE)
02071 {
02072
_pkt_errno = PDERR_NO_SPACE;
02073
return (0);
02074 }
02075
#endif
02076
02077 DISABLE();
02078
02079
#if (DOSX & (PHARLAP|X32VM|POWERPAK))
02080
seg = RP_SEGM();
02081 ofs = PKT_TMP();
02082 WriteRealMem (rm_base + PKT_TMP(), (
void*)listbuf, len);
02083
02084
#elif (DOSX & DOS4GW)
02085
seg = RP_SEGM();
02086 ofs = PKT_TMP();
02087 memcpy ((
void*)(rm_base + PKT_TMP()), listbuf, len);
02088
02089
#elif (DOSX & DJGPP)
02090
seg = RP_SEGM();
02091 ofs = PKT_TMP();
02092 DOSMEMPUT (listbuf, len, rm_base + PKT_TMP());
02093
02094
#else
02095
seg = FP_SEG (listbuf);
02096 ofs = FP_OFF (listbuf);
02097
#endif
02098
02099 ENABLE();
02100
02101 regs.r_ax = PD_SET_MULTI;
02102 regs.r_cx = len;
02103 regs.r_es = seg;
02104 regs.r_di = ofs;
02105
02106
if (!PKT_API(®s))
02107 {
02108
if (debug_on > 0)
02109 PKT_ERR (
"Error setting multicast list: ",
_pkt_errno);
02110
return (0);
02111 }
02112
return (1);
02113 }
02114
#endif
02115
#endif
02116