JP Abgrall | 511eca3 | 2014-02-12 13:46:45 -0800 | [diff] [blame] | 1 | /*
|
| 2 | * File.........: pktdrvr.c
|
| 3 | *
|
| 4 | * Responsible..: Gisle Vanem, giva@bgnett.no
|
| 5 | *
|
| 6 | * Created......: 26.Sept 1995
|
| 7 | *
|
| 8 | * Description..: Packet-driver interface for 16/32-bit C :
|
| 9 | * Borland C/C++ 3.0+ small/large model
|
| 10 | * Watcom C/C++ 11+, DOS4GW flat model
|
| 11 | * Metaware HighC 3.1+ and PharLap 386|DosX
|
| 12 | * GNU C/C++ 2.7+ and djgpp 2.x extender
|
| 13 | *
|
| 14 | * References...: PC/TCP Packet driver Specification. rev 1.09
|
| 15 | * FTP Software Inc.
|
| 16 | *
|
| 17 | */
|
| 18 |
|
| 19 | #include <stdio.h>
|
| 20 | #include <stdlib.h>
|
| 21 | #include <string.h>
|
| 22 | #include <dos.h>
|
| 23 |
|
| 24 | #include "pcap-dos.h"
|
| 25 | #include "pcap-int.h"
|
| 26 | #include "msdos/pktdrvr.h"
|
| 27 |
|
| 28 | #if (DOSX)
|
| 29 | #define NUM_RX_BUF 32 /* # of buffers in Rx FIFO queue */
|
| 30 | #else
|
| 31 | #define NUM_RX_BUF 10
|
| 32 | #endif
|
| 33 |
|
| 34 | #define DIM(x) (sizeof((x)) / sizeof(x[0]))
|
| 35 | #define PUTS(s) do { \
|
| 36 | if (!pktInfo.quiet) \
|
| 37 | pktInfo.error ? \
|
| 38 | printf ("%s: %s\n", s, pktInfo.error) : \
|
| 39 | printf ("%s\n", pktInfo.error = s); \
|
| 40 | } while (0)
|
| 41 |
|
| 42 | #if defined(__HIGHC__)
|
| 43 | extern UINT _mwenv;
|
| 44 |
|
| 45 | #elif defined(__DJGPP__)
|
| 46 | #include <stddef.h>
|
| 47 | #include <dpmi.h>
|
| 48 | #include <go32.h>
|
| 49 | #include <pc.h>
|
| 50 | #include <sys/farptr.h>
|
| 51 |
|
| 52 | #elif defined(__WATCOMC__)
|
| 53 | #include <i86.h>
|
| 54 | #include <stddef.h>
|
| 55 | extern char _Extender;
|
| 56 |
|
| 57 | #else
|
| 58 | extern void far PktReceiver (void);
|
| 59 | #endif
|
| 60 |
|
| 61 |
|
| 62 | #if (DOSX & (DJGPP|DOS4GW))
|
| 63 | #include <sys/pack_on.h>
|
| 64 |
|
| 65 | struct DPMI_regs {
|
| 66 | DWORD r_di;
|
| 67 | DWORD r_si;
|
| 68 | DWORD r_bp;
|
| 69 | DWORD reserved;
|
| 70 | DWORD r_bx;
|
| 71 | DWORD r_dx;
|
| 72 | DWORD r_cx;
|
| 73 | DWORD r_ax;
|
| 74 | WORD r_flags;
|
| 75 | WORD r_es, r_ds, r_fs, r_gs;
|
| 76 | WORD r_ip, r_cs, r_sp, r_ss;
|
| 77 | };
|
| 78 |
|
| 79 | /* Data located in a real-mode segment. This becomes far at runtime
|
| 80 | */
|
| 81 | typedef struct { /* must match data/code in pkt_rx1.s */
|
| 82 | WORD _rxOutOfs;
|
| 83 | WORD _rxInOfs;
|
| 84 | DWORD _pktDrop;
|
| 85 | BYTE _pktTemp [20];
|
| 86 | TX_ELEMENT _pktTxBuf[1];
|
| 87 | RX_ELEMENT _pktRxBuf[NUM_RX_BUF];
|
| 88 | WORD _dummy[2]; /* screenSeg,newInOffset */
|
| 89 | BYTE _fanChars[4];
|
| 90 | WORD _fanIndex;
|
| 91 | BYTE _PktReceiver[15]; /* starts on a paragraph (16byte) */
|
| 92 | } PktRealStub;
|
| 93 | #include <sys/pack_off.h>
|
| 94 |
|
| 95 | static BYTE real_stub_array [] = {
|
| 96 | #include "pkt_stub.inc" /* generated opcode array */
|
| 97 | };
|
| 98 |
|
| 99 | #define rxOutOfs offsetof (PktRealStub,_rxOutOfs)
|
| 100 | #define rxInOfs offsetof (PktRealStub,_rxInOfs)
|
| 101 | #define PktReceiver offsetof (PktRealStub,_PktReceiver [para_skip])
|
| 102 | #define pktDrop offsetof (PktRealStub,_pktDrop)
|
| 103 | #define pktTemp offsetof (PktRealStub,_pktTemp)
|
| 104 | #define pktTxBuf offsetof (PktRealStub,_pktTxBuf)
|
| 105 | #define FIRST_RX_BUF offsetof (PktRealStub,_pktRxBuf [0])
|
| 106 | #define LAST_RX_BUF offsetof (PktRealStub,_pktRxBuf [NUM_RX_BUF-1])
|
| 107 |
|
| 108 | #else
|
| 109 | extern WORD rxOutOfs; /* offsets into pktRxBuf FIFO queue */
|
| 110 | extern WORD rxInOfs;
|
| 111 | extern DWORD pktDrop; /* # packets dropped in PktReceiver() */
|
| 112 | extern BYTE pktRxEnd; /* marks the end of r-mode code/data */
|
| 113 |
|
| 114 | extern RX_ELEMENT pktRxBuf [NUM_RX_BUF]; /* PktDrvr Rx buffers */
|
| 115 | extern TX_ELEMENT pktTxBuf; /* PktDrvr Tx buffer */
|
| 116 | extern char pktTemp[20]; /* PktDrvr temp area */
|
| 117 |
|
| 118 | #define FIRST_RX_BUF (WORD) &pktRxBuf [0]
|
| 119 | #define LAST_RX_BUF (WORD) &pktRxBuf [NUM_RX_BUF-1]
|
| 120 | #endif
|
| 121 |
|
| 122 |
|
| 123 | #ifdef __BORLANDC__ /* Use Borland's inline functions */
|
| 124 | #define memcpy __memcpy__
|
| 125 | #define memcmp __memcmp__
|
| 126 | #define memset __memset__
|
| 127 | #endif
|
| 128 |
|
| 129 |
|
| 130 | #if (DOSX & PHARLAP)
|
| 131 | extern void PktReceiver (void); /* in pkt_rx0.asm */
|
| 132 | static int RealCopy (ULONG, ULONG, REALPTR*, FARPTR*, USHORT*);
|
| 133 |
|
| 134 | #undef FP_SEG
|
| 135 | #undef FP_OFF
|
| 136 | #define FP_OFF(x) ((WORD)(x))
|
| 137 | #define FP_SEG(x) ((WORD)(realBase >> 16))
|
| 138 | #define DOS_ADDR(s,o) (((DWORD)(s) << 16) + (WORD)(o))
|
| 139 | #define r_ax eax
|
| 140 | #define r_bx ebx
|
| 141 | #define r_dx edx
|
| 142 | #define r_cx ecx
|
| 143 | #define r_si esi
|
| 144 | #define r_di edi
|
| 145 | #define r_ds ds
|
| 146 | #define r_es es
|
| 147 | LOCAL FARPTR protBase;
|
| 148 | LOCAL REALPTR realBase;
|
| 149 | LOCAL WORD realSeg; /* DOS para-address of allocated area */
|
| 150 | LOCAL SWI_REGS reg;
|
| 151 |
|
| 152 | static WORD _far *rxOutOfsFp, *rxInOfsFp;
|
| 153 |
|
| 154 | #elif (DOSX & DJGPP)
|
| 155 | static _go32_dpmi_seginfo rm_mem;
|
| 156 | static __dpmi_regs reg;
|
| 157 | static DWORD realBase;
|
| 158 | static int para_skip = 0;
|
| 159 |
|
| 160 | #define DOS_ADDR(s,o) (((WORD)(s) << 4) + (o))
|
| 161 | #define r_ax x.ax
|
| 162 | #define r_bx x.bx
|
| 163 | #define r_dx x.dx
|
| 164 | #define r_cx x.cx
|
| 165 | #define r_si x.si
|
| 166 | #define r_di x.di
|
| 167 | #define r_ds x.ds
|
| 168 | #define r_es x.es
|
| 169 |
|
| 170 | #elif (DOSX & DOS4GW)
|
| 171 | LOCAL struct DPMI_regs reg;
|
| 172 | LOCAL WORD rm_base_seg, rm_base_sel;
|
| 173 | LOCAL DWORD realBase;
|
| 174 | LOCAL int para_skip = 0;
|
| 175 |
|
| 176 | LOCAL DWORD dpmi_get_real_vector (int intr);
|
| 177 | LOCAL WORD dpmi_real_malloc (int size, WORD *selector);
|
| 178 | LOCAL void dpmi_real_free (WORD selector);
|
| 179 | #define DOS_ADDR(s,o) (((DWORD)(s) << 4) + (WORD)(o))
|
| 180 |
|
| 181 | #else /* real-mode Borland etc. */
|
| 182 | static struct {
|
| 183 | WORD r_ax, r_bx, r_cx, r_dx, r_bp;
|
| 184 | WORD r_si, r_di, r_ds, r_es, r_flags;
|
| 185 | } reg;
|
| 186 | #endif
|
| 187 |
|
| 188 | #ifdef __HIGHC__
|
| 189 | #pragma Alias (pktDrop, "_pktDrop")
|
| 190 | #pragma Alias (pktRxBuf, "_pktRxBuf")
|
| 191 | #pragma Alias (pktTxBuf, "_pktTxBuf")
|
| 192 | #pragma Alias (pktTemp, "_pktTemp")
|
| 193 | #pragma Alias (rxOutOfs, "_rxOutOfs")
|
| 194 | #pragma Alias (rxInOfs, "_rxInOfs")
|
| 195 | #pragma Alias (pktRxEnd, "_pktRxEnd")
|
| 196 | #pragma Alias (PktReceiver,"_PktReceiver")
|
| 197 | #endif
|
| 198 |
|
| 199 |
|
| 200 | PUBLIC PKT_STAT pktStat; /* statistics for packets */
|
| 201 | PUBLIC PKT_INFO pktInfo; /* packet-driver information */
|
| 202 |
|
| 203 | PUBLIC PKT_RX_MODE receiveMode = PDRX_DIRECT;
|
| 204 | PUBLIC ETHER myAddress = { 0, 0, 0, 0, 0, 0 };
|
| 205 | PUBLIC ETHER ethBroadcast = { 255,255,255,255,255,255 };
|
| 206 |
|
| 207 | LOCAL struct { /* internal statistics */
|
| 208 | DWORD tooSmall; /* size < ETH_MIN */
|
| 209 | DWORD tooLarge; /* size > ETH_MAX */
|
| 210 | DWORD badSync; /* count_1 != count_2 */
|
| 211 | DWORD wrongHandle; /* upcall to wrong handle */
|
| 212 | } intStat;
|
| 213 |
|
| 214 | /***************************************************************************/
|
| 215 |
|
| 216 | PUBLIC const char *PktGetErrorStr (int errNum)
|
| 217 | {
|
| 218 | static const char *errStr[] = {
|
| 219 | "",
|
| 220 | "Invalid handle number",
|
| 221 | "No interfaces of specified class found",
|
| 222 | "No interfaces of specified type found",
|
| 223 | "No interfaces of specified number found",
|
| 224 | "Bad packet type specified",
|
| 225 | "Interface does not support multicast",
|
| 226 | "Packet driver cannot terminate",
|
| 227 | "Invalid receiver mode specified",
|
| 228 | "Insufficient memory space",
|
| 229 | "Type previously accessed, and not released",
|
| 230 | "Command out of range, or not implemented",
|
| 231 | "Cannot send packet (usually hardware error)",
|
| 232 | "Cannot change hardware address ( > 1 handle open)",
|
| 233 | "Hardware address has bad length or format",
|
| 234 | "Cannot reset interface (more than 1 handle open)",
|
| 235 | "Bad Check-sum",
|
| 236 | "Bad size",
|
| 237 | "Bad sync" ,
|
| 238 | "Source hit"
|
| 239 | };
|
| 240 |
|
| 241 | if (errNum < 0 || errNum >= DIM(errStr))
|
| 242 | return ("Unknown driver error.");
|
| 243 | return (errStr [errNum]);
|
| 244 | }
|
| 245 |
|
| 246 | /**************************************************************************/
|
| 247 |
|
| 248 | PUBLIC const char *PktGetClassName (WORD class)
|
| 249 | {
|
| 250 | switch (class)
|
| 251 | {
|
| 252 | case PD_ETHER:
|
| 253 | return ("DIX-Ether");
|
| 254 | case PD_PRONET10:
|
| 255 | return ("ProNET-10");
|
| 256 | case PD_IEEE8025:
|
| 257 | return ("IEEE 802.5");
|
| 258 | case PD_OMNINET:
|
| 259 | return ("OmniNet");
|
| 260 | case PD_APPLETALK:
|
| 261 | return ("AppleTalk");
|
| 262 | case PD_SLIP:
|
| 263 | return ("SLIP");
|
| 264 | case PD_STARTLAN:
|
| 265 | return ("StartLAN");
|
| 266 | case PD_ARCNET:
|
| 267 | return ("ArcNet");
|
| 268 | case PD_AX25:
|
| 269 | return ("AX.25");
|
| 270 | case PD_KISS:
|
| 271 | return ("KISS");
|
| 272 | case PD_IEEE8023_2:
|
| 273 | return ("IEEE 802.3 w/802.2 hdr");
|
| 274 | case PD_FDDI8022:
|
| 275 | return ("FDDI w/802.2 hdr");
|
| 276 | case PD_X25:
|
| 277 | return ("X.25");
|
| 278 | case PD_LANstar:
|
| 279 | return ("LANstar");
|
| 280 | case PD_PPP:
|
| 281 | return ("PPP");
|
| 282 | default:
|
| 283 | return ("unknown");
|
| 284 | }
|
| 285 | }
|
| 286 |
|
| 287 | /**************************************************************************/
|
| 288 |
|
| 289 | PUBLIC char const *PktRXmodeStr (PKT_RX_MODE mode)
|
| 290 | {
|
| 291 | static const char *modeStr [] = {
|
| 292 | "Receiver turned off",
|
| 293 | "Receive only directly addressed packets",
|
| 294 | "Receive direct & broadcast packets",
|
| 295 | "Receive direct,broadcast and limited multicast packets",
|
| 296 | "Receive direct,broadcast and all multicast packets",
|
| 297 | "Receive all packets (promiscuouos mode)"
|
| 298 | };
|
| 299 |
|
| 300 | if (mode > DIM(modeStr))
|
| 301 | return ("??");
|
| 302 | return (modeStr [mode-1]);
|
| 303 | }
|
| 304 |
|
| 305 | /**************************************************************************/
|
| 306 |
|
| 307 | LOCAL __inline BOOL PktInterrupt (void)
|
| 308 | {
|
| 309 | BOOL okay;
|
| 310 |
|
| 311 | #if (DOSX & PHARLAP)
|
| 312 | _dx_real_int ((UINT)pktInfo.intr, ®);
|
| 313 | okay = ((reg.flags & 1) == 0); /* OK if carry clear */
|
| 314 |
|
| 315 | #elif (DOSX & DJGPP)
|
| 316 | __dpmi_int ((int)pktInfo.intr, ®);
|
| 317 | okay = ((reg.x.flags & 1) == 0);
|
| 318 |
|
| 319 | #elif (DOSX & DOS4GW)
|
| 320 | union REGS r;
|
| 321 | struct SREGS s;
|
| 322 |
|
| 323 | memset (&r, 0, sizeof(r));
|
| 324 | segread (&s);
|
| 325 | r.w.ax = 0x300;
|
| 326 | r.x.ebx = pktInfo.intr;
|
| 327 | r.w.cx = 0;
|
| 328 | s.es = FP_SEG (®);
|
| 329 | r.x.edi = FP_OFF (®);
|
| 330 | reg.r_flags = 0;
|
| 331 | reg.r_ss = reg.r_sp = 0; /* DPMI host provides stack */
|
| 332 |
|
| 333 | int386x (0x31, &r, &r, &s);
|
| 334 | okay = (!r.w.cflag);
|
| 335 |
|
| 336 | #else
|
| 337 | reg.r_flags = 0;
|
| 338 | intr (pktInfo.intr, (struct REGPACK*)®);
|
| 339 | okay = ((reg.r_flags & 1) == 0);
|
| 340 | #endif
|
| 341 |
|
| 342 | if (okay)
|
| 343 | pktInfo.error = NULL;
|
| 344 | else pktInfo.error = PktGetErrorStr (reg.r_dx >> 8);
|
| 345 | return (okay);
|
| 346 | }
|
| 347 |
|
| 348 | /**************************************************************************/
|
| 349 |
|
| 350 | /*
|
| 351 | * Search for packet driver at interrupt 60h through 80h. If ASCIIZ
|
| 352 | * string "PKT DRVR" found at offset 3 in the interrupt handler, return
|
| 353 | * interrupt number, else return zero in pktInfo.intr
|
| 354 | */
|
| 355 | PUBLIC BOOL PktSearchDriver (void)
|
| 356 | {
|
| 357 | BYTE intr = 0x20;
|
| 358 | BOOL found = FALSE;
|
| 359 |
|
| 360 | while (!found && intr < 0xFF)
|
| 361 | {
|
| 362 | static char str[12]; /* 3 + strlen("PKT DRVR") */
|
| 363 | static char pktStr[9] = "PKT DRVR"; /* ASCIIZ string at ofs 3 */
|
| 364 | DWORD rp; /* in interrupt routine */
|
| 365 |
|
| 366 | #if (DOSX & PHARLAP)
|
| 367 | _dx_rmiv_get (intr, &rp);
|
| 368 | ReadRealMem (&str, (REALPTR)rp, sizeof(str));
|
| 369 |
|
| 370 | #elif (DOSX & DJGPP)
|
| 371 | __dpmi_raddr realAdr;
|
| 372 | __dpmi_get_real_mode_interrupt_vector (intr, &realAdr);
|
| 373 | rp = (realAdr.segment << 4) + realAdr.offset16;
|
| 374 | dosmemget (rp, sizeof(str), &str);
|
| 375 |
|
| 376 | #elif (DOSX & DOS4GW)
|
| 377 | rp = dpmi_get_real_vector (intr);
|
| 378 | memcpy (&str, (void*)rp, sizeof(str));
|
| 379 |
|
| 380 | #else
|
| 381 | _fmemcpy (&str, getvect(intr), sizeof(str));
|
| 382 | #endif
|
| 383 |
|
| 384 | found = memcmp (&str[3],&pktStr,sizeof(pktStr)) == 0;
|
| 385 | intr++;
|
| 386 | }
|
| 387 | pktInfo.intr = (found ? intr-1 : 0);
|
| 388 | return (found);
|
| 389 | }
|
| 390 |
|
| 391 |
|
| 392 | /**************************************************************************/
|
| 393 |
|
| 394 | static BOOL PktSetAccess (void)
|
| 395 | {
|
| 396 | reg.r_ax = 0x0200 + pktInfo.class;
|
| 397 | reg.r_bx = 0xFFFF;
|
| 398 | reg.r_dx = 0;
|
| 399 | reg.r_cx = 0;
|
| 400 |
|
| 401 | #if (DOSX & PHARLAP)
|
| 402 | reg.ds = 0;
|
| 403 | reg.esi = 0;
|
| 404 | reg.es = RP_SEG (realBase);
|
| 405 | reg.edi = (WORD) &PktReceiver;
|
| 406 |
|
| 407 | #elif (DOSX & DJGPP)
|
| 408 | reg.x.ds = 0;
|
| 409 | reg.x.si = 0;
|
| 410 | reg.x.es = rm_mem.rm_segment;
|
| 411 | reg.x.di = PktReceiver;
|
| 412 |
|
| 413 | #elif (DOSX & DOS4GW)
|
| 414 | reg.r_ds = 0;
|
| 415 | reg.r_si = 0;
|
| 416 | reg.r_es = rm_base_seg;
|
| 417 | reg.r_di = PktReceiver;
|
| 418 |
|
| 419 | #else
|
| 420 | reg.r_ds = 0;
|
| 421 | reg.r_si = 0;
|
| 422 | reg.r_es = FP_SEG (&PktReceiver);
|
| 423 | reg.r_di = FP_OFF (&PktReceiver);
|
| 424 | #endif
|
| 425 |
|
| 426 | if (!PktInterrupt())
|
| 427 | return (FALSE);
|
| 428 |
|
| 429 | pktInfo.handle = reg.r_ax;
|
| 430 | return (TRUE);
|
| 431 | }
|
| 432 |
|
| 433 | /**************************************************************************/
|
| 434 |
|
| 435 | PUBLIC BOOL PktReleaseHandle (WORD handle)
|
| 436 | {
|
| 437 | reg.r_ax = 0x0300;
|
| 438 | reg.r_bx = handle;
|
| 439 | return PktInterrupt();
|
| 440 | }
|
| 441 |
|
| 442 | /**************************************************************************/
|
| 443 |
|
| 444 | PUBLIC BOOL PktTransmit (const void *eth, int len)
|
| 445 | {
|
| 446 | if (len > ETH_MTU)
|
| 447 | return (FALSE);
|
| 448 |
|
| 449 | reg.r_ax = 0x0400; /* Function 4, send pkt */
|
| 450 | reg.r_cx = len; /* total size of frame */
|
| 451 |
|
| 452 | #if (DOSX & DJGPP)
|
| 453 | dosmemput (eth, len, realBase+pktTxBuf);
|
| 454 | reg.x.ds = rm_mem.rm_segment; /* DOS data segment and */
|
| 455 | reg.x.si = pktTxBuf; /* DOS offset to buffer */
|
| 456 |
|
| 457 | #elif (DOSX & DOS4GW)
|
| 458 | memcpy ((void*)(realBase+pktTxBuf), eth, len);
|
| 459 | reg.r_ds = rm_base_seg;
|
| 460 | reg.r_si = pktTxBuf;
|
| 461 |
|
| 462 | #elif (DOSX & PHARLAP)
|
| 463 | memcpy (&pktTxBuf, eth, len);
|
| 464 | reg.r_ds = FP_SEG (&pktTxBuf);
|
| 465 | reg.r_si = FP_OFF (&pktTxBuf);
|
| 466 |
|
| 467 | #else
|
| 468 | reg.r_ds = FP_SEG (eth);
|
| 469 | reg.r_si = FP_OFF (eth);
|
| 470 | #endif
|
| 471 |
|
| 472 | return PktInterrupt();
|
| 473 | }
|
| 474 |
|
| 475 | /**************************************************************************/
|
| 476 |
|
| 477 | #if (DOSX & (DJGPP|DOS4GW))
|
| 478 | LOCAL __inline BOOL CheckElement (RX_ELEMENT *rx)
|
| 479 | #else
|
| 480 | LOCAL __inline BOOL CheckElement (RX_ELEMENT _far *rx)
|
| 481 | #endif
|
| 482 | {
|
| 483 | WORD count_1, count_2;
|
| 484 |
|
| 485 | /*
|
| 486 | * We got an upcall to the same RMCB with wrong handle.
|
| 487 | * This can happen if we failed to release handle at program exit
|
| 488 | */
|
| 489 | if (rx->handle != pktInfo.handle)
|
| 490 | {
|
| 491 | pktInfo.error = "Wrong handle";
|
| 492 | intStat.wrongHandle++;
|
| 493 | PktReleaseHandle (rx->handle);
|
| 494 | return (FALSE);
|
| 495 | }
|
| 496 | count_1 = rx->firstCount;
|
| 497 | count_2 = rx->secondCount;
|
| 498 |
|
| 499 | if (count_1 != count_2)
|
| 500 | {
|
| 501 | pktInfo.error = "Bad sync";
|
| 502 | intStat.badSync++;
|
| 503 | return (FALSE);
|
| 504 | }
|
| 505 | if (count_1 > ETH_MAX)
|
| 506 | {
|
| 507 | pktInfo.error = "Large esize";
|
| 508 | intStat.tooLarge++;
|
| 509 | return (FALSE);
|
| 510 | }
|
| 511 | #if 0
|
| 512 | if (count_1 < ETH_MIN)
|
| 513 | {
|
| 514 | pktInfo.error = "Small esize";
|
| 515 | intStat.tooSmall++;
|
| 516 | return (FALSE);
|
| 517 | }
|
| 518 | #endif
|
| 519 | return (TRUE);
|
| 520 | }
|
| 521 |
|
| 522 | /**************************************************************************/
|
| 523 |
|
| 524 | PUBLIC BOOL PktTerminHandle (WORD handle)
|
| 525 | {
|
| 526 | reg.r_ax = 0x0500;
|
| 527 | reg.r_bx = handle;
|
| 528 | return PktInterrupt();
|
| 529 | }
|
| 530 |
|
| 531 | /**************************************************************************/
|
| 532 |
|
| 533 | PUBLIC BOOL PktResetInterface (WORD handle)
|
| 534 | {
|
| 535 | reg.r_ax = 0x0700;
|
| 536 | reg.r_bx = handle;
|
| 537 | return PktInterrupt();
|
| 538 | }
|
| 539 |
|
| 540 | /**************************************************************************/
|
| 541 |
|
| 542 | PUBLIC BOOL PktSetReceiverMode (PKT_RX_MODE mode)
|
| 543 | {
|
| 544 | if (pktInfo.class == PD_SLIP || pktInfo.class == PD_PPP)
|
| 545 | return (TRUE);
|
| 546 |
|
| 547 | reg.r_ax = 0x1400;
|
| 548 | reg.r_bx = pktInfo.handle;
|
| 549 | reg.r_cx = (WORD)mode;
|
| 550 |
|
| 551 | if (!PktInterrupt())
|
| 552 | return (FALSE);
|
| 553 |
|
| 554 | receiveMode = mode;
|
| 555 | return (TRUE);
|
| 556 | }
|
| 557 |
|
| 558 | /**************************************************************************/
|
| 559 |
|
| 560 | PUBLIC BOOL PktGetReceiverMode (PKT_RX_MODE *mode)
|
| 561 | {
|
| 562 | reg.r_ax = 0x1500;
|
| 563 | reg.r_bx = pktInfo.handle;
|
| 564 |
|
| 565 | if (!PktInterrupt())
|
| 566 | return (FALSE);
|
| 567 |
|
| 568 | *mode = reg.r_ax;
|
| 569 | return (TRUE);
|
| 570 | }
|
| 571 |
|
| 572 | /**************************************************************************/
|
| 573 |
|
| 574 | static PKT_STAT initialStat; /* statistics at startup */
|
| 575 | static BOOL resetStat = FALSE; /* statistics reset ? */
|
| 576 |
|
| 577 | PUBLIC BOOL PktGetStatistics (WORD handle)
|
| 578 | {
|
| 579 | reg.r_ax = 0x1800;
|
| 580 | reg.r_bx = handle;
|
| 581 |
|
| 582 | if (!PktInterrupt())
|
| 583 | return (FALSE);
|
| 584 |
|
| 585 | #if (DOSX & PHARLAP)
|
| 586 | ReadRealMem (&pktStat, DOS_ADDR(reg.ds,reg.esi), sizeof(pktStat));
|
| 587 |
|
| 588 | #elif (DOSX & DJGPP)
|
| 589 | dosmemget (DOS_ADDR(reg.x.ds,reg.x.si), sizeof(pktStat), &pktStat);
|
| 590 |
|
| 591 | #elif (DOSX & DOS4GW)
|
| 592 | memcpy (&pktStat, (void*)DOS_ADDR(reg.r_ds,reg.r_si), sizeof(pktStat));
|
| 593 |
|
| 594 | #else
|
| 595 | _fmemcpy (&pktStat, MK_FP(reg.r_ds,reg.r_si), sizeof(pktStat));
|
| 596 | #endif
|
| 597 |
|
| 598 | return (TRUE);
|
| 599 | }
|
| 600 |
|
| 601 | /**************************************************************************/
|
| 602 |
|
| 603 | PUBLIC BOOL PktSessStatistics (WORD handle)
|
| 604 | {
|
| 605 | if (!PktGetStatistics(pktInfo.handle))
|
| 606 | return (FALSE);
|
| 607 |
|
| 608 | if (resetStat)
|
| 609 | {
|
| 610 | pktStat.inPackets -= initialStat.inPackets;
|
| 611 | pktStat.outPackets -= initialStat.outPackets;
|
| 612 | pktStat.inBytes -= initialStat.inBytes;
|
| 613 | pktStat.outBytes -= initialStat.outBytes;
|
| 614 | pktStat.inErrors -= initialStat.inErrors;
|
| 615 | pktStat.outErrors -= initialStat.outErrors;
|
| 616 | pktStat.outErrors -= initialStat.outErrors;
|
| 617 | pktStat.lost -= initialStat.lost;
|
| 618 | }
|
| 619 | return (TRUE);
|
| 620 | }
|
| 621 |
|
| 622 | /**************************************************************************/
|
| 623 |
|
| 624 | PUBLIC BOOL PktResetStatistics (WORD handle)
|
| 625 | {
|
| 626 | if (!PktGetStatistics(pktInfo.handle))
|
| 627 | return (FALSE);
|
| 628 |
|
| 629 | memcpy (&initialStat, &pktStat, sizeof(initialStat));
|
| 630 | resetStat = TRUE;
|
| 631 | return (TRUE);
|
| 632 | }
|
| 633 |
|
| 634 | /**************************************************************************/
|
| 635 |
|
| 636 | PUBLIC BOOL PktGetAddress (ETHER *addr)
|
| 637 | {
|
| 638 | reg.r_ax = 0x0600;
|
| 639 | reg.r_bx = pktInfo.handle;
|
| 640 | reg.r_cx = sizeof (*addr);
|
| 641 |
|
| 642 | #if (DOSX & DJGPP)
|
| 643 | reg.x.es = rm_mem.rm_segment;
|
| 644 | reg.x.di = pktTemp;
|
| 645 | #elif (DOSX & DOS4GW)
|
| 646 | reg.r_es = rm_base_seg;
|
| 647 | reg.r_di = pktTemp;
|
| 648 | #else
|
| 649 | reg.r_es = FP_SEG (&pktTemp);
|
| 650 | reg.r_di = FP_OFF (&pktTemp); /* ES:DI = address for result */
|
| 651 | #endif
|
| 652 |
|
| 653 | if (!PktInterrupt())
|
| 654 | return (FALSE);
|
| 655 |
|
| 656 | #if (DOSX & PHARLAP)
|
| 657 | ReadRealMem (addr, realBase + (WORD)&pktTemp, sizeof(*addr));
|
| 658 |
|
| 659 | #elif (DOSX & DJGPP)
|
| 660 | dosmemget (realBase+pktTemp, sizeof(*addr), addr);
|
| 661 |
|
| 662 | #elif (DOSX & DOS4GW)
|
| 663 | memcpy (addr, (void*)(realBase+pktTemp), sizeof(*addr));
|
| 664 |
|
| 665 | #else
|
| 666 | memcpy ((void*)addr, &pktTemp, sizeof(*addr));
|
| 667 | #endif
|
| 668 |
|
| 669 | return (TRUE);
|
| 670 | }
|
| 671 |
|
| 672 | /**************************************************************************/
|
| 673 |
|
| 674 | PUBLIC BOOL PktSetAddress (const ETHER *addr)
|
| 675 | {
|
| 676 | /* copy addr to real-mode scrath area */
|
| 677 |
|
| 678 | #if (DOSX & PHARLAP)
|
| 679 | WriteRealMem (realBase + (WORD)&pktTemp, (void*)addr, sizeof(*addr));
|
| 680 |
|
| 681 | #elif (DOSX & DJGPP)
|
| 682 | dosmemput (addr, sizeof(*addr), realBase+pktTemp);
|
| 683 |
|
| 684 | #elif (DOSX & DOS4GW)
|
| 685 | memcpy ((void*)(realBase+pktTemp), addr, sizeof(*addr));
|
| 686 |
|
| 687 | #else
|
| 688 | memcpy (&pktTemp, (void*)addr, sizeof(*addr));
|
| 689 | #endif
|
| 690 |
|
| 691 | reg.r_ax = 0x1900;
|
| 692 | reg.r_cx = sizeof (*addr); /* address length */
|
| 693 |
|
| 694 | #if (DOSX & DJGPP)
|
| 695 | reg.x.es = rm_mem.rm_segment; /* DOS offset to param */
|
| 696 | reg.x.di = pktTemp; /* DOS segment to param */
|
| 697 | #elif (DOSX & DOS4GW)
|
| 698 | reg.r_es = rm_base_seg;
|
| 699 | reg.r_di = pktTemp;
|
| 700 | #else
|
| 701 | reg.r_es = FP_SEG (&pktTemp);
|
| 702 | reg.r_di = FP_OFF (&pktTemp);
|
| 703 | #endif
|
| 704 |
|
| 705 | return PktInterrupt();
|
| 706 | }
|
| 707 |
|
| 708 | /**************************************************************************/
|
| 709 |
|
| 710 | PUBLIC BOOL PktGetDriverInfo (void)
|
| 711 | {
|
| 712 | pktInfo.majVer = 0;
|
| 713 | pktInfo.minVer = 0;
|
| 714 | memset (&pktInfo.name, 0, sizeof(pktInfo.name));
|
| 715 | reg.r_ax = 0x01FF;
|
| 716 | reg.r_bx = 0;
|
| 717 |
|
| 718 | if (!PktInterrupt())
|
| 719 | return (FALSE);
|
| 720 |
|
| 721 | pktInfo.number = reg.r_cx & 0xFF;
|
| 722 | pktInfo.class = reg.r_cx >> 8;
|
| 723 | #if 0
|
| 724 | pktInfo.minVer = reg.r_bx % 10;
|
| 725 | pktInfo.majVer = reg.r_bx / 10;
|
| 726 | #else
|
| 727 | pktInfo.majVer = reg.r_bx; // !!
|
| 728 | #endif
|
| 729 | pktInfo.funcs = reg.r_ax & 0xFF;
|
| 730 | pktInfo.type = reg.r_dx & 0xFF;
|
| 731 |
|
| 732 | #if (DOSX & PHARLAP)
|
| 733 | ReadRealMem (&pktInfo.name, DOS_ADDR(reg.ds,reg.esi), sizeof(pktInfo.name));
|
| 734 |
|
| 735 | #elif (DOSX & DJGPP)
|
| 736 | dosmemget (DOS_ADDR(reg.x.ds,reg.x.si), sizeof(pktInfo.name), &pktInfo.name);
|
| 737 |
|
| 738 | #elif (DOSX & DOS4GW)
|
| 739 | memcpy (&pktInfo.name, (void*)DOS_ADDR(reg.r_ds,reg.r_si), sizeof(pktInfo.name));
|
| 740 |
|
| 741 | #else
|
| 742 | _fmemcpy (&pktInfo.name, MK_FP(reg.r_ds,reg.r_si), sizeof(pktInfo.name));
|
| 743 | #endif
|
| 744 | return (TRUE);
|
| 745 | }
|
| 746 |
|
| 747 | /**************************************************************************/
|
| 748 |
|
| 749 | PUBLIC BOOL PktGetDriverParam (void)
|
| 750 | {
|
| 751 | reg.r_ax = 0x0A00;
|
| 752 |
|
| 753 | if (!PktInterrupt())
|
| 754 | return (FALSE);
|
| 755 |
|
| 756 | #if (DOSX & PHARLAP)
|
| 757 | ReadRealMem (&pktInfo.majVer, DOS_ADDR(reg.es,reg.edi), PKT_PARAM_SIZE);
|
| 758 |
|
| 759 | #elif (DOSX & DJGPP)
|
| 760 | dosmemget (DOS_ADDR(reg.x.es,reg.x.di), PKT_PARAM_SIZE, &pktInfo.majVer);
|
| 761 |
|
| 762 | #elif (DOSX & DOS4GW)
|
| 763 | memcpy (&pktInfo.majVer, (void*)DOS_ADDR(reg.r_es,reg.r_di), PKT_PARAM_SIZE);
|
| 764 |
|
| 765 | #else
|
| 766 | _fmemcpy (&pktInfo.majVer, MK_FP(reg.r_es,reg.r_di), PKT_PARAM_SIZE);
|
| 767 | #endif
|
| 768 | return (TRUE);
|
| 769 | }
|
| 770 |
|
| 771 | /**************************************************************************/
|
| 772 |
|
| 773 | #if (DOSX & PHARLAP)
|
| 774 | PUBLIC int PktReceive (BYTE *buf, int max)
|
| 775 | {
|
| 776 | WORD inOfs = *rxInOfsFp;
|
| 777 | WORD outOfs = *rxOutOfsFp;
|
| 778 |
|
| 779 | if (outOfs != inOfs)
|
| 780 | {
|
| 781 | RX_ELEMENT _far *head = (RX_ELEMENT _far*)(protBase+outOfs);
|
| 782 | int size, len = max;
|
| 783 |
|
| 784 | if (CheckElement(head))
|
| 785 | {
|
| 786 | size = min (head->firstCount, sizeof(RX_ELEMENT));
|
| 787 | len = min (size, max);
|
| 788 | _fmemcpy (buf, &head->destin, len);
|
| 789 | }
|
| 790 | else
|
| 791 | size = -1;
|
| 792 |
|
| 793 | outOfs += sizeof (RX_ELEMENT);
|
| 794 | if (outOfs > LAST_RX_BUF)
|
| 795 | outOfs = FIRST_RX_BUF;
|
| 796 | *rxOutOfsFp = outOfs;
|
| 797 | return (size);
|
| 798 | }
|
| 799 | return (0);
|
| 800 | }
|
| 801 |
|
| 802 | PUBLIC void PktQueueBusy (BOOL busy)
|
| 803 | {
|
| 804 | *rxOutOfsFp = busy ? (*rxInOfsFp + sizeof(RX_ELEMENT)) : *rxInOfsFp;
|
| 805 | if (*rxOutOfsFp > LAST_RX_BUF)
|
| 806 | *rxOutOfsFp = FIRST_RX_BUF;
|
| 807 | *(DWORD _far*)(protBase + (WORD)&pktDrop) = 0;
|
| 808 | }
|
| 809 |
|
| 810 | PUBLIC WORD PktBuffersUsed (void)
|
| 811 | {
|
| 812 | WORD inOfs = *rxInOfsFp;
|
| 813 | WORD outOfs = *rxOutOfsFp;
|
| 814 |
|
| 815 | if (inOfs >= outOfs)
|
| 816 | return (inOfs - outOfs) / sizeof(RX_ELEMENT);
|
| 817 | return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));
|
| 818 | }
|
| 819 |
|
| 820 | PUBLIC DWORD PktRxDropped (void)
|
| 821 | {
|
| 822 | return (*(DWORD _far*)(protBase + (WORD)&pktDrop));
|
| 823 | }
|
| 824 |
|
| 825 | #elif (DOSX & DJGPP)
|
| 826 | PUBLIC int PktReceive (BYTE *buf, int max)
|
| 827 | {
|
| 828 | WORD ofs = _farpeekw (_dos_ds, realBase+rxOutOfs);
|
| 829 |
|
| 830 | if (ofs != _farpeekw (_dos_ds, realBase+rxInOfs))
|
| 831 | {
|
| 832 | RX_ELEMENT head;
|
| 833 | int size, len = max;
|
| 834 |
|
| 835 | head.firstCount = _farpeekw (_dos_ds, realBase+ofs);
|
| 836 | head.secondCount = _farpeekw (_dos_ds, realBase+ofs+2);
|
| 837 | head.handle = _farpeekw (_dos_ds, realBase+ofs+4);
|
| 838 |
|
| 839 | if (CheckElement(&head))
|
| 840 | {
|
| 841 | size = min (head.firstCount, sizeof(RX_ELEMENT));
|
| 842 | len = min (size, max);
|
| 843 | dosmemget (realBase+ofs+6, len, buf);
|
| 844 | }
|
| 845 | else
|
| 846 | size = -1;
|
| 847 |
|
| 848 | ofs += sizeof (RX_ELEMENT);
|
| 849 | if (ofs > LAST_RX_BUF)
|
| 850 | _farpokew (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);
|
| 851 | else _farpokew (_dos_ds, realBase+rxOutOfs, ofs);
|
| 852 | return (size);
|
| 853 | }
|
| 854 | return (0);
|
| 855 | }
|
| 856 |
|
| 857 | PUBLIC void PktQueueBusy (BOOL busy)
|
| 858 | {
|
| 859 | WORD ofs;
|
| 860 |
|
| 861 | disable();
|
| 862 | ofs = _farpeekw (_dos_ds, realBase+rxInOfs);
|
| 863 | if (busy)
|
| 864 | ofs += sizeof (RX_ELEMENT);
|
| 865 |
|
| 866 | if (ofs > LAST_RX_BUF)
|
| 867 | _farpokew (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);
|
| 868 | else _farpokew (_dos_ds, realBase+rxOutOfs, ofs);
|
| 869 | _farpokel (_dos_ds, realBase+pktDrop, 0UL);
|
| 870 | enable();
|
| 871 | }
|
| 872 |
|
| 873 | PUBLIC WORD PktBuffersUsed (void)
|
| 874 | {
|
| 875 | WORD inOfs, outOfs;
|
| 876 |
|
| 877 | disable();
|
| 878 | inOfs = _farpeekw (_dos_ds, realBase+rxInOfs);
|
| 879 | outOfs = _farpeekw (_dos_ds, realBase+rxOutOfs);
|
| 880 | enable();
|
| 881 | if (inOfs >= outOfs)
|
| 882 | return (inOfs - outOfs) / sizeof(RX_ELEMENT);
|
| 883 | return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));
|
| 884 | }
|
| 885 |
|
| 886 | PUBLIC DWORD PktRxDropped (void)
|
| 887 | {
|
| 888 | return _farpeekl (_dos_ds, realBase+pktDrop);
|
| 889 | }
|
| 890 |
|
| 891 | #elif (DOSX & DOS4GW)
|
| 892 | PUBLIC int PktReceive (BYTE *buf, int max)
|
| 893 | {
|
| 894 | WORD ofs = *(WORD*) (realBase+rxOutOfs);
|
| 895 |
|
| 896 | if (ofs != *(WORD*) (realBase+rxInOfs))
|
| 897 | {
|
| 898 | RX_ELEMENT head;
|
| 899 | int size, len = max;
|
| 900 |
|
| 901 | head.firstCount = *(WORD*) (realBase+ofs);
|
| 902 | head.secondCount = *(WORD*) (realBase+ofs+2);
|
| 903 | head.handle = *(WORD*) (realBase+ofs+4);
|
| 904 |
|
| 905 | if (CheckElement(&head))
|
| 906 | {
|
| 907 | size = min (head.firstCount, sizeof(RX_ELEMENT));
|
| 908 | len = min (size, max);
|
| 909 | memcpy (buf, (const void*)(realBase+ofs+6), len);
|
| 910 | }
|
| 911 | else
|
| 912 | size = -1;
|
| 913 |
|
| 914 | ofs += sizeof (RX_ELEMENT);
|
| 915 | if (ofs > LAST_RX_BUF)
|
| 916 | *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;
|
| 917 | else *(WORD*) (realBase+rxOutOfs) = ofs;
|
| 918 | return (size);
|
| 919 | }
|
| 920 | return (0);
|
| 921 | }
|
| 922 |
|
| 923 | PUBLIC void PktQueueBusy (BOOL busy)
|
| 924 | {
|
| 925 | WORD ofs;
|
| 926 |
|
| 927 | _disable();
|
| 928 | ofs = *(WORD*) (realBase+rxInOfs);
|
| 929 | if (busy)
|
| 930 | ofs += sizeof (RX_ELEMENT);
|
| 931 |
|
| 932 | if (ofs > LAST_RX_BUF)
|
| 933 | *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;
|
| 934 | else *(WORD*) (realBase+rxOutOfs) = ofs;
|
| 935 | *(DWORD*) (realBase+pktDrop) = 0UL;
|
| 936 | _enable();
|
| 937 | }
|
| 938 |
|
| 939 | PUBLIC WORD PktBuffersUsed (void)
|
| 940 | {
|
| 941 | WORD inOfs, outOfs;
|
| 942 |
|
| 943 | _disable();
|
| 944 | inOfs = *(WORD*) (realBase+rxInOfs);
|
| 945 | outOfs = *(WORD*) (realBase+rxOutOfs);
|
| 946 | _enable();
|
| 947 | if (inOfs >= outOfs)
|
| 948 | return (inOfs - outOfs) / sizeof(RX_ELEMENT);
|
| 949 | return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));
|
| 950 | }
|
| 951 |
|
| 952 | PUBLIC DWORD PktRxDropped (void)
|
| 953 | {
|
| 954 | return *(DWORD*) (realBase+pktDrop);
|
| 955 | }
|
| 956 |
|
| 957 | #else /* real-mode small/large model */
|
| 958 |
|
| 959 | PUBLIC int PktReceive (BYTE *buf, int max)
|
| 960 | {
|
| 961 | if (rxOutOfs != rxInOfs)
|
| 962 | {
|
| 963 | RX_ELEMENT far *head = (RX_ELEMENT far*) MK_FP (_DS,rxOutOfs);
|
| 964 | int size, len = max;
|
| 965 |
|
| 966 | if (CheckElement(head))
|
| 967 | {
|
| 968 | size = min (head->firstCount, sizeof(RX_ELEMENT));
|
| 969 | len = min (size, max);
|
| 970 | _fmemcpy (buf, &head->destin, len);
|
| 971 | }
|
| 972 | else
|
| 973 | size = -1;
|
| 974 |
|
| 975 | rxOutOfs += sizeof (RX_ELEMENT);
|
| 976 | if (rxOutOfs > LAST_RX_BUF)
|
| 977 | rxOutOfs = FIRST_RX_BUF;
|
| 978 | return (size);
|
| 979 | }
|
| 980 | return (0);
|
| 981 | }
|
| 982 |
|
| 983 | PUBLIC void PktQueueBusy (BOOL busy)
|
| 984 | {
|
| 985 | rxOutOfs = busy ? (rxInOfs + sizeof(RX_ELEMENT)) : rxInOfs;
|
| 986 | if (rxOutOfs > LAST_RX_BUF)
|
| 987 | rxOutOfs = FIRST_RX_BUF;
|
| 988 | pktDrop = 0L;
|
| 989 | }
|
| 990 |
|
| 991 | PUBLIC WORD PktBuffersUsed (void)
|
| 992 | {
|
| 993 | WORD inOfs = rxInOfs;
|
| 994 | WORD outOfs = rxOutOfs;
|
| 995 |
|
| 996 | if (inOfs >= outOfs)
|
| 997 | return ((inOfs - outOfs) / sizeof(RX_ELEMENT));
|
| 998 | return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));
|
| 999 | }
|
| 1000 |
|
| 1001 | PUBLIC DWORD PktRxDropped (void)
|
| 1002 | {
|
| 1003 | return (pktDrop);
|
| 1004 | }
|
| 1005 | #endif
|
| 1006 |
|
| 1007 | /**************************************************************************/
|
| 1008 |
|
| 1009 | LOCAL __inline void PktFreeMem (void)
|
| 1010 | {
|
| 1011 | #if (DOSX & PHARLAP)
|
| 1012 | if (realSeg)
|
| 1013 | {
|
| 1014 | _dx_real_free (realSeg);
|
| 1015 | realSeg = 0;
|
| 1016 | }
|
| 1017 | #elif (DOSX & DJGPP)
|
| 1018 | if (rm_mem.rm_segment)
|
| 1019 | {
|
| 1020 | unsigned ofs; /* clear the DOS-mem to prevent further upcalls */
|
| 1021 |
|
| 1022 | for (ofs = 0; ofs < 16 * rm_mem.size / 4; ofs += 4)
|
| 1023 | _farpokel (_dos_ds, realBase + ofs, 0);
|
| 1024 | _go32_dpmi_free_dos_memory (&rm_mem);
|
| 1025 | rm_mem.rm_segment = 0;
|
| 1026 | }
|
| 1027 | #elif (DOSX & DOS4GW)
|
| 1028 | if (rm_base_sel)
|
| 1029 | {
|
| 1030 | dpmi_real_free (rm_base_sel);
|
| 1031 | rm_base_sel = 0;
|
| 1032 | }
|
| 1033 | #endif
|
| 1034 | }
|
| 1035 |
|
| 1036 | /**************************************************************************/
|
| 1037 |
|
| 1038 | PUBLIC BOOL PktExitDriver (void)
|
| 1039 | {
|
| 1040 | if (pktInfo.handle)
|
| 1041 | {
|
| 1042 | if (!PktSetReceiverMode(PDRX_BROADCAST))
|
| 1043 | PUTS ("Error restoring receiver mode.");
|
| 1044 |
|
| 1045 | if (!PktReleaseHandle(pktInfo.handle))
|
| 1046 | PUTS ("Error releasing PKT-DRVR handle.");
|
| 1047 |
|
| 1048 | PktFreeMem();
|
| 1049 | pktInfo.handle = 0;
|
| 1050 | }
|
| 1051 |
|
| 1052 | if (pcap_pkt_debug >= 1)
|
| 1053 | printf ("Internal stats: too-small %lu, too-large %lu, bad-sync %lu, "
|
| 1054 | "wrong-handle %lu\n",
|
| 1055 | intStat.tooSmall, intStat.tooLarge,
|
| 1056 | intStat.badSync, intStat.wrongHandle);
|
| 1057 | return (TRUE);
|
| 1058 | }
|
| 1059 |
|
| 1060 | #if (DOSX & (DJGPP|DOS4GW))
|
| 1061 | static void dump_pkt_stub (void)
|
| 1062 | {
|
| 1063 | int i;
|
| 1064 |
|
| 1065 | fprintf (stderr, "PktReceiver %lu, pkt_stub[PktReceiver] =\n",
|
| 1066 | PktReceiver);
|
| 1067 | for (i = 0; i < 15; i++)
|
| 1068 | fprintf (stderr, "%02X, ", real_stub_array[i+PktReceiver]);
|
| 1069 | fputs ("\n", stderr);
|
| 1070 | }
|
| 1071 | #endif
|
| 1072 |
|
| 1073 | /*
|
| 1074 | * Front end initialization routine
|
| 1075 | */
|
| 1076 | PUBLIC BOOL PktInitDriver (PKT_RX_MODE mode)
|
| 1077 | {
|
| 1078 | PKT_RX_MODE rxMode;
|
| 1079 | BOOL writeInfo = (pcap_pkt_debug >= 3);
|
| 1080 |
|
| 1081 | pktInfo.quiet = (pcap_pkt_debug < 3);
|
| 1082 |
|
| 1083 | #if (DOSX & PHARLAP) && defined(__HIGHC__)
|
| 1084 | if (_mwenv != 2)
|
| 1085 | {
|
| 1086 | fprintf (stderr, "Only Pharlap DOS extender supported.\n");
|
| 1087 | return (FALSE);
|
| 1088 | }
|
| 1089 | #endif
|
| 1090 |
|
| 1091 | #if (DOSX & PHARLAP) && defined(__WATCOMC__)
|
| 1092 | if (_Extender != 1)
|
| 1093 | {
|
| 1094 | fprintf (stderr, "Only DOS4GW style extenders supported.\n");
|
| 1095 | return (FALSE);
|
| 1096 | }
|
| 1097 | #endif
|
| 1098 |
|
| 1099 | if (!PktSearchDriver())
|
| 1100 | {
|
| 1101 | PUTS ("Packet driver not found.");
|
| 1102 | PktFreeMem();
|
| 1103 | return (FALSE);
|
| 1104 | }
|
| 1105 |
|
| 1106 | if (!PktGetDriverInfo())
|
| 1107 | {
|
| 1108 | PUTS ("Error getting pkt-drvr information.");
|
| 1109 | PktFreeMem();
|
| 1110 | return (FALSE);
|
| 1111 | }
|
| 1112 |
|
| 1113 | #if (DOSX & PHARLAP)
|
| 1114 | if (RealCopy((ULONG)&rxOutOfs, (ULONG)&pktRxEnd,
|
| 1115 | &realBase, &protBase, (USHORT*)&realSeg))
|
| 1116 | {
|
| 1117 | rxOutOfsFp = (WORD _far *) (protBase + (WORD) &rxOutOfs);
|
| 1118 | rxInOfsFp = (WORD _far *) (protBase + (WORD) &rxInOfs);
|
| 1119 | *rxOutOfsFp = FIRST_RX_BUF;
|
| 1120 | *rxInOfsFp = FIRST_RX_BUF;
|
| 1121 | }
|
| 1122 | else
|
| 1123 | {
|
| 1124 | PUTS ("Cannot allocate real-mode stub.");
|
| 1125 | return (FALSE);
|
| 1126 | }
|
| 1127 |
|
| 1128 | #elif (DOSX & (DJGPP|DOS4GW))
|
| 1129 | if (sizeof(real_stub_array) > 0xFFFF)
|
| 1130 | {
|
| 1131 | fprintf (stderr, "`real_stub_array[]' too big.\n");
|
| 1132 | return (FALSE);
|
| 1133 | }
|
| 1134 | #if (DOSX & DJGPP)
|
| 1135 | rm_mem.size = (sizeof(real_stub_array) + 15) / 16;
|
| 1136 |
|
| 1137 | if (_go32_dpmi_allocate_dos_memory(&rm_mem) || rm_mem.rm_offset != 0)
|
| 1138 | {
|
| 1139 | PUTS ("real-mode init failed.");
|
| 1140 | return (FALSE);
|
| 1141 | }
|
| 1142 | realBase = (rm_mem.rm_segment << 4);
|
| 1143 | dosmemput (&real_stub_array, sizeof(real_stub_array), realBase);
|
| 1144 | _farpokel (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);
|
| 1145 | _farpokel (_dos_ds, realBase+rxInOfs, FIRST_RX_BUF);
|
| 1146 |
|
| 1147 | #elif (DOSX & DOS4GW)
|
| 1148 | rm_base_seg = dpmi_real_malloc (sizeof(real_stub_array), &rm_base_sel);
|
| 1149 | if (!rm_base_seg)
|
| 1150 | {
|
| 1151 | PUTS ("real-mode init failed.");
|
| 1152 | return (FALSE);
|
| 1153 | }
|
| 1154 | realBase = (rm_base_seg << 4);
|
| 1155 | memcpy ((void*)realBase, &real_stub_array, sizeof(real_stub_array));
|
| 1156 | *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;
|
| 1157 | *(WORD*) (realBase+rxInOfs) = FIRST_RX_BUF;
|
| 1158 |
|
| 1159 | #endif
|
| 1160 | {
|
| 1161 | int pushf = PktReceiver;
|
| 1162 |
|
| 1163 | while (real_stub_array[pushf++] != 0x9C && /* pushf */
|
| 1164 | real_stub_array[pushf] != 0xFA) /* cli */
|
| 1165 | {
|
| 1166 | if (++para_skip > 16)
|
| 1167 | {
|
| 1168 | fprintf (stderr, "Something wrong with `pkt_stub.inc'.\n");
|
| 1169 | para_skip = 0;
|
| 1170 | dump_pkt_stub();
|
| 1171 | return (FALSE);
|
| 1172 | }
|
| 1173 | }
|
| 1174 | if (*(WORD*)(real_stub_array + offsetof(PktRealStub,_dummy)) != 0xB800)
|
| 1175 | {
|
| 1176 | fprintf (stderr, "`real_stub_array[]' is misaligned.\n");
|
| 1177 | return (FALSE);
|
| 1178 | }
|
| 1179 | }
|
| 1180 |
|
| 1181 | if (pcap_pkt_debug > 2)
|
| 1182 | dump_pkt_stub();
|
| 1183 |
|
| 1184 | #else
|
| 1185 | rxOutOfs = FIRST_RX_BUF;
|
| 1186 | rxInOfs = FIRST_RX_BUF;
|
| 1187 | #endif
|
| 1188 |
|
| 1189 | if (!PktSetAccess())
|
| 1190 | {
|
| 1191 | PUTS ("Error setting pkt-drvr access.");
|
| 1192 | PktFreeMem();
|
| 1193 | return (FALSE);
|
| 1194 | }
|
| 1195 |
|
| 1196 | if (!PktGetAddress(&myAddress))
|
| 1197 | {
|
| 1198 | PUTS ("Error fetching adapter address.");
|
| 1199 | PktFreeMem();
|
| 1200 | return (FALSE);
|
| 1201 | }
|
| 1202 |
|
| 1203 | if (!PktSetReceiverMode(mode))
|
| 1204 | {
|
| 1205 | PUTS ("Error setting receiver mode.");
|
| 1206 | PktFreeMem();
|
| 1207 | return (FALSE);
|
| 1208 | }
|
| 1209 |
|
| 1210 | if (!PktGetReceiverMode(&rxMode))
|
| 1211 | {
|
| 1212 | PUTS ("Error getting receiver mode.");
|
| 1213 | PktFreeMem();
|
| 1214 | return (FALSE);
|
| 1215 | }
|
| 1216 |
|
| 1217 | if (writeInfo)
|
| 1218 | printf ("Pkt-driver information:\n"
|
| 1219 | " Version : %d.%d\n"
|
| 1220 | " Name : %.15s\n"
|
| 1221 | " Class : %u (%s)\n"
|
| 1222 | " Type : %u\n"
|
| 1223 | " Number : %u\n"
|
| 1224 | " Funcs : %u\n"
|
| 1225 | " Intr : %Xh\n"
|
| 1226 | " Handle : %u\n"
|
| 1227 | " Extended : %s\n"
|
| 1228 | " Hi-perf : %s\n"
|
| 1229 | " RX mode : %s\n"
|
| 1230 | " Eth-addr : %02X:%02X:%02X:%02X:%02X:%02X\n",
|
| 1231 |
|
| 1232 | pktInfo.majVer, pktInfo.minVer, pktInfo.name,
|
| 1233 | pktInfo.class, PktGetClassName(pktInfo.class),
|
| 1234 | pktInfo.type, pktInfo.number,
|
| 1235 | pktInfo.funcs, pktInfo.intr, pktInfo.handle,
|
| 1236 | pktInfo.funcs == 2 || pktInfo.funcs == 6 ? "Yes" : "No",
|
| 1237 | pktInfo.funcs == 5 || pktInfo.funcs == 6 ? "Yes" : "No",
|
| 1238 | PktRXmodeStr(rxMode),
|
| 1239 | myAddress[0], myAddress[1], myAddress[2],
|
| 1240 | myAddress[3], myAddress[4], myAddress[5]);
|
| 1241 |
|
| 1242 | #if defined(DEBUG) && (DOSX & PHARLAP)
|
| 1243 | if (writeInfo)
|
| 1244 | {
|
| 1245 | DWORD rAdr = realBase + (WORD)&PktReceiver;
|
| 1246 | unsigned sel, ofs;
|
| 1247 |
|
| 1248 | printf ("\nReceiver at %04X:%04X\n", RP_SEG(rAdr), RP_OFF(rAdr));
|
| 1249 | printf ("Realbase = %04X:%04X\n", RP_SEG(realBase),RP_OFF(realBase));
|
| 1250 |
|
| 1251 | sel = _FP_SEG (protBase);
|
| 1252 | ofs = _FP_OFF (protBase);
|
| 1253 | printf ("Protbase = %04X:%08X\n", sel,ofs);
|
| 1254 | printf ("RealSeg = %04X\n", realSeg);
|
| 1255 |
|
| 1256 | sel = _FP_SEG (rxOutOfsFp);
|
| 1257 | ofs = _FP_OFF (rxOutOfsFp);
|
| 1258 | printf ("rxOutOfsFp = %04X:%08X\n", sel,ofs);
|
| 1259 |
|
| 1260 | sel = _FP_SEG (rxInOfsFp);
|
| 1261 | ofs = _FP_OFF (rxInOfsFp);
|
| 1262 | printf ("rxInOfsFp = %04X:%08X\n", sel,ofs);
|
| 1263 |
|
| 1264 | printf ("Ready: *rxOutOfsFp = %04X *rxInOfsFp = %04X\n",
|
| 1265 | *rxOutOfsFp, *rxInOfsFp);
|
| 1266 |
|
| 1267 | PktQueueBusy (TRUE);
|
| 1268 | printf ("Busy: *rxOutOfsFp = %04X *rxInOfsFp = %04X\n",
|
| 1269 | *rxOutOfsFp, *rxInOfsFp);
|
| 1270 | }
|
| 1271 | #endif
|
| 1272 |
|
| 1273 | memset (&pktStat, 0, sizeof(pktStat)); /* clear statistics */
|
| 1274 | PktQueueBusy (TRUE);
|
| 1275 | return (TRUE);
|
| 1276 | }
|
| 1277 |
|
| 1278 |
|
| 1279 | /*
|
| 1280 | * DPMI functions only for Watcom + DOS4GW extenders
|
| 1281 | */
|
| 1282 | #if (DOSX & DOS4GW)
|
| 1283 | LOCAL DWORD dpmi_get_real_vector (int intr)
|
| 1284 | {
|
| 1285 | union REGS r;
|
| 1286 |
|
| 1287 | r.x.eax = 0x200;
|
| 1288 | r.x.ebx = (DWORD) intr;
|
| 1289 | int386 (0x31, &r, &r);
|
| 1290 | return ((r.w.cx << 4) + r.w.dx);
|
| 1291 | }
|
| 1292 |
|
| 1293 | LOCAL WORD dpmi_real_malloc (int size, WORD *selector)
|
| 1294 | {
|
| 1295 | union REGS r;
|
| 1296 |
|
| 1297 | r.x.eax = 0x0100; /* DPMI allocate DOS memory */
|
| 1298 | r.x.ebx = (size + 15) / 16; /* Number of paragraphs requested */
|
| 1299 | int386 (0x31, &r, &r);
|
| 1300 | if (r.w.cflag & 1)
|
| 1301 | return (0);
|
| 1302 |
|
| 1303 | *selector = r.w.dx;
|
| 1304 | return (r.w.ax); /* Return segment address */
|
| 1305 | }
|
| 1306 |
|
| 1307 | LOCAL void dpmi_real_free (WORD selector)
|
| 1308 | {
|
| 1309 | union REGS r;
|
| 1310 |
|
| 1311 | r.x.eax = 0x101; /* DPMI free DOS memory */
|
| 1312 | r.x.ebx = selector; /* Selector to free */
|
| 1313 | int386 (0x31, &r, &r);
|
| 1314 | }
|
| 1315 | #endif
|
| 1316 |
|
| 1317 |
|
| 1318 | #if defined(DOSX) && (DOSX & PHARLAP)
|
| 1319 | /*
|
| 1320 | * Description:
|
| 1321 | * This routine allocates conventional memory for the specified block
|
| 1322 | * of code (which must be within the first 64K of the protected mode
|
| 1323 | * program segment) and copies the code to it.
|
| 1324 | *
|
| 1325 | * The caller should free up the conventional memory block when it
|
| 1326 | * is done with the conventional memory.
|
| 1327 | *
|
| 1328 | * NOTE THIS ROUTINE REQUIRES 386|DOS-EXTENDER 3.0 OR LATER.
|
| 1329 | *
|
| 1330 | * Calling arguments:
|
| 1331 | * start_offs start of real mode code in program segment
|
| 1332 | * end_offs 1 byte past end of real mode code in program segment
|
| 1333 | * real_basep returned; real mode ptr to use as a base for the
|
| 1334 | * real mode code (eg, to get the real mode FAR
|
| 1335 | * addr of a function foo(), take
|
| 1336 | * real_basep + (ULONG) foo).
|
| 1337 | * This pointer is constructed such that
|
| 1338 | * offsets within the real mode segment are
|
| 1339 | * the same as the link-time offsets in the
|
| 1340 | * protected mode program segment
|
| 1341 | * prot_basep returned; prot mode ptr to use as a base for getting
|
| 1342 | * to the conventional memory, also constructed
|
| 1343 | * so that adding the prot mode offset of a
|
| 1344 | * function or variable to the base gets you a
|
| 1345 | * ptr to the function or variable in the
|
| 1346 | * conventional memory block.
|
| 1347 | * rmem_adrp returned; real mode para addr of allocated
|
| 1348 | * conventional memory block, to be used to free
|
| 1349 | * up the conventional memory when done. DO NOT
|
| 1350 | * USE THIS TO CONSTRUCT A REAL MODE PTR, USE
|
| 1351 | * REAL_BASEP INSTEAD SO THAT OFFSETS WORK OUT
|
| 1352 | * CORRECTLY.
|
| 1353 | *
|
| 1354 | * Returned values:
|
| 1355 | * 0 if error
|
| 1356 | * 1 if success
|
| 1357 | */
|
| 1358 | int RealCopy (ULONG start_offs,
|
| 1359 | ULONG end_offs,
|
| 1360 | REALPTR *real_basep,
|
| 1361 | FARPTR *prot_basep,
|
| 1362 | USHORT *rmem_adrp)
|
| 1363 | {
|
| 1364 | ULONG rm_base; /* base real mode para addr for accessing */
|
| 1365 | /* allocated conventional memory */
|
| 1366 | UCHAR *source; /* source pointer for copy */
|
| 1367 | FARPTR destin; /* destination pointer for copy */
|
| 1368 | ULONG len; /* number of bytes to copy */
|
| 1369 | ULONG temp;
|
| 1370 | USHORT stemp;
|
| 1371 |
|
| 1372 | /* First check for valid inputs
|
| 1373 | */
|
| 1374 | if (start_offs >= end_offs || end_offs > 0x10000)
|
| 1375 | return (FALSE);
|
| 1376 |
|
| 1377 | /* Round start_offs down to a paragraph (16-byte) boundary so we can set up
|
| 1378 | * the real mode pointer easily. Round up end_offs to make sure we allocate
|
| 1379 | * enough paragraphs
|
| 1380 | */
|
| 1381 | start_offs &= ~15;
|
| 1382 | end_offs = (15 + (end_offs << 4)) >> 4;
|
| 1383 |
|
| 1384 | /* Allocate the conventional memory for our real mode code. Remember to
|
| 1385 | * round byte count UP to 16-byte paragraph size. We alloc it
|
| 1386 | * above the DOS data buffer so both the DOS data buffer and the appl
|
| 1387 | * conventional mem block can still be resized.
|
| 1388 | *
|
| 1389 | * First just try to alloc it; if we can't get it, shrink the appl mem
|
| 1390 | * block down to the minimum, try to alloc the memory again, then grow the
|
| 1391 | * appl mem block back to the maximum. (Don't try to shrink the DOS data
|
| 1392 | * buffer to free conventional memory; it wouldn't be good for this routine
|
| 1393 | * to have the possible side effect of making file I/O run slower.)
|
| 1394 | */
|
| 1395 | len = ((end_offs - start_offs) + 15) >> 4;
|
| 1396 | if (_dx_real_above(len, rmem_adrp, &stemp) != _DOSE_NONE)
|
| 1397 | {
|
| 1398 | if (_dx_cmem_usage(0, 0, &temp, &temp) != _DOSE_NONE)
|
| 1399 | return (FALSE);
|
| 1400 |
|
| 1401 | if (_dx_real_above(len, rmem_adrp, &stemp) != _DOSE_NONE)
|
| 1402 | *rmem_adrp = 0;
|
| 1403 |
|
| 1404 | if (_dx_cmem_usage(0, 1, &temp, &temp) != _DOSE_NONE)
|
| 1405 | {
|
| 1406 | if (*rmem_adrp != 0)
|
| 1407 | _dx_real_free (*rmem_adrp);
|
| 1408 | return (FALSE);
|
| 1409 | }
|
| 1410 |
|
| 1411 | if (*rmem_adrp == 0)
|
| 1412 | return (FALSE);
|
| 1413 | }
|
| 1414 |
|
| 1415 | /* Construct real mode & protected mode pointers to access the allocated
|
| 1416 | * memory. Note we know start_offs is aligned on a paragraph (16-byte)
|
| 1417 | * boundary, because we rounded it down.
|
| 1418 | *
|
| 1419 | * We make the offsets come out rights by backing off the real mode selector
|
| 1420 | * by start_offs.
|
| 1421 | */
|
| 1422 | rm_base = ((ULONG) *rmem_adrp) - (start_offs >> 4);
|
| 1423 | RP_SET (*real_basep, 0, rm_base);
|
| 1424 | FP_SET (*prot_basep, rm_base << 4, SS_DOSMEM);
|
| 1425 |
|
| 1426 | /* Copy the real mode code/data to the allocated memory
|
| 1427 | */
|
| 1428 | source = (UCHAR *) start_offs;
|
| 1429 | destin = *prot_basep;
|
| 1430 | FP_SET (destin, FP_OFF(*prot_basep) + start_offs, FP_SEL(*prot_basep));
|
| 1431 | len = end_offs - start_offs;
|
| 1432 | WriteFarMem (destin, source, len);
|
| 1433 |
|
| 1434 | return (TRUE);
|
| 1435 | }
|
| 1436 | #endif /* DOSX && (DOSX & PHARLAP) */
|