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
27 #include "msdos/pktdrvr.h"
30 #define NUM_RX_BUF 32 /* # of buffers in Rx FIFO queue */
35 #define DIM(x) (sizeof((x)) / sizeof(x[0]))
36 #define PUTS(s) do { \
39 printf ("%s: %s\n", s, pktInfo.error) : \
40 printf ("%s\n", pktInfo.error = s); \
43 #if defined(__HIGHC__)
46 #elif defined(__DJGPP__)
51 #include <sys/farptr.h>
53 #elif defined(__WATCOMC__)
56 extern char _Extender
;
59 extern void far
PktReceiver (void);
63 #if (DOSX & (DJGPP|DOS4GW))
64 #include <sys/packon.h>
76 WORD r_es
, r_ds
, r_fs
, r_gs
;
77 WORD r_ip
, r_cs
, r_sp
, r_ss
;
80 /* Data located in a real-mode segment. This becomes far at runtime
82 typedef struct { /* must match data/code in pkt_rx1.s */
87 TX_ELEMENT _pktTxBuf
[1];
88 RX_ELEMENT _pktRxBuf
[NUM_RX_BUF
];
89 WORD _dummy
[2]; /* screenSeg,newInOffset */
92 BYTE _PktReceiver
[15]; /* starts on a paragraph (16byte) */
94 #include <sys/packoff.h>
96 static BYTE real_stub_array
[] = {
97 #include "pkt_stub.inc" /* generated opcode array */
100 #define rxOutOfs offsetof (PktRealStub,_rxOutOfs)
101 #define rxInOfs offsetof (PktRealStub,_rxInOfs)
102 #define PktReceiver offsetof (PktRealStub,_PktReceiver [para_skip])
103 #define pktDrop offsetof (PktRealStub,_pktDrop)
104 #define pktTemp offsetof (PktRealStub,_pktTemp)
105 #define pktTxBuf offsetof (PktRealStub,_pktTxBuf)
106 #define FIRST_RX_BUF offsetof (PktRealStub,_pktRxBuf [0])
107 #define LAST_RX_BUF offsetof (PktRealStub,_pktRxBuf [NUM_RX_BUF-1])
110 extern WORD rxOutOfs
; /* offsets into pktRxBuf FIFO queue */
112 extern DWORD pktDrop
; /* # packets dropped in PktReceiver() */
113 extern BYTE pktRxEnd
; /* marks the end of r-mode code/data */
115 extern RX_ELEMENT pktRxBuf
[NUM_RX_BUF
]; /* PktDrvr Rx buffers */
116 extern TX_ELEMENT pktTxBuf
; /* PktDrvr Tx buffer */
117 extern char pktTemp
[20]; /* PktDrvr temp area */
119 #define FIRST_RX_BUF (WORD) &pktRxBuf [0]
120 #define LAST_RX_BUF (WORD) &pktRxBuf [NUM_RX_BUF-1]
124 #ifdef __BORLANDC__ /* Use Borland's inline functions */
125 #define memcpy __memcpy__
126 #define memcmp __memcmp__
127 #define memset __memset__
132 extern void PktReceiver (void); /* in pkt_rx0.asm */
133 static int RealCopy (ULONG
, ULONG
, REALPTR
*, FARPTR
*, USHORT
*);
137 #define FP_OFF(x) ((WORD)(x))
138 #define FP_SEG(x) ((WORD)(realBase >> 16))
139 #define DOS_ADDR(s,o) (((DWORD)(s) << 16) + (WORD)(o))
148 LOCAL FARPTR protBase
;
149 LOCAL REALPTR realBase
;
150 LOCAL WORD realSeg
; /* DOS para-address of allocated area */
153 static WORD _far
*rxOutOfsFp
, *rxInOfsFp
;
156 static _go32_dpmi_seginfo rm_mem
;
157 static __dpmi_regs reg
;
158 static DWORD realBase
;
159 static int para_skip
= 0;
161 #define DOS_ADDR(s,o) (((WORD)(s) << 4) + (o))
171 #elif (DOSX & DOS4GW)
172 LOCAL
struct DPMI_regs reg
;
173 LOCAL WORD rm_base_seg
, rm_base_sel
;
174 LOCAL DWORD realBase
;
175 LOCAL
int para_skip
= 0;
177 LOCAL DWORD
dpmi_get_real_vector (int intr
);
178 LOCAL WORD
dpmi_real_malloc (int size
, WORD
*selector
);
179 LOCAL
void dpmi_real_free (WORD selector
);
180 #define DOS_ADDR(s,o) (((DWORD)(s) << 4) + (WORD)(o))
182 #else /* real-mode Borland etc. */
184 WORD r_ax
, r_bx
, r_cx
, r_dx
, r_bp
;
185 WORD r_si
, r_di
, r_ds
, r_es
, r_flags
;
190 #pragma Alias (pktDrop, "_pktDrop")
191 #pragma Alias (pktRxBuf, "_pktRxBuf")
192 #pragma Alias (pktTxBuf, "_pktTxBuf")
193 #pragma Alias (pktTemp, "_pktTemp")
194 #pragma Alias (rxOutOfs, "_rxOutOfs")
195 #pragma Alias (rxInOfs, "_rxInOfs")
196 #pragma Alias (pktRxEnd, "_pktRxEnd")
197 #pragma Alias (PktReceiver,"_PktReceiver")
201 PUBLIC PKT_STAT pktStat
; /* statistics for packets */
202 PUBLIC PKT_INFO pktInfo
; /* packet-driver information */
204 PUBLIC PKT_RX_MODE receiveMode
= PDRX_DIRECT
;
205 PUBLIC ETHER myAddress
= { 0, 0, 0, 0, 0, 0 };
206 PUBLIC ETHER ethBroadcast
= { 255,255,255,255,255,255 };
208 LOCAL
struct { /* internal statistics */
209 DWORD tooSmall
; /* size < ETH_MIN */
210 DWORD tooLarge
; /* size > ETH_MAX */
211 DWORD badSync
; /* count_1 != count_2 */
212 DWORD wrongHandle
; /* upcall to wrong handle */
215 /***************************************************************************/
217 PUBLIC
const char *PktGetErrorStr (int errNum
)
219 static const char *errStr
[] = {
221 "Invalid handle number",
222 "No interfaces of specified class found",
223 "No interfaces of specified type found",
224 "No interfaces of specified number found",
225 "Bad packet type specified",
226 "Interface does not support multicast",
227 "Packet driver cannot terminate",
228 "Invalid receiver mode specified",
229 "Insufficient memory space",
230 "Type previously accessed, and not released",
231 "Command out of range, or not implemented",
232 "Cannot send packet (usually hardware error)",
233 "Cannot change hardware address ( > 1 handle open)",
234 "Hardware address has bad length or format",
235 "Cannot reset interface (more than 1 handle open)",
242 if (errNum
< 0 || errNum
>= DIM(errStr
))
243 return ("Unknown driver error.");
244 return (errStr
[errNum
]);
247 /**************************************************************************/
249 PUBLIC
const char *PktGetClassName (WORD
class)
254 return ("DIX-Ether");
256 return ("ProNET-10");
258 return ("IEEE 802.5");
262 return ("AppleTalk");
274 return ("IEEE 802.3 w/802.2 hdr");
276 return ("FDDI w/802.2 hdr");
288 /**************************************************************************/
290 PUBLIC
char const *PktRXmodeStr (PKT_RX_MODE mode
)
292 static const char *modeStr
[] = {
293 "Receiver turned off",
294 "Receive only directly addressed packets",
295 "Receive direct & broadcast packets",
296 "Receive direct,broadcast and limited multicast packets",
297 "Receive direct,broadcast and all multicast packets",
298 "Receive all packets (promiscuouos mode)"
301 if (mode
> DIM(modeStr
))
303 return (modeStr
[mode
-1]);
306 /**************************************************************************/
308 LOCAL __inline BOOL
PktInterrupt (void)
313 _dx_real_int ((UINT
)pktInfo
.intr
, ®
);
314 okay
= ((reg
.flags
& 1) == 0); /* OK if carry clear */
317 __dpmi_int ((int)pktInfo
.intr
, ®
);
318 okay
= ((reg
.x
.flags
& 1) == 0);
320 #elif (DOSX & DOS4GW)
324 memset (&r
, 0, sizeof(r
));
327 r
.x
.ebx
= pktInfo
.intr
;
329 s
.es
= FP_SEG (®
);
330 r
.x
.edi
= FP_OFF (®
);
332 reg
.r_ss
= reg
.r_sp
= 0; /* DPMI host provides stack */
334 int386x (0x31, &r
, &r
, &s
);
339 intr (pktInfo
.intr
, (struct REGPACK
*)®
);
340 okay
= ((reg
.r_flags
& 1) == 0);
344 pktInfo
.error
= NULL
;
345 else pktInfo
.error
= PktGetErrorStr (reg
.r_dx
>> 8);
349 /**************************************************************************/
352 * Search for packet driver at interrupt 60h through 80h. If ASCIIZ
353 * string "PKT DRVR" found at offset 3 in the interrupt handler, return
354 * interrupt number, else return zero in pktInfo.intr
356 PUBLIC BOOL
PktSearchDriver (void)
361 while (!found
&& intr
< 0xFF)
363 static char str
[12]; /* 3 + strlen("PKT DRVR") */
364 static char pktStr
[9] = "PKT DRVR"; /* ASCIIZ string at ofs 3 */
365 DWORD rp
; /* in interrupt routine */
368 _dx_rmiv_get (intr
, &rp
);
369 ReadRealMem (&str
, (REALPTR
)rp
, sizeof(str
));
372 __dpmi_raddr realAdr
;
373 __dpmi_get_real_mode_interrupt_vector (intr
, &realAdr
);
374 rp
= (realAdr
.segment
<< 4) + realAdr
.offset16
;
375 dosmemget (rp
, sizeof(str
), &str
);
377 #elif (DOSX & DOS4GW)
378 rp
= dpmi_get_real_vector (intr
);
379 memcpy (&str
, (void*)rp
, sizeof(str
));
382 _fmemcpy (&str
, getvect(intr
), sizeof(str
));
385 found
= memcmp (&str
[3],&pktStr
,sizeof(pktStr
)) == 0;
388 pktInfo
.intr
= (found
? intr
-1 : 0);
393 /**************************************************************************/
395 static BOOL
PktSetAccess (void)
397 reg
.r_ax
= 0x0200 + pktInfo
.class;
405 reg
.es
= RP_SEG (realBase
);
406 reg
.edi
= (WORD
) &PktReceiver
;
411 reg
.x
.es
= rm_mem
.rm_segment
;
412 reg
.x
.di
= PktReceiver
;
414 #elif (DOSX & DOS4GW)
417 reg
.r_es
= rm_base_seg
;
418 reg
.r_di
= PktReceiver
;
423 reg
.r_es
= FP_SEG (&PktReceiver
);
424 reg
.r_di
= FP_OFF (&PktReceiver
);
430 pktInfo
.handle
= reg
.r_ax
;
434 /**************************************************************************/
436 PUBLIC BOOL
PktReleaseHandle (WORD handle
)
440 return PktInterrupt();
443 /**************************************************************************/
445 PUBLIC BOOL
PktTransmit (const void *eth
, int len
)
450 reg
.r_ax
= 0x0400; /* Function 4, send pkt */
451 reg
.r_cx
= len
; /* total size of frame */
454 dosmemput (eth
, len
, realBase
+pktTxBuf
);
455 reg
.x
.ds
= rm_mem
.rm_segment
; /* DOS data segment and */
456 reg
.x
.si
= pktTxBuf
; /* DOS offset to buffer */
458 #elif (DOSX & DOS4GW)
459 memcpy ((void*)(realBase
+pktTxBuf
), eth
, len
);
460 reg
.r_ds
= rm_base_seg
;
463 #elif (DOSX & PHARLAP)
464 memcpy (&pktTxBuf
, eth
, len
);
465 reg
.r_ds
= FP_SEG (&pktTxBuf
);
466 reg
.r_si
= FP_OFF (&pktTxBuf
);
469 reg
.r_ds
= FP_SEG (eth
);
470 reg
.r_si
= FP_OFF (eth
);
473 return PktInterrupt();
476 /**************************************************************************/
478 #if (DOSX & (DJGPP|DOS4GW))
479 LOCAL __inline BOOL
CheckElement (RX_ELEMENT
*rx
)
481 LOCAL __inline BOOL
CheckElement (RX_ELEMENT _far
*rx
)
484 WORD count_1
, count_2
;
487 * We got an upcall to the same RMCB with wrong handle.
488 * This can happen if we failed to release handle at program exit
490 if (rx
->handle
!= pktInfo
.handle
)
492 pktInfo
.error
= "Wrong handle";
493 intStat
.wrongHandle
++;
494 PktReleaseHandle (rx
->handle
);
497 count_1
= rx
->firstCount
;
498 count_2
= rx
->secondCount
;
500 if (count_1
!= count_2
)
502 pktInfo
.error
= "Bad sync";
506 if (count_1
> ETH_MAX
)
508 pktInfo
.error
= "Large esize";
513 if (count_1
< ETH_MIN
)
515 pktInfo
.error
= "Small esize";
523 /**************************************************************************/
525 PUBLIC BOOL
PktTerminHandle (WORD handle
)
529 return PktInterrupt();
532 /**************************************************************************/
534 PUBLIC BOOL
PktResetInterface (WORD handle
)
538 return PktInterrupt();
541 /**************************************************************************/
543 PUBLIC BOOL
PktSetReceiverMode (PKT_RX_MODE mode
)
545 if (pktInfo
.class == PD_SLIP
|| pktInfo
.class == PD_PPP
)
549 reg
.r_bx
= pktInfo
.handle
;
550 reg
.r_cx
= (WORD
)mode
;
559 /**************************************************************************/
561 PUBLIC BOOL
PktGetReceiverMode (PKT_RX_MODE
*mode
)
564 reg
.r_bx
= pktInfo
.handle
;
573 /**************************************************************************/
575 static PKT_STAT initialStat
; /* statistics at startup */
576 static BOOL resetStat
= FALSE
; /* statistics reset ? */
578 PUBLIC BOOL
PktGetStatistics (WORD handle
)
587 ReadRealMem (&pktStat
, DOS_ADDR(reg
.ds
,reg
.esi
), sizeof(pktStat
));
590 dosmemget (DOS_ADDR(reg
.x
.ds
,reg
.x
.si
), sizeof(pktStat
), &pktStat
);
592 #elif (DOSX & DOS4GW)
593 memcpy (&pktStat
, (void*)DOS_ADDR(reg
.r_ds
,reg
.r_si
), sizeof(pktStat
));
596 _fmemcpy (&pktStat
, MK_FP(reg
.r_ds
,reg
.r_si
), sizeof(pktStat
));
602 /**************************************************************************/
604 PUBLIC BOOL
PktSessStatistics (WORD handle
)
606 if (!PktGetStatistics(pktInfo
.handle
))
611 pktStat
.inPackets
-= initialStat
.inPackets
;
612 pktStat
.outPackets
-= initialStat
.outPackets
;
613 pktStat
.inBytes
-= initialStat
.inBytes
;
614 pktStat
.outBytes
-= initialStat
.outBytes
;
615 pktStat
.inErrors
-= initialStat
.inErrors
;
616 pktStat
.outErrors
-= initialStat
.outErrors
;
617 pktStat
.outErrors
-= initialStat
.outErrors
;
618 pktStat
.lost
-= initialStat
.lost
;
623 /**************************************************************************/
625 PUBLIC BOOL
PktResetStatistics (WORD handle
)
627 if (!PktGetStatistics(pktInfo
.handle
))
630 memcpy (&initialStat
, &pktStat
, sizeof(initialStat
));
635 /**************************************************************************/
637 PUBLIC BOOL
PktGetAddress (ETHER
*addr
)
640 reg
.r_bx
= pktInfo
.handle
;
641 reg
.r_cx
= sizeof (*addr
);
644 reg
.x
.es
= rm_mem
.rm_segment
;
646 #elif (DOSX & DOS4GW)
647 reg
.r_es
= rm_base_seg
;
650 reg
.r_es
= FP_SEG (&pktTemp
);
651 reg
.r_di
= FP_OFF (&pktTemp
); /* ES:DI = address for result */
658 ReadRealMem (addr
, realBase
+ (WORD
)&pktTemp
, sizeof(*addr
));
661 dosmemget (realBase
+pktTemp
, sizeof(*addr
), addr
);
663 #elif (DOSX & DOS4GW)
664 memcpy (addr
, (void*)(realBase
+pktTemp
), sizeof(*addr
));
667 memcpy ((void*)addr
, &pktTemp
, sizeof(*addr
));
673 /**************************************************************************/
675 PUBLIC BOOL
PktSetAddress (const ETHER
*addr
)
677 /* copy addr to real-mode scrath area */
680 WriteRealMem (realBase
+ (WORD
)&pktTemp
, (void*)addr
, sizeof(*addr
));
683 dosmemput (addr
, sizeof(*addr
), realBase
+pktTemp
);
685 #elif (DOSX & DOS4GW)
686 memcpy ((void*)(realBase
+pktTemp
), addr
, sizeof(*addr
));
689 memcpy (&pktTemp
, (void*)addr
, sizeof(*addr
));
693 reg
.r_cx
= sizeof (*addr
); /* address length */
696 reg
.x
.es
= rm_mem
.rm_segment
; /* DOS offset to param */
697 reg
.x
.di
= pktTemp
; /* DOS segment to param */
698 #elif (DOSX & DOS4GW)
699 reg
.r_es
= rm_base_seg
;
702 reg
.r_es
= FP_SEG (&pktTemp
);
703 reg
.r_di
= FP_OFF (&pktTemp
);
706 return PktInterrupt();
709 /**************************************************************************/
711 PUBLIC BOOL
PktGetDriverInfo (void)
715 memset (&pktInfo
.name
, 0, sizeof(pktInfo
.name
));
722 pktInfo
.number
= reg
.r_cx
& 0xFF;
723 pktInfo
.class = reg
.r_cx
>> 8;
725 pktInfo
.minVer
= reg
.r_bx
% 10;
726 pktInfo
.majVer
= reg
.r_bx
/ 10;
728 pktInfo
.majVer
= reg
.r_bx
; // !!
730 pktInfo
.funcs
= reg
.r_ax
& 0xFF;
731 pktInfo
.type
= reg
.r_dx
& 0xFF;
734 ReadRealMem (&pktInfo
.name
, DOS_ADDR(reg
.ds
,reg
.esi
), sizeof(pktInfo
.name
));
737 dosmemget (DOS_ADDR(reg
.x
.ds
,reg
.x
.si
), sizeof(pktInfo
.name
), &pktInfo
.name
);
739 #elif (DOSX & DOS4GW)
740 memcpy (&pktInfo
.name
, (void*)DOS_ADDR(reg
.r_ds
,reg
.r_si
), sizeof(pktInfo
.name
));
743 _fmemcpy (&pktInfo
.name
, MK_FP(reg
.r_ds
,reg
.r_si
), sizeof(pktInfo
.name
));
748 /**************************************************************************/
750 PUBLIC BOOL
PktGetDriverParam (void)
758 ReadRealMem (&pktInfo
.majVer
, DOS_ADDR(reg
.es
,reg
.edi
), PKT_PARAM_SIZE
);
761 dosmemget (DOS_ADDR(reg
.x
.es
,reg
.x
.di
), PKT_PARAM_SIZE
, &pktInfo
.majVer
);
763 #elif (DOSX & DOS4GW)
764 memcpy (&pktInfo
.majVer
, (void*)DOS_ADDR(reg
.r_es
,reg
.r_di
), PKT_PARAM_SIZE
);
767 _fmemcpy (&pktInfo
.majVer
, MK_FP(reg
.r_es
,reg
.r_di
), PKT_PARAM_SIZE
);
772 /**************************************************************************/
775 PUBLIC
int PktReceive (BYTE
*buf
, int max
)
777 WORD inOfs
= *rxInOfsFp
;
778 WORD outOfs
= *rxOutOfsFp
;
782 RX_ELEMENT _far
*head
= (RX_ELEMENT _far
*)(protBase
+outOfs
);
785 if (CheckElement(head
))
787 size
= min (head
->firstCount
, sizeof(RX_ELEMENT
));
788 len
= min (size
, max
);
789 _fmemcpy (buf
, &head
->destin
, len
);
794 outOfs
+= sizeof (RX_ELEMENT
);
795 if (outOfs
> LAST_RX_BUF
)
796 outOfs
= FIRST_RX_BUF
;
797 *rxOutOfsFp
= outOfs
;
803 PUBLIC
void PktQueueBusy (BOOL busy
)
805 *rxOutOfsFp
= busy
? (*rxInOfsFp
+ sizeof(RX_ELEMENT
)) : *rxInOfsFp
;
806 if (*rxOutOfsFp
> LAST_RX_BUF
)
807 *rxOutOfsFp
= FIRST_RX_BUF
;
808 *(DWORD _far
*)(protBase
+ (WORD
)&pktDrop
) = 0;
811 PUBLIC WORD
PktBuffersUsed (void)
813 WORD inOfs
= *rxInOfsFp
;
814 WORD outOfs
= *rxOutOfsFp
;
817 return (inOfs
- outOfs
) / sizeof(RX_ELEMENT
);
818 return (NUM_RX_BUF
- (outOfs
- inOfs
) / sizeof(RX_ELEMENT
));
821 PUBLIC DWORD
PktRxDropped (void)
823 return (*(DWORD _far
*)(protBase
+ (WORD
)&pktDrop
));
827 PUBLIC
int PktReceive (BYTE
*buf
, int max
)
829 WORD ofs
= _farpeekw (_dos_ds
, realBase
+rxOutOfs
);
831 if (ofs
!= _farpeekw (_dos_ds
, realBase
+rxInOfs
))
836 head
.firstCount
= _farpeekw (_dos_ds
, realBase
+ofs
);
837 head
.secondCount
= _farpeekw (_dos_ds
, realBase
+ofs
+2);
838 head
.handle
= _farpeekw (_dos_ds
, realBase
+ofs
+4);
840 if (CheckElement(&head
))
842 size
= min (head
.firstCount
, sizeof(RX_ELEMENT
));
843 len
= min (size
, max
);
844 dosmemget (realBase
+ofs
+6, len
, buf
);
849 ofs
+= sizeof (RX_ELEMENT
);
850 if (ofs
> LAST_RX_BUF
)
851 _farpokew (_dos_ds
, realBase
+rxOutOfs
, FIRST_RX_BUF
);
852 else _farpokew (_dos_ds
, realBase
+rxOutOfs
, ofs
);
858 PUBLIC
void PktQueueBusy (BOOL busy
)
863 ofs
= _farpeekw (_dos_ds
, realBase
+rxInOfs
);
865 ofs
+= sizeof (RX_ELEMENT
);
867 if (ofs
> LAST_RX_BUF
)
868 _farpokew (_dos_ds
, realBase
+rxOutOfs
, FIRST_RX_BUF
);
869 else _farpokew (_dos_ds
, realBase
+rxOutOfs
, ofs
);
870 _farpokel (_dos_ds
, realBase
+pktDrop
, 0UL);
874 PUBLIC WORD
PktBuffersUsed (void)
879 inOfs
= _farpeekw (_dos_ds
, realBase
+rxInOfs
);
880 outOfs
= _farpeekw (_dos_ds
, realBase
+rxOutOfs
);
883 return (inOfs
- outOfs
) / sizeof(RX_ELEMENT
);
884 return (NUM_RX_BUF
- (outOfs
- inOfs
) / sizeof(RX_ELEMENT
));
887 PUBLIC DWORD
PktRxDropped (void)
889 return _farpeekl (_dos_ds
, realBase
+pktDrop
);
892 #elif (DOSX & DOS4GW)
893 PUBLIC
int PktReceive (BYTE
*buf
, int max
)
895 WORD ofs
= *(WORD
*) (realBase
+rxOutOfs
);
897 if (ofs
!= *(WORD
*) (realBase
+rxInOfs
))
902 head
.firstCount
= *(WORD
*) (realBase
+ofs
);
903 head
.secondCount
= *(WORD
*) (realBase
+ofs
+2);
904 head
.handle
= *(WORD
*) (realBase
+ofs
+4);
906 if (CheckElement(&head
))
908 size
= min (head
.firstCount
, sizeof(RX_ELEMENT
));
909 len
= min (size
, max
);
910 memcpy (buf
, (const void*)(realBase
+ofs
+6), len
);
915 ofs
+= sizeof (RX_ELEMENT
);
916 if (ofs
> LAST_RX_BUF
)
917 *(WORD
*) (realBase
+rxOutOfs
) = FIRST_RX_BUF
;
918 else *(WORD
*) (realBase
+rxOutOfs
) = ofs
;
924 PUBLIC
void PktQueueBusy (BOOL busy
)
929 ofs
= *(WORD
*) (realBase
+rxInOfs
);
931 ofs
+= sizeof (RX_ELEMENT
);
933 if (ofs
> LAST_RX_BUF
)
934 *(WORD
*) (realBase
+rxOutOfs
) = FIRST_RX_BUF
;
935 else *(WORD
*) (realBase
+rxOutOfs
) = ofs
;
936 *(DWORD
*) (realBase
+pktDrop
) = 0UL;
940 PUBLIC WORD
PktBuffersUsed (void)
945 inOfs
= *(WORD
*) (realBase
+rxInOfs
);
946 outOfs
= *(WORD
*) (realBase
+rxOutOfs
);
949 return (inOfs
- outOfs
) / sizeof(RX_ELEMENT
);
950 return (NUM_RX_BUF
- (outOfs
- inOfs
) / sizeof(RX_ELEMENT
));
953 PUBLIC DWORD
PktRxDropped (void)
955 return *(DWORD
*) (realBase
+pktDrop
);
958 #else /* real-mode small/large model */
960 PUBLIC
int PktReceive (BYTE
*buf
, int max
)
962 if (rxOutOfs
!= rxInOfs
)
964 RX_ELEMENT far
*head
= (RX_ELEMENT far
*) MK_FP (_DS
,rxOutOfs
);
967 if (CheckElement(head
))
969 size
= min (head
->firstCount
, sizeof(RX_ELEMENT
));
970 len
= min (size
, max
);
971 _fmemcpy (buf
, &head
->destin
, len
);
976 rxOutOfs
+= sizeof (RX_ELEMENT
);
977 if (rxOutOfs
> LAST_RX_BUF
)
978 rxOutOfs
= FIRST_RX_BUF
;
984 PUBLIC
void PktQueueBusy (BOOL busy
)
986 rxOutOfs
= busy
? (rxInOfs
+ sizeof(RX_ELEMENT
)) : rxInOfs
;
987 if (rxOutOfs
> LAST_RX_BUF
)
988 rxOutOfs
= FIRST_RX_BUF
;
992 PUBLIC WORD
PktBuffersUsed (void)
994 WORD inOfs
= rxInOfs
;
995 WORD outOfs
= rxOutOfs
;
998 return ((inOfs
- outOfs
) / sizeof(RX_ELEMENT
));
999 return (NUM_RX_BUF
- (outOfs
- inOfs
) / sizeof(RX_ELEMENT
));
1002 PUBLIC DWORD
PktRxDropped (void)
1008 /**************************************************************************/
1010 LOCAL __inline
void PktFreeMem (void)
1012 #if (DOSX & PHARLAP)
1015 _dx_real_free (realSeg
);
1018 #elif (DOSX & DJGPP)
1019 if (rm_mem
.rm_segment
)
1021 unsigned ofs
; /* clear the DOS-mem to prevent further upcalls */
1023 for (ofs
= 0; ofs
< 16 * rm_mem
.size
/ 4; ofs
+= 4)
1024 _farpokel (_dos_ds
, realBase
+ ofs
, 0);
1025 _go32_dpmi_free_dos_memory (&rm_mem
);
1026 rm_mem
.rm_segment
= 0;
1028 #elif (DOSX & DOS4GW)
1031 dpmi_real_free (rm_base_sel
);
1037 /**************************************************************************/
1039 PUBLIC BOOL
PktExitDriver (void)
1043 if (!PktSetReceiverMode(PDRX_BROADCAST
))
1044 PUTS ("Error restoring receiver mode.");
1046 if (!PktReleaseHandle(pktInfo
.handle
))
1047 PUTS ("Error releasing PKT-DRVR handle.");
1053 if (pcap_pkt_debug
>= 1)
1054 printf ("Internal stats: too-small %lu, too-large %lu, bad-sync %lu, "
1055 "wrong-handle %lu\n",
1056 intStat
.tooSmall
, intStat
.tooLarge
,
1057 intStat
.badSync
, intStat
.wrongHandle
);
1061 #if (DOSX & (DJGPP|DOS4GW))
1062 static void dump_pkt_stub (void)
1066 fprintf (stderr
, "PktReceiver %lu, pkt_stub[PktReceiver] =\n",
1068 for (i
= 0; i
< 15; i
++)
1069 fprintf (stderr
, "%02X, ", real_stub_array
[i
+PktReceiver
]);
1070 fputs ("\n", stderr
);
1075 * Front end initialization routine
1077 PUBLIC BOOL
PktInitDriver (PKT_RX_MODE mode
)
1080 BOOL writeInfo
= (pcap_pkt_debug
>= 3);
1082 pktInfo
.quiet
= (pcap_pkt_debug
< 3);
1084 #if (DOSX & PHARLAP) && defined(__HIGHC__)
1087 fprintf (stderr
, "Only Pharlap DOS extender supported.\n");
1092 #if (DOSX & PHARLAP) && defined(__WATCOMC__)
1095 fprintf (stderr
, "Only DOS4GW style extenders supported.\n");
1100 if (!PktSearchDriver())
1102 PUTS ("Packet driver not found.");
1107 if (!PktGetDriverInfo())
1109 PUTS ("Error getting pkt-drvr information.");
1114 #if (DOSX & PHARLAP)
1115 if (RealCopy((ULONG
)&rxOutOfs
, (ULONG
)&pktRxEnd
,
1116 &realBase
, &protBase
, (USHORT
*)&realSeg
))
1118 rxOutOfsFp
= (WORD _far
*) (protBase
+ (WORD
) &rxOutOfs
);
1119 rxInOfsFp
= (WORD _far
*) (protBase
+ (WORD
) &rxInOfs
);
1120 *rxOutOfsFp
= FIRST_RX_BUF
;
1121 *rxInOfsFp
= FIRST_RX_BUF
;
1125 PUTS ("Cannot allocate real-mode stub.");
1129 #elif (DOSX & (DJGPP|DOS4GW))
1130 if (sizeof(real_stub_array
) > 0xFFFF)
1132 fprintf (stderr
, "`real_stub_array[]' too big.\n");
1136 rm_mem
.size
= (sizeof(real_stub_array
) + 15) / 16;
1138 if (_go32_dpmi_allocate_dos_memory(&rm_mem
) || rm_mem
.rm_offset
!= 0)
1140 PUTS ("real-mode init failed.");
1143 realBase
= (rm_mem
.rm_segment
<< 4);
1144 dosmemput (&real_stub_array
, sizeof(real_stub_array
), realBase
);
1145 _farpokel (_dos_ds
, realBase
+rxOutOfs
, FIRST_RX_BUF
);
1146 _farpokel (_dos_ds
, realBase
+rxInOfs
, FIRST_RX_BUF
);
1148 #elif (DOSX & DOS4GW)
1149 rm_base_seg
= dpmi_real_malloc (sizeof(real_stub_array
), &rm_base_sel
);
1152 PUTS ("real-mode init failed.");
1155 realBase
= (rm_base_seg
<< 4);
1156 memcpy ((void*)realBase
, &real_stub_array
, sizeof(real_stub_array
));
1157 *(WORD
*) (realBase
+rxOutOfs
) = FIRST_RX_BUF
;
1158 *(WORD
*) (realBase
+rxInOfs
) = FIRST_RX_BUF
;
1162 int pushf
= PktReceiver
;
1164 while (real_stub_array
[pushf
++] != 0x9C && /* pushf */
1165 real_stub_array
[pushf
] != 0xFA) /* cli */
1167 if (++para_skip
> 16)
1169 fprintf (stderr
, "Something wrong with `pkt_stub.inc'.\n");
1175 if (*(WORD
*)(real_stub_array
+ offsetof(PktRealStub
,_dummy
)) != 0xB800)
1177 fprintf (stderr
, "`real_stub_array[]' is misaligned.\n");
1182 if (pcap_pkt_debug
> 2)
1186 rxOutOfs
= FIRST_RX_BUF
;
1187 rxInOfs
= FIRST_RX_BUF
;
1190 if (!PktSetAccess())
1192 PUTS ("Error setting pkt-drvr access.");
1197 if (!PktGetAddress(&myAddress
))
1199 PUTS ("Error fetching adapter address.");
1204 if (!PktSetReceiverMode(mode
))
1206 PUTS ("Error setting receiver mode.");
1211 if (!PktGetReceiverMode(&rxMode
))
1213 PUTS ("Error getting receiver mode.");
1219 printf ("Pkt-driver information:\n"
1220 " Version : %d.%d\n"
1222 " Class : %u (%s)\n"
1231 " Eth-addr : %02X:%02X:%02X:%02X:%02X:%02X\n",
1233 pktInfo
.majVer
, pktInfo
.minVer
, pktInfo
.name
,
1234 pktInfo
.class, PktGetClassName(pktInfo
.class),
1235 pktInfo
.type
, pktInfo
.number
,
1236 pktInfo
.funcs
, pktInfo
.intr
, pktInfo
.handle
,
1237 pktInfo
.funcs
== 2 || pktInfo
.funcs
== 6 ? "Yes" : "No",
1238 pktInfo
.funcs
== 5 || pktInfo
.funcs
== 6 ? "Yes" : "No",
1239 PktRXmodeStr(rxMode
),
1240 myAddress
[0], myAddress
[1], myAddress
[2],
1241 myAddress
[3], myAddress
[4], myAddress
[5]);
1243 #if defined(DEBUG) && (DOSX & PHARLAP)
1246 DWORD rAdr
= realBase
+ (WORD
)&PktReceiver
;
1249 printf ("\nReceiver at %04X:%04X\n", RP_SEG(rAdr
), RP_OFF(rAdr
));
1250 printf ("Realbase = %04X:%04X\n", RP_SEG(realBase
),RP_OFF(realBase
));
1252 sel
= _FP_SEG (protBase
);
1253 ofs
= _FP_OFF (protBase
);
1254 printf ("Protbase = %04X:%08X\n", sel
,ofs
);
1255 printf ("RealSeg = %04X\n", realSeg
);
1257 sel
= _FP_SEG (rxOutOfsFp
);
1258 ofs
= _FP_OFF (rxOutOfsFp
);
1259 printf ("rxOutOfsFp = %04X:%08X\n", sel
,ofs
);
1261 sel
= _FP_SEG (rxInOfsFp
);
1262 ofs
= _FP_OFF (rxInOfsFp
);
1263 printf ("rxInOfsFp = %04X:%08X\n", sel
,ofs
);
1265 printf ("Ready: *rxOutOfsFp = %04X *rxInOfsFp = %04X\n",
1266 *rxOutOfsFp
, *rxInOfsFp
);
1268 PktQueueBusy (TRUE
);
1269 printf ("Busy: *rxOutOfsFp = %04X *rxInOfsFp = %04X\n",
1270 *rxOutOfsFp
, *rxInOfsFp
);
1274 memset (&pktStat
, 0, sizeof(pktStat
)); /* clear statistics */
1275 PktQueueBusy (TRUE
);
1281 * DPMI functions only for Watcom + DOS4GW extenders
1284 LOCAL DWORD
dpmi_get_real_vector (int intr
)
1289 r
.x
.ebx
= (DWORD
) intr
;
1290 int386 (0x31, &r
, &r
);
1291 return ((r
.w
.cx
<< 4) + r
.w
.dx
);
1294 LOCAL WORD
dpmi_real_malloc (int size
, WORD
*selector
)
1298 r
.x
.eax
= 0x0100; /* DPMI allocate DOS memory */
1299 r
.x
.ebx
= (size
+ 15) / 16; /* Number of paragraphs requested */
1300 int386 (0x31, &r
, &r
);
1305 return (r
.w
.ax
); /* Return segment address */
1308 LOCAL
void dpmi_real_free (WORD selector
)
1312 r
.x
.eax
= 0x101; /* DPMI free DOS memory */
1313 r
.x
.ebx
= selector
; /* Selector to free */
1314 int386 (0x31, &r
, &r
);
1319 #if defined(DOSX) && (DOSX & PHARLAP)
1322 * This routine allocates conventional memory for the specified block
1323 * of code (which must be within the first 64K of the protected mode
1324 * program segment) and copies the code to it.
1326 * The caller should free up the conventional memory block when it
1327 * is done with the conventional memory.
1329 * NOTE THIS ROUTINE REQUIRES 386|DOS-EXTENDER 3.0 OR LATER.
1331 * Calling arguments:
1332 * start_offs start of real mode code in program segment
1333 * end_offs 1 byte past end of real mode code in program segment
1334 * real_basep returned; real mode ptr to use as a base for the
1335 * real mode code (eg, to get the real mode FAR
1336 * addr of a function foo(), take
1337 * real_basep + (ULONG) foo).
1338 * This pointer is constructed such that
1339 * offsets within the real mode segment are
1340 * the same as the link-time offsets in the
1341 * protected mode program segment
1342 * prot_basep returned; prot mode ptr to use as a base for getting
1343 * to the conventional memory, also constructed
1344 * so that adding the prot mode offset of a
1345 * function or variable to the base gets you a
1346 * ptr to the function or variable in the
1347 * conventional memory block.
1348 * rmem_adrp returned; real mode para addr of allocated
1349 * conventional memory block, to be used to free
1350 * up the conventional memory when done. DO NOT
1351 * USE THIS TO CONSTRUCT A REAL MODE PTR, USE
1352 * REAL_BASEP INSTEAD SO THAT OFFSETS WORK OUT
1359 int RealCopy (ULONG start_offs
,
1361 REALPTR
*real_basep
,
1365 ULONG rm_base
; /* base real mode para addr for accessing */
1366 /* allocated conventional memory */
1367 UCHAR
*source
; /* source pointer for copy */
1368 FARPTR destin
; /* destination pointer for copy */
1369 ULONG len
; /* number of bytes to copy */
1373 /* First check for valid inputs
1375 if (start_offs
>= end_offs
|| end_offs
> 0x10000)
1378 /* Round start_offs down to a paragraph (16-byte) boundary so we can set up
1379 * the real mode pointer easily. Round up end_offs to make sure we allocate
1383 end_offs
= (15 + (end_offs
<< 4)) >> 4;
1385 /* Allocate the conventional memory for our real mode code. Remember to
1386 * round byte count UP to 16-byte paragraph size. We alloc it
1387 * above the DOS data buffer so both the DOS data buffer and the appl
1388 * conventional mem block can still be resized.
1390 * First just try to alloc it; if we can't get it, shrink the appl mem
1391 * block down to the minimum, try to alloc the memory again, then grow the
1392 * appl mem block back to the maximum. (Don't try to shrink the DOS data
1393 * buffer to free conventional memory; it wouldn't be good for this routine
1394 * to have the possible side effect of making file I/O run slower.)
1396 len
= ((end_offs
- start_offs
) + 15) >> 4;
1397 if (_dx_real_above(len
, rmem_adrp
, &stemp
) != _DOSE_NONE
)
1399 if (_dx_cmem_usage(0, 0, &temp
, &temp
) != _DOSE_NONE
)
1402 if (_dx_real_above(len
, rmem_adrp
, &stemp
) != _DOSE_NONE
)
1405 if (_dx_cmem_usage(0, 1, &temp
, &temp
) != _DOSE_NONE
)
1407 if (*rmem_adrp
!= 0)
1408 _dx_real_free (*rmem_adrp
);
1412 if (*rmem_adrp
== 0)
1416 /* Construct real mode & protected mode pointers to access the allocated
1417 * memory. Note we know start_offs is aligned on a paragraph (16-byte)
1418 * boundary, because we rounded it down.
1420 * We make the offsets come out rights by backing off the real mode selector
1423 rm_base
= ((ULONG
) *rmem_adrp
) - (start_offs
>> 4);
1424 RP_SET (*real_basep
, 0, rm_base
);
1425 FP_SET (*prot_basep
, rm_base
<< 4, SS_DOSMEM
);
1427 /* Copy the real mode code/data to the allocated memory
1429 source
= (UCHAR
*) start_offs
;
1430 destin
= *prot_basep
;
1431 FP_SET (destin
, FP_OFF(*prot_basep
) + start_offs
, FP_SEL(*prot_basep
));
1432 len
= end_offs
- start_offs
;
1433 WriteFarMem (destin
, source
, len
);
1437 #endif /* DOSX && (DOSX & PHARLAP) */