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
26 #include "msdos/pktdrvr.h"
29 #define NUM_RX_BUF 32 /* # of buffers in Rx FIFO queue */
34 #define DIM(x) (sizeof((x)) / sizeof(x[0]))
35 #define PUTS(s) do { \
38 printf ("%s: %s\n", s, pktInfo.error) : \
39 printf ("%s\n", pktInfo.error = s); \
42 #if defined(__HIGHC__)
45 #elif defined(__DJGPP__)
50 #include <sys/farptr.h>
52 #elif defined(__WATCOMC__)
55 extern char _Extender
;
58 extern void far
PktReceiver (void);
62 #if (DOSX & (DJGPP|DOS4GW))
63 #include <sys/pack_on.h>
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 */
86 TX_ELEMENT _pktTxBuf
[1];
87 RX_ELEMENT _pktRxBuf
[NUM_RX_BUF
];
88 WORD _dummy
[2]; /* screenSeg,newInOffset */
91 BYTE _PktReceiver
[15]; /* starts on a paragraph (16byte) */
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])
109 extern WORD rxOutOfs
; /* offsets into pktRxBuf FIFO queue */
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]
123 #ifdef __BORLANDC__ /* Use Borland's inline functions */
124 #define memcpy __memcpy__
125 #define memcmp __memcmp__
126 #define memset __memset__
131 extern void PktReceiver (void); /* in pkt_rx0.asm */
132 static int RealCopy (ULONG
, ULONG
, REALPTR
*, FARPTR
*, USHORT
*);
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))
147 LOCAL FARPTR protBase
;
148 LOCAL REALPTR realBase
;
149 LOCAL WORD realSeg
; /* DOS para-address of allocated area */
152 static WORD _far
*rxOutOfsFp
, *rxInOfsFp
;
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))
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. */
183 WORD r_ax
, r_bx
, r_cx
, r_dx
, r_bp
;
184 WORD r_si
, r_di
, r_ds
, r_es
, r_flags
;
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")
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 */
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)",
241 if (errNum
< 0 || errNum
>= DIM(errStr
))
242 return ("Unknown driver error.");
243 return (errStr
[errNum
]);
246 /**************************************************************************/
248 PUBLIC
const char *PktGetClassName (WORD
class)
253 return ("DIX-Ether");
255 return ("ProNET-10");
257 return ("IEEE 802.5");
261 return ("AppleTalk");
273 return ("IEEE 802.3 w/802.2 hdr");
275 return ("FDDI w/802.2 hdr");
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
))
302 return (modeStr
[mode
-1]);
305 /**************************************************************************/
307 LOCAL __inline BOOL
PktInterrupt (void)
312 _dx_real_int ((UINT
)pktInfo
.intr
, ®
);
313 okay
= ((reg
.flags
& 1) == 0); /* OK if carry clear */
316 __dpmi_int ((int)pktInfo
.intr
, ®
);
317 okay
= ((reg
.x
.flags
& 1) == 0);
319 #elif (DOSX & DOS4GW)
323 memset (&r
, 0, sizeof(r
));
326 r
.x
.ebx
= pktInfo
.intr
;
328 s
.es
= FP_SEG (®
);
329 r
.x
.edi
= FP_OFF (®
);
331 reg
.r_ss
= reg
.r_sp
= 0; /* DPMI host provides stack */
333 int386x (0x31, &r
, &r
, &s
);
338 intr (pktInfo
.intr
, (struct REGPACK
*)®
);
339 okay
= ((reg
.r_flags
& 1) == 0);
343 pktInfo
.error
= NULL
;
344 else pktInfo
.error
= PktGetErrorStr (reg
.r_dx
>> 8);
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)
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 */
367 _dx_rmiv_get (intr
, &rp
);
368 ReadRealMem (&str
, (REALPTR
)rp
, sizeof(str
));
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
));
381 _fmemcpy (&str
, getvect(intr
), sizeof(str
));
384 found
= memcmp (&str
[3],&pktStr
,sizeof(pktStr
)) == 0;
387 pktInfo
.intr
= (found
? intr
-1 : 0);
392 /**************************************************************************/
394 static BOOL
PktSetAccess (void)
396 reg
.r_ax
= 0x0200 + pktInfo
.class;
404 reg
.es
= RP_SEG (realBase
);
405 reg
.edi
= (WORD
) &PktReceiver
;
410 reg
.x
.es
= rm_mem
.rm_segment
;
411 reg
.x
.di
= PktReceiver
;
413 #elif (DOSX & DOS4GW)
416 reg
.r_es
= rm_base_seg
;
417 reg
.r_di
= PktReceiver
;
422 reg
.r_es
= FP_SEG (&PktReceiver
);
423 reg
.r_di
= FP_OFF (&PktReceiver
);
429 pktInfo
.handle
= reg
.r_ax
;
433 /**************************************************************************/
435 PUBLIC BOOL
PktReleaseHandle (WORD handle
)
439 return PktInterrupt();
442 /**************************************************************************/
444 PUBLIC BOOL
PktTransmit (const void *eth
, int len
)
449 reg
.r_ax
= 0x0400; /* Function 4, send pkt */
450 reg
.r_cx
= len
; /* total size of frame */
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
;
462 #elif (DOSX & PHARLAP)
463 memcpy (&pktTxBuf
, eth
, len
);
464 reg
.r_ds
= FP_SEG (&pktTxBuf
);
465 reg
.r_si
= FP_OFF (&pktTxBuf
);
468 reg
.r_ds
= FP_SEG (eth
);
469 reg
.r_si
= FP_OFF (eth
);
472 return PktInterrupt();
475 /**************************************************************************/
477 #if (DOSX & (DJGPP|DOS4GW))
478 LOCAL __inline BOOL
CheckElement (RX_ELEMENT
*rx
)
480 LOCAL __inline BOOL
CheckElement (RX_ELEMENT _far
*rx
)
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
);
496 count_1
= rx
->firstCount
;
497 count_2
= rx
->secondCount
;
499 if (count_1
!= count_2
)
501 pktInfo
.error
= "Bad sync";
505 if (count_1
> ETH_MAX
)
507 pktInfo
.error
= "Large esize";
512 if (count_1
< ETH_MIN
)
514 pktInfo
.error
= "Small esize";
522 /**************************************************************************/
524 PUBLIC BOOL
PktTerminHandle (WORD handle
)
528 return PktInterrupt();
531 /**************************************************************************/
533 PUBLIC BOOL
PktResetInterface (WORD handle
)
537 return PktInterrupt();
540 /**************************************************************************/
542 PUBLIC BOOL
PktSetReceiverMode (PKT_RX_MODE mode
)
544 if (pktInfo
.class == PD_SLIP
|| pktInfo
.class == PD_PPP
)
548 reg
.r_bx
= pktInfo
.handle
;
549 reg
.r_cx
= (WORD
)mode
;
558 /**************************************************************************/
560 PUBLIC BOOL
PktGetReceiverMode (PKT_RX_MODE
*mode
)
563 reg
.r_bx
= pktInfo
.handle
;
572 /**************************************************************************/
574 static PKT_STAT initialStat
; /* statistics at startup */
575 static BOOL resetStat
= FALSE
; /* statistics reset ? */
577 PUBLIC BOOL
PktGetStatistics (WORD handle
)
586 ReadRealMem (&pktStat
, DOS_ADDR(reg
.ds
,reg
.esi
), sizeof(pktStat
));
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
));
595 _fmemcpy (&pktStat
, MK_FP(reg
.r_ds
,reg
.r_si
), sizeof(pktStat
));
601 /**************************************************************************/
603 PUBLIC BOOL
PktSessStatistics (WORD handle
)
605 if (!PktGetStatistics(pktInfo
.handle
))
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
;
622 /**************************************************************************/
624 PUBLIC BOOL
PktResetStatistics (WORD handle
)
626 if (!PktGetStatistics(pktInfo
.handle
))
629 memcpy (&initialStat
, &pktStat
, sizeof(initialStat
));
634 /**************************************************************************/
636 PUBLIC BOOL
PktGetAddress (ETHER
*addr
)
639 reg
.r_bx
= pktInfo
.handle
;
640 reg
.r_cx
= sizeof (*addr
);
643 reg
.x
.es
= rm_mem
.rm_segment
;
645 #elif (DOSX & DOS4GW)
646 reg
.r_es
= rm_base_seg
;
649 reg
.r_es
= FP_SEG (&pktTemp
);
650 reg
.r_di
= FP_OFF (&pktTemp
); /* ES:DI = address for result */
657 ReadRealMem (addr
, realBase
+ (WORD
)&pktTemp
, sizeof(*addr
));
660 dosmemget (realBase
+pktTemp
, sizeof(*addr
), addr
);
662 #elif (DOSX & DOS4GW)
663 memcpy (addr
, (void*)(realBase
+pktTemp
), sizeof(*addr
));
666 memcpy ((void*)addr
, &pktTemp
, sizeof(*addr
));
672 /**************************************************************************/
674 PUBLIC BOOL
PktSetAddress (const ETHER
*addr
)
676 /* copy addr to real-mode scrath area */
679 WriteRealMem (realBase
+ (WORD
)&pktTemp
, (void*)addr
, sizeof(*addr
));
682 dosmemput (addr
, sizeof(*addr
), realBase
+pktTemp
);
684 #elif (DOSX & DOS4GW)
685 memcpy ((void*)(realBase
+pktTemp
), addr
, sizeof(*addr
));
688 memcpy (&pktTemp
, (void*)addr
, sizeof(*addr
));
692 reg
.r_cx
= sizeof (*addr
); /* address length */
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
;
701 reg
.r_es
= FP_SEG (&pktTemp
);
702 reg
.r_di
= FP_OFF (&pktTemp
);
705 return PktInterrupt();
708 /**************************************************************************/
710 PUBLIC BOOL
PktGetDriverInfo (void)
714 memset (&pktInfo
.name
, 0, sizeof(pktInfo
.name
));
721 pktInfo
.number
= reg
.r_cx
& 0xFF;
722 pktInfo
.class = reg
.r_cx
>> 8;
724 pktInfo
.minVer
= reg
.r_bx
% 10;
725 pktInfo
.majVer
= reg
.r_bx
/ 10;
727 pktInfo
.majVer
= reg
.r_bx
; // !!
729 pktInfo
.funcs
= reg
.r_ax
& 0xFF;
730 pktInfo
.type
= reg
.r_dx
& 0xFF;
733 ReadRealMem (&pktInfo
.name
, DOS_ADDR(reg
.ds
,reg
.esi
), sizeof(pktInfo
.name
));
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
));
742 _fmemcpy (&pktInfo
.name
, MK_FP(reg
.r_ds
,reg
.r_si
), sizeof(pktInfo
.name
));
747 /**************************************************************************/
749 PUBLIC BOOL
PktGetDriverParam (void)
757 ReadRealMem (&pktInfo
.majVer
, DOS_ADDR(reg
.es
,reg
.edi
), PKT_PARAM_SIZE
);
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
);
766 _fmemcpy (&pktInfo
.majVer
, MK_FP(reg
.r_es
,reg
.r_di
), PKT_PARAM_SIZE
);
771 /**************************************************************************/
774 PUBLIC
int PktReceive (BYTE
*buf
, int max
)
776 WORD inOfs
= *rxInOfsFp
;
777 WORD outOfs
= *rxOutOfsFp
;
781 RX_ELEMENT _far
*head
= (RX_ELEMENT _far
*)(protBase
+outOfs
);
784 if (CheckElement(head
))
786 size
= min (head
->firstCount
, sizeof(RX_ELEMENT
));
787 len
= min (size
, max
);
788 _fmemcpy (buf
, &head
->destin
, len
);
793 outOfs
+= sizeof (RX_ELEMENT
);
794 if (outOfs
> LAST_RX_BUF
)
795 outOfs
= FIRST_RX_BUF
;
796 *rxOutOfsFp
= outOfs
;
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
;
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
));
826 PUBLIC
int PktReceive (BYTE
*buf
, int max
)
828 WORD ofs
= _farpeekw (_dos_ds
, realBase
+rxOutOfs
);
830 if (ofs
!= _farpeekw (_dos_ds
, realBase
+rxInOfs
))
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
);
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
);
857 PUBLIC
void PktQueueBusy (BOOL busy
)
862 ofs
= _farpeekw (_dos_ds
, realBase
+rxInOfs
);
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);
873 PUBLIC WORD
PktBuffersUsed (void)
878 inOfs
= _farpeekw (_dos_ds
, realBase
+rxInOfs
);
879 outOfs
= _farpeekw (_dos_ds
, realBase
+rxOutOfs
);
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
))
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
);
914 ofs
+= sizeof (RX_ELEMENT
);
915 if (ofs
> LAST_RX_BUF
)
916 *(WORD
*) (realBase
+rxOutOfs
) = FIRST_RX_BUF
;
917 else *(WORD
*) (realBase
+rxOutOfs
) = ofs
;
923 PUBLIC
void PktQueueBusy (BOOL busy
)
928 ofs
= *(WORD
*) (realBase
+rxInOfs
);
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;
939 PUBLIC WORD
PktBuffersUsed (void)
944 inOfs
= *(WORD
*) (realBase
+rxInOfs
);
945 outOfs
= *(WORD
*) (realBase
+rxOutOfs
);
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
);
966 if (CheckElement(head
))
968 size
= min (head
->firstCount
, sizeof(RX_ELEMENT
));
969 len
= min (size
, max
);
970 _fmemcpy (buf
, &head
->destin
, len
);
975 rxOutOfs
+= sizeof (RX_ELEMENT
);
976 if (rxOutOfs
> LAST_RX_BUF
)
977 rxOutOfs
= FIRST_RX_BUF
;
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
;
991 PUBLIC WORD
PktBuffersUsed (void)
993 WORD inOfs
= rxInOfs
;
994 WORD outOfs
= rxOutOfs
;
997 return ((inOfs
- outOfs
) / sizeof(RX_ELEMENT
));
998 return (NUM_RX_BUF
- (outOfs
- inOfs
) / sizeof(RX_ELEMENT
));
1001 PUBLIC DWORD
PktRxDropped (void)
1007 /**************************************************************************/
1009 LOCAL __inline
void PktFreeMem (void)
1011 #if (DOSX & PHARLAP)
1014 _dx_real_free (realSeg
);
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)
1030 dpmi_real_free (rm_base_sel
);
1036 /**************************************************************************/
1038 PUBLIC BOOL
PktExitDriver (void)
1042 if (!PktSetReceiverMode(PDRX_BROADCAST
))
1043 PUTS ("Error restoring receiver mode.");
1045 if (!PktReleaseHandle(pktInfo
.handle
))
1046 PUTS ("Error releasing PKT-DRVR handle.");
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
);
1060 #if (DOSX & (DJGPP|DOS4GW))
1061 static void dump_pkt_stub (void)
1065 fprintf (stderr
, "PktReceiver %lu, pkt_stub[PktReceiver] =\n",
1067 for (i
= 0; i
< 15; i
++)
1068 fprintf (stderr
, "%02X, ", real_stub_array
[i
+PktReceiver
]);
1069 fputs ("\n", stderr
);
1074 * Front end initialization routine
1076 PUBLIC BOOL
PktInitDriver (PKT_RX_MODE mode
)
1079 BOOL writeInfo
= (pcap_pkt_debug
>= 3);
1081 pktInfo
.quiet
= (pcap_pkt_debug
< 3);
1083 #if (DOSX & PHARLAP) && defined(__HIGHC__)
1086 fprintf (stderr
, "Only Pharlap DOS extender supported.\n");
1091 #if (DOSX & PHARLAP) && defined(__WATCOMC__)
1094 fprintf (stderr
, "Only DOS4GW style extenders supported.\n");
1099 if (!PktSearchDriver())
1101 PUTS ("Packet driver not found.");
1106 if (!PktGetDriverInfo())
1108 PUTS ("Error getting pkt-drvr information.");
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
;
1124 PUTS ("Cannot allocate real-mode stub.");
1128 #elif (DOSX & (DJGPP|DOS4GW))
1129 if (sizeof(real_stub_array
) > 0xFFFF)
1131 fprintf (stderr
, "`real_stub_array[]' too big.\n");
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.");
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
);
1151 PUTS ("real-mode init failed.");
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
;
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");
1174 if (*(WORD
*)(real_stub_array
+ offsetof(PktRealStub
,_dummy
)) != 0xB800)
1176 fprintf (stderr
, "`real_stub_array[]' is misaligned.\n");
1181 if (pcap_pkt_debug
> 2)
1185 rxOutOfs
= FIRST_RX_BUF
;
1186 rxInOfs
= FIRST_RX_BUF
;
1189 if (!PktSetAccess())
1191 PUTS ("Error setting pkt-drvr access.");
1196 if (!PktGetAddress(&myAddress
))
1198 PUTS ("Error fetching adapter address.");
1203 if (!PktSetReceiverMode(mode
))
1205 PUTS ("Error setting receiver mode.");
1210 if (!PktGetReceiverMode(&rxMode
))
1212 PUTS ("Error getting receiver mode.");
1218 printf ("Pkt-driver information:\n"
1219 " Version : %d.%d\n"
1221 " Class : %u (%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)
1245 DWORD rAdr
= realBase
+ (WORD
)&PktReceiver
;
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
);
1273 memset (&pktStat
, 0, sizeof(pktStat
)); /* clear statistics */
1274 PktQueueBusy (TRUE
);
1280 * DPMI functions only for Watcom + DOS4GW extenders
1283 LOCAL DWORD
dpmi_get_real_vector (int intr
)
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
)
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
);
1304 return (r
.w
.ax
); /* Return segment address */
1307 LOCAL
void dpmi_real_free (WORD selector
)
1311 r
.x
.eax
= 0x101; /* DPMI free DOS memory */
1312 r
.x
.ebx
= selector
; /* Selector to free */
1313 int386 (0x31, &r
, &r
);
1318 #if defined(DOSX) && (DOSX & PHARLAP)
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
1358 int RealCopy (ULONG start_offs
,
1360 REALPTR
*real_basep
,
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 */
1372 /* First check for valid inputs
1374 if (start_offs
>= end_offs
|| end_offs
> 0x10000)
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
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
)
1401 if (_dx_real_above(len
, rmem_adrp
, &stemp
) != _DOSE_NONE
)
1404 if (_dx_cmem_usage(0, 1, &temp
, &temp
) != _DOSE_NONE
)
1406 if (*rmem_adrp
!= 0)
1407 _dx_real_free (*rmem_adrp
);
1411 if (*rmem_adrp
== 0)
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
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
);
1436 #endif /* DOSX && (DOSX & PHARLAP) */