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