Updates to Tomato RAF including NGINX && PHP
[tomato.git] / release / src / router / libpcap / msdos / pktdrvr.c
blobcd22ee645900e6dbec6ae90c0ca5cd4021e741b3
1 /*
2 * File.........: pktdrvr.c
4 * Responsible..: Gisle Vanem, giva@bgnett.no
6 * Created......: 26.Sept 1995
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
14 * References...: PC/TCP Packet driver Specification. rev 1.09
15 * FTP Software Inc.
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <dos.h>
24 #include "pcap-dos.h"
25 #include "pcap-int.h"
26 #include "msdos/pktdrvr.h"
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
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)
42 #if defined(__HIGHC__)
43 extern UINT _mwenv;
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>
52 #elif defined(__WATCOMC__)
53 #include <i86.h>
54 #include <stddef.h>
55 extern char _Extender;
57 #else
58 extern void far PktReceiver (void);
59 #endif
62 #if (DOSX & (DJGPP|DOS4GW))
63 #include <sys/pack_on.h>
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;
79 /* Data located in a real-mode segment. This becomes far at runtime
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>
95 static BYTE real_stub_array [] = {
96 #include "pkt_stub.inc" /* generated opcode array */
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])
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 */
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 */
118 #define FIRST_RX_BUF (WORD) &pktRxBuf [0]
119 #define LAST_RX_BUF (WORD) &pktRxBuf [NUM_RX_BUF-1]
120 #endif
123 #ifdef __BORLANDC__ /* Use Borland's inline functions */
124 #define memcpy __memcpy__
125 #define memcmp __memcmp__
126 #define memset __memset__
127 #endif
130 #if (DOSX & PHARLAP)
131 extern void PktReceiver (void); /* in pkt_rx0.asm */
132 static int RealCopy (ULONG, ULONG, REALPTR*, FARPTR*, USHORT*);
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;
152 static WORD _far *rxOutOfsFp, *rxInOfsFp;
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;
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
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;
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))
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
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
200 PUBLIC PKT_STAT pktStat; /* statistics for packets */
201 PUBLIC PKT_INFO pktInfo; /* packet-driver information */
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 };
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;
214 /***************************************************************************/
216 PUBLIC const char *PktGetErrorStr (int errNum)
218 static const char *errStr[] = {
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"
241 if (errNum < 0 || errNum >= DIM(errStr))
242 return ("Unknown driver error.");
243 return (errStr [errNum]);
246 /**************************************************************************/
248 PUBLIC const char *PktGetClassName (WORD class)
250 switch (class)
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");
287 /**************************************************************************/
289 PUBLIC char const *PktRXmodeStr (PKT_RX_MODE mode)
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)"
300 if (mode > DIM(modeStr))
301 return ("??");
302 return (modeStr [mode-1]);
305 /**************************************************************************/
307 LOCAL __inline BOOL PktInterrupt (void)
309 BOOL okay;
311 #if (DOSX & PHARLAP)
312 _dx_real_int ((UINT)pktInfo.intr, &reg);
313 okay = ((reg.flags & 1) == 0); /* OK if carry clear */
315 #elif (DOSX & DJGPP)
316 __dpmi_int ((int)pktInfo.intr, &reg);
317 okay = ((reg.x.flags & 1) == 0);
319 #elif (DOSX & DOS4GW)
320 union REGS r;
321 struct SREGS s;
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 (&reg);
329 r.x.edi = FP_OFF (&reg);
330 reg.r_flags = 0;
331 reg.r_ss = reg.r_sp = 0; /* DPMI host provides stack */
333 int386x (0x31, &r, &r, &s);
334 okay = (!r.w.cflag);
336 #else
337 reg.r_flags = 0;
338 intr (pktInfo.intr, (struct REGPACK*)&reg);
339 okay = ((reg.r_flags & 1) == 0);
340 #endif
342 if (okay)
343 pktInfo.error = NULL;
344 else pktInfo.error = PktGetErrorStr (reg.r_dx >> 8);
345 return (okay);
348 /**************************************************************************/
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
355 PUBLIC BOOL PktSearchDriver (void)
357 BYTE intr = 0x20;
358 BOOL found = FALSE;
360 while (!found && intr < 0xFF)
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 */
366 #if (DOSX & PHARLAP)
367 _dx_rmiv_get (intr, &rp);
368 ReadRealMem (&str, (REALPTR)rp, sizeof(str));
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);
376 #elif (DOSX & DOS4GW)
377 rp = dpmi_get_real_vector (intr);
378 memcpy (&str, (void*)rp, sizeof(str));
380 #else
381 _fmemcpy (&str, getvect(intr), sizeof(str));
382 #endif
384 found = memcmp (&str[3],&pktStr,sizeof(pktStr)) == 0;
385 intr++;
387 pktInfo.intr = (found ? intr-1 : 0);
388 return (found);
392 /**************************************************************************/
394 static BOOL PktSetAccess (void)
396 reg.r_ax = 0x0200 + pktInfo.class;
397 reg.r_bx = 0xFFFF;
398 reg.r_dx = 0;
399 reg.r_cx = 0;
401 #if (DOSX & PHARLAP)
402 reg.ds = 0;
403 reg.esi = 0;
404 reg.es = RP_SEG (realBase);
405 reg.edi = (WORD) &PktReceiver;
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;
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;
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
426 if (!PktInterrupt())
427 return (FALSE);
429 pktInfo.handle = reg.r_ax;
430 return (TRUE);
433 /**************************************************************************/
435 PUBLIC BOOL PktReleaseHandle (WORD handle)
437 reg.r_ax = 0x0300;
438 reg.r_bx = handle;
439 return PktInterrupt();
442 /**************************************************************************/
444 PUBLIC BOOL PktTransmit (const void *eth, int len)
446 if (len > ETH_MTU)
447 return (FALSE);
449 reg.r_ax = 0x0400; /* Function 4, send pkt */
450 reg.r_cx = len; /* total size of frame */
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 */
457 #elif (DOSX & DOS4GW)
458 memcpy ((void*)(realBase+pktTxBuf), eth, len);
459 reg.r_ds = rm_base_seg;
460 reg.r_si = pktTxBuf;
462 #elif (DOSX & PHARLAP)
463 memcpy (&pktTxBuf, eth, len);
464 reg.r_ds = FP_SEG (&pktTxBuf);
465 reg.r_si = FP_OFF (&pktTxBuf);
467 #else
468 reg.r_ds = FP_SEG (eth);
469 reg.r_si = FP_OFF (eth);
470 #endif
472 return PktInterrupt();
475 /**************************************************************************/
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
483 WORD count_1, count_2;
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
489 if (rx->handle != pktInfo.handle)
491 pktInfo.error = "Wrong handle";
492 intStat.wrongHandle++;
493 PktReleaseHandle (rx->handle);
494 return (FALSE);
496 count_1 = rx->firstCount;
497 count_2 = rx->secondCount;
499 if (count_1 != count_2)
501 pktInfo.error = "Bad sync";
502 intStat.badSync++;
503 return (FALSE);
505 if (count_1 > ETH_MAX)
507 pktInfo.error = "Large esize";
508 intStat.tooLarge++;
509 return (FALSE);
511 #if 0
512 if (count_1 < ETH_MIN)
514 pktInfo.error = "Small esize";
515 intStat.tooSmall++;
516 return (FALSE);
518 #endif
519 return (TRUE);
522 /**************************************************************************/
524 PUBLIC BOOL PktTerminHandle (WORD handle)
526 reg.r_ax = 0x0500;
527 reg.r_bx = handle;
528 return PktInterrupt();
531 /**************************************************************************/
533 PUBLIC BOOL PktResetInterface (WORD handle)
535 reg.r_ax = 0x0700;
536 reg.r_bx = handle;
537 return PktInterrupt();
540 /**************************************************************************/
542 PUBLIC BOOL PktSetReceiverMode (PKT_RX_MODE mode)
544 if (pktInfo.class == PD_SLIP || pktInfo.class == PD_PPP)
545 return (TRUE);
547 reg.r_ax = 0x1400;
548 reg.r_bx = pktInfo.handle;
549 reg.r_cx = (WORD)mode;
551 if (!PktInterrupt())
552 return (FALSE);
554 receiveMode = mode;
555 return (TRUE);
558 /**************************************************************************/
560 PUBLIC BOOL PktGetReceiverMode (PKT_RX_MODE *mode)
562 reg.r_ax = 0x1500;
563 reg.r_bx = pktInfo.handle;
565 if (!PktInterrupt())
566 return (FALSE);
568 *mode = reg.r_ax;
569 return (TRUE);
572 /**************************************************************************/
574 static PKT_STAT initialStat; /* statistics at startup */
575 static BOOL resetStat = FALSE; /* statistics reset ? */
577 PUBLIC BOOL PktGetStatistics (WORD handle)
579 reg.r_ax = 0x1800;
580 reg.r_bx = handle;
582 if (!PktInterrupt())
583 return (FALSE);
585 #if (DOSX & PHARLAP)
586 ReadRealMem (&pktStat, DOS_ADDR(reg.ds,reg.esi), sizeof(pktStat));
588 #elif (DOSX & DJGPP)
589 dosmemget (DOS_ADDR(reg.x.ds,reg.x.si), sizeof(pktStat), &pktStat);
591 #elif (DOSX & DOS4GW)
592 memcpy (&pktStat, (void*)DOS_ADDR(reg.r_ds,reg.r_si), sizeof(pktStat));
594 #else
595 _fmemcpy (&pktStat, MK_FP(reg.r_ds,reg.r_si), sizeof(pktStat));
596 #endif
598 return (TRUE);
601 /**************************************************************************/
603 PUBLIC BOOL PktSessStatistics (WORD handle)
605 if (!PktGetStatistics(pktInfo.handle))
606 return (FALSE);
608 if (resetStat)
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;
619 return (TRUE);
622 /**************************************************************************/
624 PUBLIC BOOL PktResetStatistics (WORD handle)
626 if (!PktGetStatistics(pktInfo.handle))
627 return (FALSE);
629 memcpy (&initialStat, &pktStat, sizeof(initialStat));
630 resetStat = TRUE;
631 return (TRUE);
634 /**************************************************************************/
636 PUBLIC BOOL PktGetAddress (ETHER *addr)
638 reg.r_ax = 0x0600;
639 reg.r_bx = pktInfo.handle;
640 reg.r_cx = sizeof (*addr);
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
653 if (!PktInterrupt())
654 return (FALSE);
656 #if (DOSX & PHARLAP)
657 ReadRealMem (addr, realBase + (WORD)&pktTemp, sizeof(*addr));
659 #elif (DOSX & DJGPP)
660 dosmemget (realBase+pktTemp, sizeof(*addr), addr);
662 #elif (DOSX & DOS4GW)
663 memcpy (addr, (void*)(realBase+pktTemp), sizeof(*addr));
665 #else
666 memcpy ((void*)addr, &pktTemp, sizeof(*addr));
667 #endif
669 return (TRUE);
672 /**************************************************************************/
674 PUBLIC BOOL PktSetAddress (const ETHER *addr)
676 /* copy addr to real-mode scrath area */
678 #if (DOSX & PHARLAP)
679 WriteRealMem (realBase + (WORD)&pktTemp, (void*)addr, sizeof(*addr));
681 #elif (DOSX & DJGPP)
682 dosmemput (addr, sizeof(*addr), realBase+pktTemp);
684 #elif (DOSX & DOS4GW)
685 memcpy ((void*)(realBase+pktTemp), addr, sizeof(*addr));
687 #else
688 memcpy (&pktTemp, (void*)addr, sizeof(*addr));
689 #endif
691 reg.r_ax = 0x1900;
692 reg.r_cx = sizeof (*addr); /* address length */
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
705 return PktInterrupt();
708 /**************************************************************************/
710 PUBLIC BOOL PktGetDriverInfo (void)
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;
718 if (!PktInterrupt())
719 return (FALSE);
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;
732 #if (DOSX & PHARLAP)
733 ReadRealMem (&pktInfo.name, DOS_ADDR(reg.ds,reg.esi), sizeof(pktInfo.name));
735 #elif (DOSX & DJGPP)
736 dosmemget (DOS_ADDR(reg.x.ds,reg.x.si), sizeof(pktInfo.name), &pktInfo.name);
738 #elif (DOSX & DOS4GW)
739 memcpy (&pktInfo.name, (void*)DOS_ADDR(reg.r_ds,reg.r_si), sizeof(pktInfo.name));
741 #else
742 _fmemcpy (&pktInfo.name, MK_FP(reg.r_ds,reg.r_si), sizeof(pktInfo.name));
743 #endif
744 return (TRUE);
747 /**************************************************************************/
749 PUBLIC BOOL PktGetDriverParam (void)
751 reg.r_ax = 0x0A00;
753 if (!PktInterrupt())
754 return (FALSE);
756 #if (DOSX & PHARLAP)
757 ReadRealMem (&pktInfo.majVer, DOS_ADDR(reg.es,reg.edi), PKT_PARAM_SIZE);
759 #elif (DOSX & DJGPP)
760 dosmemget (DOS_ADDR(reg.x.es,reg.x.di), PKT_PARAM_SIZE, &pktInfo.majVer);
762 #elif (DOSX & DOS4GW)
763 memcpy (&pktInfo.majVer, (void*)DOS_ADDR(reg.r_es,reg.r_di), PKT_PARAM_SIZE);
765 #else
766 _fmemcpy (&pktInfo.majVer, MK_FP(reg.r_es,reg.r_di), PKT_PARAM_SIZE);
767 #endif
768 return (TRUE);
771 /**************************************************************************/
773 #if (DOSX & PHARLAP)
774 PUBLIC int PktReceive (BYTE *buf, int max)
776 WORD inOfs = *rxInOfsFp;
777 WORD outOfs = *rxOutOfsFp;
779 if (outOfs != inOfs)
781 RX_ELEMENT _far *head = (RX_ELEMENT _far*)(protBase+outOfs);
782 int size, len = max;
784 if (CheckElement(head))
786 size = min (head->firstCount, sizeof(RX_ELEMENT));
787 len = min (size, max);
788 _fmemcpy (buf, &head->destin, len);
790 else
791 size = -1;
793 outOfs += sizeof (RX_ELEMENT);
794 if (outOfs > LAST_RX_BUF)
795 outOfs = FIRST_RX_BUF;
796 *rxOutOfsFp = outOfs;
797 return (size);
799 return (0);
802 PUBLIC void PktQueueBusy (BOOL busy)
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;
810 PUBLIC WORD PktBuffersUsed (void)
812 WORD inOfs = *rxInOfsFp;
813 WORD outOfs = *rxOutOfsFp;
815 if (inOfs >= outOfs)
816 return (inOfs - outOfs) / sizeof(RX_ELEMENT);
817 return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));
820 PUBLIC DWORD PktRxDropped (void)
822 return (*(DWORD _far*)(protBase + (WORD)&pktDrop));
825 #elif (DOSX & DJGPP)
826 PUBLIC int PktReceive (BYTE *buf, int max)
828 WORD ofs = _farpeekw (_dos_ds, realBase+rxOutOfs);
830 if (ofs != _farpeekw (_dos_ds, realBase+rxInOfs))
832 RX_ELEMENT head;
833 int size, len = max;
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);
839 if (CheckElement(&head))
841 size = min (head.firstCount, sizeof(RX_ELEMENT));
842 len = min (size, max);
843 dosmemget (realBase+ofs+6, len, buf);
845 else
846 size = -1;
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);
854 return (0);
857 PUBLIC void PktQueueBusy (BOOL busy)
859 WORD ofs;
861 disable();
862 ofs = _farpeekw (_dos_ds, realBase+rxInOfs);
863 if (busy)
864 ofs += sizeof (RX_ELEMENT);
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();
873 PUBLIC WORD PktBuffersUsed (void)
875 WORD inOfs, outOfs;
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));
886 PUBLIC DWORD PktRxDropped (void)
888 return _farpeekl (_dos_ds, realBase+pktDrop);
891 #elif (DOSX & DOS4GW)
892 PUBLIC int PktReceive (BYTE *buf, int max)
894 WORD ofs = *(WORD*) (realBase+rxOutOfs);
896 if (ofs != *(WORD*) (realBase+rxInOfs))
898 RX_ELEMENT head;
899 int size, len = max;
901 head.firstCount = *(WORD*) (realBase+ofs);
902 head.secondCount = *(WORD*) (realBase+ofs+2);
903 head.handle = *(WORD*) (realBase+ofs+4);
905 if (CheckElement(&head))
907 size = min (head.firstCount, sizeof(RX_ELEMENT));
908 len = min (size, max);
909 memcpy (buf, (const void*)(realBase+ofs+6), len);
911 else
912 size = -1;
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);
920 return (0);
923 PUBLIC void PktQueueBusy (BOOL busy)
925 WORD ofs;
927 _disable();
928 ofs = *(WORD*) (realBase+rxInOfs);
929 if (busy)
930 ofs += sizeof (RX_ELEMENT);
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();
939 PUBLIC WORD PktBuffersUsed (void)
941 WORD inOfs, outOfs;
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));
952 PUBLIC DWORD PktRxDropped (void)
954 return *(DWORD*) (realBase+pktDrop);
957 #else /* real-mode small/large model */
959 PUBLIC int PktReceive (BYTE *buf, int max)
961 if (rxOutOfs != rxInOfs)
963 RX_ELEMENT far *head = (RX_ELEMENT far*) MK_FP (_DS,rxOutOfs);
964 int size, len = max;
966 if (CheckElement(head))
968 size = min (head->firstCount, sizeof(RX_ELEMENT));
969 len = min (size, max);
970 _fmemcpy (buf, &head->destin, len);
972 else
973 size = -1;
975 rxOutOfs += sizeof (RX_ELEMENT);
976 if (rxOutOfs > LAST_RX_BUF)
977 rxOutOfs = FIRST_RX_BUF;
978 return (size);
980 return (0);
983 PUBLIC void PktQueueBusy (BOOL busy)
985 rxOutOfs = busy ? (rxInOfs + sizeof(RX_ELEMENT)) : rxInOfs;
986 if (rxOutOfs > LAST_RX_BUF)
987 rxOutOfs = FIRST_RX_BUF;
988 pktDrop = 0L;
991 PUBLIC WORD PktBuffersUsed (void)
993 WORD inOfs = rxInOfs;
994 WORD outOfs = rxOutOfs;
996 if (inOfs >= outOfs)
997 return ((inOfs - outOfs) / sizeof(RX_ELEMENT));
998 return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));
1001 PUBLIC DWORD PktRxDropped (void)
1003 return (pktDrop);
1005 #endif
1007 /**************************************************************************/
1009 LOCAL __inline void PktFreeMem (void)
1011 #if (DOSX & PHARLAP)
1012 if (realSeg)
1014 _dx_real_free (realSeg);
1015 realSeg = 0;
1017 #elif (DOSX & DJGPP)
1018 if (rm_mem.rm_segment)
1020 unsigned ofs; /* clear the DOS-mem to prevent further upcalls */
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;
1027 #elif (DOSX & DOS4GW)
1028 if (rm_base_sel)
1030 dpmi_real_free (rm_base_sel);
1031 rm_base_sel = 0;
1033 #endif
1036 /**************************************************************************/
1038 PUBLIC BOOL PktExitDriver (void)
1040 if (pktInfo.handle)
1042 if (!PktSetReceiverMode(PDRX_BROADCAST))
1043 PUTS ("Error restoring receiver mode.");
1045 if (!PktReleaseHandle(pktInfo.handle))
1046 PUTS ("Error releasing PKT-DRVR handle.");
1048 PktFreeMem();
1049 pktInfo.handle = 0;
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);
1060 #if (DOSX & (DJGPP|DOS4GW))
1061 static void dump_pkt_stub (void)
1063 int i;
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);
1071 #endif
1074 * Front end initialization routine
1076 PUBLIC BOOL PktInitDriver (PKT_RX_MODE mode)
1078 PKT_RX_MODE rxMode;
1079 BOOL writeInfo = (pcap_pkt_debug >= 3);
1081 pktInfo.quiet = (pcap_pkt_debug < 3);
1083 #if (DOSX & PHARLAP) && defined(__HIGHC__)
1084 if (_mwenv != 2)
1086 fprintf (stderr, "Only Pharlap DOS extender supported.\n");
1087 return (FALSE);
1089 #endif
1091 #if (DOSX & PHARLAP) && defined(__WATCOMC__)
1092 if (_Extender != 1)
1094 fprintf (stderr, "Only DOS4GW style extenders supported.\n");
1095 return (FALSE);
1097 #endif
1099 if (!PktSearchDriver())
1101 PUTS ("Packet driver not found.");
1102 PktFreeMem();
1103 return (FALSE);
1106 if (!PktGetDriverInfo())
1108 PUTS ("Error getting pkt-drvr information.");
1109 PktFreeMem();
1110 return (FALSE);
1113 #if (DOSX & PHARLAP)
1114 if (RealCopy((ULONG)&rxOutOfs, (ULONG)&pktRxEnd,
1115 &realBase, &protBase, (USHORT*)&realSeg))
1117 rxOutOfsFp = (WORD _far *) (protBase + (WORD) &rxOutOfs);
1118 rxInOfsFp = (WORD _far *) (protBase + (WORD) &rxInOfs);
1119 *rxOutOfsFp = FIRST_RX_BUF;
1120 *rxInOfsFp = FIRST_RX_BUF;
1122 else
1124 PUTS ("Cannot allocate real-mode stub.");
1125 return (FALSE);
1128 #elif (DOSX & (DJGPP|DOS4GW))
1129 if (sizeof(real_stub_array) > 0xFFFF)
1131 fprintf (stderr, "`real_stub_array[]' too big.\n");
1132 return (FALSE);
1134 #if (DOSX & DJGPP)
1135 rm_mem.size = (sizeof(real_stub_array) + 15) / 16;
1137 if (_go32_dpmi_allocate_dos_memory(&rm_mem) || rm_mem.rm_offset != 0)
1139 PUTS ("real-mode init failed.");
1140 return (FALSE);
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);
1147 #elif (DOSX & DOS4GW)
1148 rm_base_seg = dpmi_real_malloc (sizeof(real_stub_array), &rm_base_sel);
1149 if (!rm_base_seg)
1151 PUTS ("real-mode init failed.");
1152 return (FALSE);
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;
1159 #endif
1161 int pushf = PktReceiver;
1163 while (real_stub_array[pushf++] != 0x9C && /* pushf */
1164 real_stub_array[pushf] != 0xFA) /* cli */
1166 if (++para_skip > 16)
1168 fprintf (stderr, "Something wrong with `pkt_stub.inc'.\n");
1169 para_skip = 0;
1170 dump_pkt_stub();
1171 return (FALSE);
1174 if (*(WORD*)(real_stub_array + offsetof(PktRealStub,_dummy)) != 0xB800)
1176 fprintf (stderr, "`real_stub_array[]' is misaligned.\n");
1177 return (FALSE);
1181 if (pcap_pkt_debug > 2)
1182 dump_pkt_stub();
1184 #else
1185 rxOutOfs = FIRST_RX_BUF;
1186 rxInOfs = FIRST_RX_BUF;
1187 #endif
1189 if (!PktSetAccess())
1191 PUTS ("Error setting pkt-drvr access.");
1192 PktFreeMem();
1193 return (FALSE);
1196 if (!PktGetAddress(&myAddress))
1198 PUTS ("Error fetching adapter address.");
1199 PktFreeMem();
1200 return (FALSE);
1203 if (!PktSetReceiverMode(mode))
1205 PUTS ("Error setting receiver mode.");
1206 PktFreeMem();
1207 return (FALSE);
1210 if (!PktGetReceiverMode(&rxMode))
1212 PUTS ("Error getting receiver mode.");
1213 PktFreeMem();
1214 return (FALSE);
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",
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]);
1242 #if defined(DEBUG) && (DOSX & PHARLAP)
1243 if (writeInfo)
1245 DWORD rAdr = realBase + (WORD)&PktReceiver;
1246 unsigned sel, ofs;
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));
1251 sel = _FP_SEG (protBase);
1252 ofs = _FP_OFF (protBase);
1253 printf ("Protbase = %04X:%08X\n", sel,ofs);
1254 printf ("RealSeg = %04X\n", realSeg);
1256 sel = _FP_SEG (rxOutOfsFp);
1257 ofs = _FP_OFF (rxOutOfsFp);
1258 printf ("rxOutOfsFp = %04X:%08X\n", sel,ofs);
1260 sel = _FP_SEG (rxInOfsFp);
1261 ofs = _FP_OFF (rxInOfsFp);
1262 printf ("rxInOfsFp = %04X:%08X\n", sel,ofs);
1264 printf ("Ready: *rxOutOfsFp = %04X *rxInOfsFp = %04X\n",
1265 *rxOutOfsFp, *rxInOfsFp);
1267 PktQueueBusy (TRUE);
1268 printf ("Busy: *rxOutOfsFp = %04X *rxInOfsFp = %04X\n",
1269 *rxOutOfsFp, *rxInOfsFp);
1271 #endif
1273 memset (&pktStat, 0, sizeof(pktStat)); /* clear statistics */
1274 PktQueueBusy (TRUE);
1275 return (TRUE);
1280 * DPMI functions only for Watcom + DOS4GW extenders
1282 #if (DOSX & DOS4GW)
1283 LOCAL DWORD dpmi_get_real_vector (int intr)
1285 union REGS r;
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);
1293 LOCAL WORD dpmi_real_malloc (int size, WORD *selector)
1295 union REGS r;
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);
1303 *selector = r.w.dx;
1304 return (r.w.ax); /* Return segment address */
1307 LOCAL void dpmi_real_free (WORD selector)
1309 union REGS r;
1311 r.x.eax = 0x101; /* DPMI free DOS memory */
1312 r.x.ebx = selector; /* Selector to free */
1313 int386 (0x31, &r, &r);
1315 #endif
1318 #if defined(DOSX) && (DOSX & PHARLAP)
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.
1325 * The caller should free up the conventional memory block when it
1326 * is done with the conventional memory.
1328 * NOTE THIS ROUTINE REQUIRES 386|DOS-EXTENDER 3.0 OR LATER.
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.
1354 * Returned values:
1355 * 0 if error
1356 * 1 if success
1358 int RealCopy (ULONG start_offs,
1359 ULONG end_offs,
1360 REALPTR *real_basep,
1361 FARPTR *prot_basep,
1362 USHORT *rmem_adrp)
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;
1372 /* First check for valid inputs
1374 if (start_offs >= end_offs || end_offs > 0x10000)
1375 return (FALSE);
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
1381 start_offs &= ~15;
1382 end_offs = (15 + (end_offs << 4)) >> 4;
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.
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.)
1395 len = ((end_offs - start_offs) + 15) >> 4;
1396 if (_dx_real_above(len, rmem_adrp, &stemp) != _DOSE_NONE)
1398 if (_dx_cmem_usage(0, 0, &temp, &temp) != _DOSE_NONE)
1399 return (FALSE);
1401 if (_dx_real_above(len, rmem_adrp, &stemp) != _DOSE_NONE)
1402 *rmem_adrp = 0;
1404 if (_dx_cmem_usage(0, 1, &temp, &temp) != _DOSE_NONE)
1406 if (*rmem_adrp != 0)
1407 _dx_real_free (*rmem_adrp);
1408 return (FALSE);
1411 if (*rmem_adrp == 0)
1412 return (FALSE);
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.
1419 * We make the offsets come out rights by backing off the real mode selector
1420 * by start_offs.
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);
1426 /* Copy the real mode code/data to the allocated memory
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);
1434 return (TRUE);
1436 #endif /* DOSX && (DOSX & PHARLAP) */