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