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