Main Page | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

SRC/pcpkt.c

Go to the documentation of this file.
00001 00009 #include <stdio.h> 00010 #include <stdlib.h> 00011 #include <stddef.h> 00012 #include <string.h> 00013 #include <limits.h> 00014 00015 /* Nothing of this is needed for Win32. 00016 * Refer winpkt.c instead. 00017 */ 00018 #if !defined(WIN32) && !defined(_WIN32) 00019 00020 #if defined(__DJGPP__) 00021 #include <sys/exceptn.h> 00022 #include <sys/nearptr.h> 00023 #include <crt0.h> 00024 #endif 00025 00026 #include "copyrigh.h" 00027 #include "wattcp.h" 00028 #include "wdpmi.h" 00029 #include "x32vm.h" 00030 #include "powerpak.h" 00031 #include "asmpkt.h" 00032 #include "strings.h" 00033 #include "language.h" 00034 #include "sock_ini.h" 00035 #include "cpumodel.h" 00036 #include "misc.h" 00037 #include "timer.h" 00038 #include "profile.h" 00039 #include "pcsed.h" 00040 #include "pcstat.h" 00041 #include "pcconfig.h" 00042 #include "pcdbug.h" 00043 #include "pcmulti.h" 00044 #include "pcqueue.h" 00045 #include "pcpkt.h" 00046 #include "pcpkt32.h" 00047 00048 00049 /*@-usedef@*/ 00050 00051 WORD _pktdevclass = PDCLASS_UNKNOWN; 00052 WORD _pkt_ip_ofs = 0; 00053 WORD _pkt_type_ofs = 0; 00054 BOOL _pktserial = FALSE; 00055 BYTE _pktdevlevel = 1; 00056 int _pkt_rxmode = RXMODE_BROADCAST; 00057 int _pkt_rxmode0 = -1; 00058 int _pkt_errno = 0; 00059 const char *pkt_error = NULL; 00061 int _pkt_forced_rxmode = -1; 00062 char _pktdrvrname[20] = "unknown"; 00063 00064 struct pkt_info *_pkt_inf = NULL; 00066 static char pkt_sign[] = "PKT DRVR"; 00067 static WORD pkt_interrupt = 0; 00068 static DWORD pkt_drop_cnt = 0; 00069 static BYTE pkt_txretries = 2; 00070 static int pkt_txwait = 0; /* # msec to wait if Tx fails */ 00071 static BOOL pkt_use_near = FALSE; /* Use near-ptr if enabled */ 00072 static BOOL pkt_do_reset = FALSE; /* reset handle at exit */ 00073 static int pkt_drvr_ver = 0; /* Driver internal version */ 00074 static int pkt_num_rx_bufs = RX_BUFS; 00075 00076 #if defined(USE_STATISTICS) 00077 static struct PktStats init_stats; 00078 static void get_init_stats (void); 00079 #endif 00080 00081 static struct PktParameters pkt_params; 00082 static BOOL got_params = FALSE; 00083 00088 #define PKT_FIRST_VEC 0x60 00089 #define PKT_LAST_VEC 0x80 00090 #define PKT_FIRST_VEC_11 0x20 00091 #define PKT_LAST_VEC_11 0xFF 00092 00093 00094 #if (DOSX & PHARLAP) 00095 #include <mw/exc.h> 00096 00097 REALPTR rm_base; 00098 00099 /* 00100 * real-data is organised as follows: PKT_TMP at rm_base + 0x40 00101 * TX_BUF at PKT_TMP + PKT_TMP_SIZE 00102 * RX_BUF at TX_BUF + RX_SIZE 00103 */ 00104 #define PKT_TMP() (WORD) 0x40 00105 #define TX_BUF() (PKT_TMP() + PKT_TMP_SIZE) /* DWORD boundary */ 00106 #define RX_BUF() (TX_BUF() + RX_SIZE) 00107 #define RDATA_SIZE (RX_BUF() + RX_SIZE) 00108 #define RP_SEGM() RP_SEG (rm_base) 00109 00110 #elif (DOSX & X32VM) /* X32VM is very similar to Pharlap except that it */ 00111 REALPTR rm_base; /* automatically maps DOS memory into our DS */ 00112 00113 #define PKT_TMP() (WORD) 0x40 00114 #define TX_BUF() (PKT_TMP() + PKT_TMP_SIZE) 00115 #define RX_BUF() (TX_BUF() + RX_SIZE) 00116 #define RDATA_SIZE (RX_BUF() + RX_SIZE) 00117 #define RP_SEGM() RP_SEG (rm_base) 00118 00119 #elif (DOSX & DJGPP) 00120 #if !defined(USE_FAST_PKT) 00121 static _go32_dpmi_seginfo rm_cb; 00122 #endif 00123 00124 static DWORD rm_base; 00125 00126 /* 00127 * real-data is organised as follows: PKT_TMP at rm_base + 0 00128 * TX_BUF at PKT_TMP + PKT_TMP_SIZE 00129 * RX_BUF at TX_BUF + RX_SIZE 00130 */ 00131 #define PKT_TMP() 0 00132 #define TX_BUF() (PKT_TMP() + PKT_TMP_SIZE) 00133 #define RX_BUF() (TX_BUF() + RX_SIZE) 00134 #define RDATA_SIZE (RX_BUF() + RX_SIZE) 00135 #define RP_SEGM() _pkt_inf->rm_seg 00136 00137 #elif (DOSX & DOS4GW) /* All DOS4GW type extenders */ 00138 00139 static DWORD rm_base; /* Linear address (in DOS) for allocated area */ 00140 #if !defined(USE_FAST_PKT) 00141 static WORD pkt_inf_sel; /* selector returned from `_pkt_inf' allocation */ 00142 #endif 00143 00144 /* 00145 * The DOS-area (0-1MB) is automagically mapped into application 00146 * data. This eases communication with packet-driver, but clean 00147 * crashes can not be expected. i.e. bugs (dereferencing null-ptr) 00148 * in application will most likely hang the machine. 00149 * 00150 * Real-mode code/data is organised like this: 00151 * pkt_receiver4_start() copied to allocated area at rm_base 00152 * PKT_TMP at rm_base + (pkt_receiver4_end() - pkt_receiver4_start()) 00153 * TX_BUF at PKT_TMP + PKT_TMP_SIZE 00154 * end area at TX_BUF + RX_SIZE 00155 * RX_BUF is in DOS-allocated `_pkt_inf' structure. 00156 */ 00157 #define PKT_TMP() ((DWORD)pkt_receiver4_end - \ 00158 (DWORD)pkt_receiver4_start) 00159 #define TX_BUF() (PKT_TMP() + PKT_TMP_SIZE) 00160 #define RCV_OFS() ((DWORD)pkt_receiver4_rm - \ 00161 (DWORD)pkt_receiver4_start) 00162 #define RP_SEGM() _pkt_inf->rm_seg 00163 00164 #elif (DOSX & POWERPAK) 00165 static REALPTR rm_base; 00166 #if !defined(USE_FAST_PKT) 00167 static DPMI_callback rm_cb; 00168 #endif 00169 00170 #define PKT_TMP() 0 00171 #define TX_BUF() (PKT_TMP() + PKT_TMP_SIZE) 00172 #define RX_BUF() (TX_BUF() + RX_SIZE) 00173 #define RDATA_SIZE (RX_BUF() + RX_SIZE) 00174 #define RP_SEGM() _pkt_inf->rm_seg 00175 00176 #elif (DOSX == 0) 00177 void (__cdecl _far * pkt_enque_ptr) (BYTE _far *buf, WORD len); 00178 void (__cdecl _far *_pkt_enque_ptr) (BYTE _far *buf, WORD len); 00179 00180 #else 00181 #error Help me! 00182 #endif 00183 00184 00185 #if defined(USE_FAST_PKT) 00186 #include "pcpkt2.c" 00187 00188 #elif (DOSX) 00189 static int setup_rmode_callback (void); 00190 static int lock_code_and_data (void); 00191 static int unlock_code_and_data (void); 00192 #endif 00193 00194 static int find_vector (int first, int num); 00195 static int setup_pkt_inf (void); 00196 static void get_rmode_data (void *dest, unsigned size, WORD seg, WORD ofs); 00197 static BOOL pkt_api_entry (IREGS *reg, unsigned called_from_line); 00198 00199 #define PKT_API(reg) pkt_api_entry (reg, __LINE__) 00200 #define CARRY_BIT 1 /* carry bit in (e)flags register */ 00201 00202 #define PKT_ERR(str,code) do { \ 00203 const char *err = pkt_strerror (code); \ 00204 outs (_LANG(str)); \ 00205 outsnl (err); \ 00206 } while (0) 00207 00211 const char *pkt_strerror (int code) 00212 { 00213 static char buf[50]; 00214 static const char *errors[] = { 00215 __LANG("Unknown driver error (0x--)"), 00216 /* 1 */ __LANG("Invalid handle number"), 00217 __LANG("No interfaces of specified class found"), 00218 /* 3 */ __LANG("No interfaces of specified type found"), 00219 __LANG("No interfaces of specified number found"), 00220 /* 5 */ __LANG("Bad packet type specified"), 00221 __LANG("This interface does not support multicast"), 00222 /* 7 */ __LANG("This packet driver cannot terminate"), 00223 __LANG("An invalid receiver mode was specified"), 00224 /* 9 */ __LANG("Operation failed because of insufficient space"), 00225 __LANG("Type previously accessed, and not released"), 00226 /* 11 */ __LANG("The command was out of range, or not implemented"), 00227 __LANG("Cannot send packet (hardware error)"), 00228 /* 13 */ __LANG("Cannot change hardware address"), 00229 __LANG("Hardware address has bad length/format"), 00230 /* 15 */ __LANG("Could not reset interface"), 00231 __LANG("Extended driver needed") 00232 }; 00233 const char *rc; 00234 char *p; 00235 00236 if (code > 0 && code < DIM(errors)) 00237 return (_LANG(errors[code])); 00238 00239 rc = StrLcpy (buf, _LANG(errors[0]), sizeof(buf)); 00240 p = strchr (rc, '('); 00241 if (p && strlen(p) >= 5) 00242 { 00243 code &= 0xFF; 00244 p[3] = hex_chars_upper [code >> 4]; 00245 p[4] = hex_chars_upper [code & 15]; 00246 } 00247 return (buf); 00248 } 00249 00250 /* 00251 * Only for testing asmpkt4.asm 00252 */ 00253 #if (DOSX & DOS4GW) && 0 00254 static void dump_asm4 (void) 00255 { 00256 const BYTE *p = (const BYTE*) rm_base; 00257 int i; 00258 00259 printf ("PKT_INF %08lX, HEAD %08lX, QUEUE %08lX, INDEX %04X, XYPOS %d\n", 00260 *(DWORD*)p, *(DWORD*)(p+4), *(DWORD*)(p+8), *(WORD*)(p+12), 00261 *(WORD*)(p+14)); 00262 00263 printf ("rm_base %08lX, handle %04X, is_serial %d\n", 00264 rm_base, _pkt_inf->handle, _pkt_inf->is_serial); 00265 00266 printf ("VAR_1-14: "); 00267 for (i = 16; i <= 42; i += 2) 00268 printf ("%04X ", *(WORD*)(p+i)); 00269 00270 #if 0 00271 printf ("PKT_RECV: "); 00272 for (i = RCV_OFS(); i < RCV_OFS()+10; i++) 00273 printf ("%02X ", p[i]); 00274 00275 printf ("\nPKT_TMP: "); 00276 for (i = PKT_TMP(); i < PKT_TMP()+PKT_TMP_SIZE; i++) 00277 printf ("%02X ", p[i]); 00278 #endif 00279 fflush (stdout); 00280 } 00281 #endif 00282 00283 00289 #if (DOSX & DOS4GW) 00290 void *pkt_tx_buf (void) 00291 { 00292 return (void*)(rm_base + TX_BUF()); 00293 } 00294 00295 #elif (DOSX & DJGPP) 00296 void *pkt_tx_buf (void) 00297 { 00298 if (_pkt_inf && _pkt_inf->use_near_ptr) 00299 return (void*)(rm_base + TX_BUF() + __djgpp_conventional_base); 00300 fprintf (stderr, "%s (%d): wrong usage of pkt_tx_buf()\n", 00301 __FILE__, __LINE__); 00302 exit (-1); 00303 /*@-unreachable-*/ 00304 return (NULL); 00305 } 00306 00307 #elif (DOSX & X32VM) 00308 void *pkt_tx_buf (void) 00309 { 00310 return (void*) ((RP_SEG(rm_base) << 4) + RP_OFF(rm_base) + 00311 (DWORD)_x386_zero_base_ptr + TX_BUF()); 00312 } 00313 #endif 00314 00320 static int pkt_set_access (void) 00321 { 00322 IREGS regs; 00323 00324 ASSERT_PKT_INF (0); 00325 00326 memset (&regs, 0, sizeof(regs)); 00327 00328 regs.r_ax = PD_ACCESS | _pktdevclass; 00329 regs.r_bx = 0xFFFF; /* any type */ 00330 regs.r_dx = 0; /* generic interface */ 00331 regs.r_cx = 0; /* receive any proto */ 00332 00333 #if defined(USE_FAST_PKT) 00334 regs.r_es = _pkt_inf->rm_seg; 00335 regs.r_di = PktReceiver; 00336 00337 #elif (DOSX & DJGPP) 00338 regs.r_es = rm_cb.rm_segment; 00339 regs.r_di = rm_cb.rm_offset; 00340 00341 #elif (DOSX & (PHARLAP|X32VM)) 00342 regs.r_es = RP_SEGM(); 00343 regs.r_di = 0; /* RMCB aligned at para address */ 00344 00345 #elif (DOSX & POWERPAK) 00346 regs.r_es = RP_SEG (rm_cb.rm_addr); 00347 regs.r_di = RP_OFF (rm_cb.rm_addr); 00348 00349 #elif (DOSX & DOS4GW) 00350 regs.r_es = RP_SEGM(); 00351 regs.r_di = RCV_OFS(); 00352 00353 #else /* real-mode targets */ 00354 regs.r_es = FP_SEG (pkt_receiver_rm); /* = this CS */ 00355 regs.r_di = FP_OFF (pkt_receiver_rm); 00356 #endif 00357 00358 if (!PKT_API(&regs)) 00359 { 00360 PKT_ERR ("Error allocating handle: ", _pkt_errno); 00361 return (0); 00362 } 00363 _pkt_inf->handle = (WORD) regs.r_ax; 00364 return (1); 00365 } 00366 00370 static int pkt_drvr_info (void) 00371 { 00372 IREGS regs; 00373 int rc = 1; /* assume okay */ 00374 00375 ASSERT_PKT_INF (0); 00376 00377 /* Lets find out about the driver 00378 */ 00379 memset (&regs, 0, sizeof(regs)); 00380 regs.r_ax = PD_DRIVER_INFO; 00381 00382 if (!PKT_API(&regs)) 00383 { 00384 TCP_CONSOLE_MSG (0, ("Warning: old-type PKTDRVR\n")); 00385 _pktdevclass = PDCLASS_ETHER; /* assume Ethernet */ 00386 _pkt_ip_ofs = sizeof(eth_Header); 00387 _pkt_type_ofs = offsetof (struct eth_Header, type); 00388 _pkt_errno = 0; 00389 } 00390 else /* new Packet-Driver (1.09+) */ 00391 { 00392 _pktdevlevel = loBYTE (regs.r_ax); 00393 _pktdevclass = hiBYTE (regs.r_cx); 00394 pkt_drvr_ver = regs.r_bx & 0xFFFF; 00395 00396 switch (_pktdevclass) 00397 { 00398 case PDCLASS_TOKEN: 00399 case PDCLASS_TOKEN_RIF: /* !! fix me */ 00400 _pkt_ip_ofs = sizeof(tok_Header); 00401 _pkt_type_ofs = offsetof (struct tok_Header, type); 00402 break; 00403 00404 case PDCLASS_ETHER: 00405 _pkt_ip_ofs = sizeof(eth_Header); 00406 _pkt_type_ofs = offsetof (struct eth_Header, type); 00407 break; 00408 00409 case PDCLASS_FDDI: 00410 _pkt_ip_ofs = sizeof(fddi_Header); 00411 _pkt_type_ofs = offsetof (struct fddi_Header, type); 00412 break; 00413 00414 case PDCLASS_ARCNET: 00415 _pkt_ip_ofs = ARC_HDRLEN; 00416 _pkt_type_ofs = ARC_TYPE_OFS; 00417 break; 00418 00419 case PDCLASS_SLIP: 00420 case PDCLASS_PPP: 00421 case PDCLASS_AX25: /* !! for now */ 00422 _pkt_ip_ofs = 0; 00423 _pkt_type_ofs = 0; 00424 break; 00425 00426 default: 00427 outs (_LANG("PKT-ERROR: Unsupported driver class ")); 00428 outhex ((char)_pktdevclass); 00429 outsnl ("h"); 00430 _pkt_errno = PDERR_NO_CLASS; 00431 rc = 0; 00432 } 00433 get_rmode_data (_pktdrvrname, sizeof(_pktdrvrname), regs.r_ds, regs.r_si); 00434 _pktdrvrname [sizeof(_pktdrvrname)-1] = '\0'; 00435 00436 if (pkt_txwait == 0 && 00437 !strcmp(_pktdrvrname,"NDIS3PKT")) 00438 pkt_txwait = 1; /* This helps when using NDIS3PKT */ 00439 } 00440 00441 _pktserial = (_pktdevclass == PDCLASS_SLIP || 00442 _pktdevclass == PDCLASS_PPP || 00443 _pktdevclass == PDCLASS_AX25); 00444 00445 _pkt_inf->is_serial = _pktserial; 00446 _pkt_inf->pkt_ip_ofs = _pkt_ip_ofs; 00447 _pkt_inf->pkt_type_ofs = _pkt_type_ofs; 00448 return (rc); 00449 } 00450 00454 int pkt_get_params (struct PktParameters *params) 00455 { 00456 IREGS regs; 00457 int rc = 0; 00458 00459 memset (&regs, 0, sizeof(regs)); 00460 regs.r_ax = PD_GET_PARAM; /* get driver parameters */ 00461 00462 DISABLE(); 00463 if (PKT_API(&regs)) 00464 { 00465 get_rmode_data (params, sizeof(*params), regs.r_es, regs.r_di); 00466 got_params = TRUE; 00467 rc = 1; 00468 } 00469 ENABLE(); 00470 return (rc); 00471 } 00472 00477 int pkt_get_mtu (void) 00478 { 00479 if (_pktdevclass == PDCLASS_ARCNET) 00480 return (ARCNET_MAX_DATA - 8); 00481 00482 if (got_params) 00483 return (pkt_params.mtu); 00484 return (-1); 00485 } 00486 00487 #ifdef NOT_USED 00488 00492 int pkt_get_mac_len (void) 00493 { 00494 if (_pktdevclass == PDCLASS_ARCNET) 00495 return (sizeof(arcnet_address)); 00496 if (got_params) 00497 return (pkt_params.addr_len); 00498 return (-1); 00499 } 00500 #endif 00501 00507 int pkt_get_api_ver (DWORD *ver) 00508 { 00509 if (got_params) 00510 { 00511 *ver = ((pkt_params.major_rev << 8) + pkt_params.minor_rev); 00512 return (1); 00513 } 00514 return (0); 00515 } 00516 00520 int pkt_get_drvr_ver (WORD *major, WORD *minor) 00521 { 00522 if (!pkt_drvr_ver) 00523 return (0); 00524 *major = pkt_drvr_ver >> 8; 00525 *minor = pkt_drvr_ver & 255; 00526 return (1); 00527 } 00528 00532 int pkt_get_vector (void) 00533 { 00534 return (pkt_interrupt); 00535 } 00536 00548 static int pkt16_drvr_init (mac_address *mac_addr) 00549 { 00550 /* If interrupt specified in config-file ("PKT.VECTOR = 0xNN"), 00551 * check a single vector. Else, search for the 1st driver in range 00552 * 0x60-0x80. 00553 */ 00554 if (pkt_interrupt) 00555 pkt_interrupt = find_vector (pkt_interrupt, 1); 00556 else pkt_interrupt = find_vector (PKT_FIRST_VEC, 00557 PKT_LAST_VEC - PKT_FIRST_VEC + 1); 00558 00559 if (pkt_interrupt == 0) 00560 { 00561 outsnl (_LANG("NO PACKET DRIVER FOUND.")); 00562 return (WERR_NO_DRIVER); 00563 } 00564 00565 if (!setup_pkt_inf()) 00566 { 00567 outsnl (_LANG("Failed to allocate PACKET DRIVER data.")); 00568 return (WERR_NO_MEM); 00569 } 00570 00571 #if defined(USE_FAST_PKT) 00572 switch (setup_rmode_receiver()) 00573 { 00574 case -1: 00575 outsnl (_LANG("Error in PACKET DRIVER stub code.")); 00576 return (WERR_PKT_ERROR); 00577 } 00578 #elif (DOSX) 00579 switch (setup_rmode_callback()) 00580 { 00581 case -1: 00582 outsnl (_LANG("Failed to allocate callback for PACKET DRIVER.")); 00583 return (WERR_NO_MEM); 00584 case -2: 00585 outsnl (_LANG("Failed to allocate DOS-mem for PACKET DRIVER.")); 00586 case -3: /* msg already printed */ 00587 return (WERR_NO_MEM); 00588 } 00589 00590 if (lock_code_and_data() < 0) 00591 { 00592 outsnl (_LANG("Failed to lock code/data for PACKET DRIVER.")); 00593 return (WERR_PKT_ERROR); 00594 } 00595 #endif /* USE_FAST_PKT */ 00596 00597 if (!pkt_drvr_info()) /* get device class etc. of driver */ 00598 return (WERR_PKT_ERROR); 00599 00600 if (!pkt_set_access()) /* set upcall receive handler */ 00601 { 00602 pkt_release(); 00603 return (WERR_PKT_ERROR); 00604 } 00605 00606 if (!pkt_get_addr(mac_addr)) /* get our MAC address */ 00607 { 00608 pkt_release(); 00609 return (WERR_PKT_ERROR); 00610 } 00611 00612 memset (&pkt_params, 0, sizeof(pkt_params)); 00613 got_params = FALSE; 00614 00615 if (_pktdevlevel >= 5 && _pktdevlevel < 255) /* high-performance driver */ 00616 { 00617 if (!pkt_get_params(&pkt_params)) 00618 TCP_CONSOLE_MSG (1, ("Failed to get PKTDRVR params; %s\n", 00619 pkt_strerror(_pkt_errno))); 00620 } 00621 00622 #if defined(USE_STATISTICS) 00623 if (_pktdevlevel >= 2 && _pktdevlevel < 255) /* extended driver */ 00624 get_init_stats(); 00625 #endif 00626 00627 if (_pktserial) 00628 return (0); /* success */ 00629 00630 /* Set Rx-mode forced via config. 00631 */ 00632 if (_pkt_forced_rxmode != -1 && 00633 (_pkt_forced_rxmode < -1 || 00634 _pkt_forced_rxmode > RXMODE_PROMISCOUS)) 00635 { 00636 TCP_CONSOLE_MSG (0, ("Illegal Rx-mode (%d) specified\n", 00637 _pkt_forced_rxmode)); 00638 _pkt_forced_rxmode = -1; 00639 } 00640 00641 if (pkt_get_rcv_mode()) 00642 _pkt_rxmode0 = _pkt_rxmode; /* remember startup mode */ 00643 00644 if (_pkt_forced_rxmode != -1 && 00645 _pkt_forced_rxmode != _pkt_rxmode0) 00646 pkt_set_rcv_mode (_pkt_forced_rxmode); 00647 00648 /* else hope _pkt_rxmode0 is >= RXMODE_BROADCAST */ 00649 00650 return (0); /* success */ 00651 } 00652 00653 /* 00654 * The following functions (ending at '_pkt_end()') are called 00655 * at interrupt time (or asynchronously). 'pkt_release()' may be 00656 * called from SIGSEGV handler. Therefore don't assume anything 00657 * about the state of our stack (except hope it's large enough). 00658 * And don't use large local variables here. Hope we will not be 00659 * reentered since not all functions below are reentrant. 00660 */ 00661 00662 /* Disable stack-checking here 00663 */ 00664 #if defined(__HIGHC__) 00665 #pragma off(Call_trace) 00666 #pragma off(Prolog_trace) 00667 #pragma off(Epilog_trace) 00668 #endif 00669 00670 #if defined(WATCOM386) 00671 /* #pragma option -zu */ /* assume SS != DS (doesn't work) */ 00672 /* #pragma aux pkt_release __modify[ss] */ /* !! fix-me (doesn't work) */ 00673 #endif 00674 00675 #include "nochkstk.h" 00676 00677 00681 int pkt_release_handle (WORD handle) 00682 { 00683 static IREGS regs; /* `static' because the stack could be too small */ 00684 00685 memset (&regs, 0, sizeof(regs)); 00686 regs.r_ax = PD_RELEASE; 00687 regs.r_bx = handle; 00688 00689 if (!PKT_API(&regs) && !_watt_fatal_error) 00690 PKT_ERR ("Error releasing handle: ", _pkt_errno); 00691 return (1); 00692 } 00693 00697 int pkt_reset_handle (WORD handle) 00698 { 00699 static IREGS regs; /* `static' because the stack could be too small */ 00700 00701 memset (&regs, 0, sizeof(regs)); 00702 regs.r_ax = PD_RESET; 00703 regs.r_bx = handle; 00704 00705 if (!PKT_API(&regs)) 00706 PKT_ERR ("Error resetting handle: ", _pkt_errno); 00707 return (1); 00708 } 00709 00710 #if (DOSX) && !defined(USE_FAST_PKT) 00711 static void release_callback (void) 00712 { 00713 #if (DOSX & (PHARLAP|X32VM)) 00714 if (rm_base) 00715 _dx_free_rmode_wrapper (rm_base); 00716 rm_base = 0; 00717 00718 #elif (DOSX & POWERPAK) 00719 if (rm_cb.pm_func) 00720 dpmi_free_callback_retf (&rm_cb); 00721 rm_cb.pm_func = 0; 00722 00723 #elif (DOSX & DJGPP) 00724 if (rm_cb.pm_offset) 00725 _pkt_dpmi_free_real_mode_callback (&rm_cb); 00726 rm_cb.pm_offset = 0; 00727 #endif 00728 } 00729 #endif /* DOSX && !USE_FAST_PKT */ 00730 00731 00735 #if (DOSX) && defined(USE_FAST_PKT) 00736 static void release_real_mem (void) 00737 { 00738 #if (DOSX & PHARLAP) 00739 if (_pkt_inf && _pkt_inf->rm_seg) 00740 _dx_real_free (_pkt_inf->rm_seg); 00741 rm_base = 0; 00742 00743 #elif (DOSX & X32VM) 00744 if (rm_base) 00745 _x32_real_free (rm_base); 00746 rm_base = 0; 00747 00748 #elif (DOSX & POWERPAK) 00749 if (_pkt_inf && _pkt_inf->rm_sel) 00750 dpmi_real_free (_pkt_inf->rm_sel); 00751 00752 #elif (DOSX & DJGPP) 00753 if (_pkt_inf && _pkt_inf->rm_sel) 00754 { 00755 __dpmi_error = 0; 00756 __dpmi_free_dos_memory (_pkt_inf->rm_sel); /* DPMI fn 101h */ 00757 if (__dpmi_error) 00758 { 00759 (*_printf) ("%s (%u): DPMI/DOS error %04Xh\n", 00760 __FILE__, __LINE__, __dpmi_error); 00761 TCP_TRACE_MSG (("release_real_mem: dpmi_error %u\n", __dpmi_error)); 00762 } 00763 } 00764 rm_base = (DWORD)-1; /* crash if used after freed */ 00765 00766 #elif (DOSX & DOS4GW) 00767 if (!_watt_fatal_error && _pkt_inf) 00768 { 00769 if (_pkt_inf->rm_sel) 00770 dpmi_real_free (_pkt_inf->rm_sel); 00771 00772 #if !defined(USE_FAST_PKT) 00773 if (pkt_inf_sel) 00774 dpmi_real_free (pkt_inf_sel); 00775 pkt_inf_sel = 0; 00776 #endif 00777 } 00778 #endif 00779 00780 if (_pkt_inf) 00781 _pkt_inf->rm_sel = _pkt_inf->rm_seg = 0; 00782 00783 #if !defined(USE_FAST_PKT) 00784 _pkt_inf = NULL; /* don't free this ptr below */ 00785 #endif 00786 } 00787 #endif /* DOSX && USE_FAST_PKT */ 00788 00789 00798 #ifdef __WATCOMC__ 00799 #pragma aux pkt_release loadds; 00800 #endif 00801 00802 #ifdef __GNUC__ 00803 #define DTOR __attribute__((destructor)) 00804 #else 00805 #define DTOR 00806 #endif 00807 00808 int DTOR pkt_release (void) 00809 { 00810 DISABLE(); 00811 00812 if (_pkt_inf) 00813 { 00814 /* Don't do this by default. It may cause some (RealTek) 00815 * packet-drivers to fail all further upcalls. 00816 */ 00817 if (pkt_do_reset) 00818 pkt_reset_handle (_pkt_inf->handle); 00819 pkt_release_handle (_pkt_inf->handle); 00820 } 00821 00822 /* !! pkt_interrupt = 0; */ 00823 00831 #if (DOSX) && !defined(USE_FAST_PKT) 00832 unlock_code_and_data(); /* unlock before freeing */ 00833 release_callback(); 00834 #endif 00835 00836 #if (DOSX) && defined(USE_FAST_PKT) 00837 release_real_mem(); 00838 #endif 00839 00840 if (_pkt_inf && !_watt_fatal_error) 00841 free (_pkt_inf); 00842 00843 _pkt_inf = NULL; /* drop anything still in the queue */ 00844 00845 ENABLE(); 00846 return (1); 00847 } 00848 00849 #if defined(__BORLANDC__) 00850 #pragma exit pkt_release 100 00851 #elif defined(__CCDL__) 00852 #pragma rundown pkt_release 110 00853 #endif 00854 00855 00856 #if !defined(USE_FAST_PKT) && !(DOSX & DOS4GW) 00857 00885 #if (DOSX) 00886 static void pkt_enqueue (unsigned rxBuf, WORD rxLen) 00887 #else 00888 static void __cdecl _far pkt_enqueue (BYTE _far *rxBuf, WORD rxLen) 00889 #endif 00890 { 00891 struct pkt_ringbuf *q = &_pkt_inf->pkt_queue; 00892 int index; 00893 00894 /* don't use pktq_in_index() and pktq_in_buf() because they 00895 * are not in locked code area. 00896 */ 00897 index = q->in_index + 1; 00898 if (index >= q->num_buf) 00899 index = 0; 00900 00901 if (index != q->out_index) 00902 { 00903 char *head = (char*)q->buf_start + (q->buf_size * q->in_index); 00904 int padLen = q->buf_size - 4 - rxLen; 00905 00906 if (rxLen > q->buf_size - 4) /* don't overwrite marker */ 00907 { 00908 rxLen = q->buf_size - 4; 00909 padLen = 0; 00910 } 00911 00912 #if (DOSX & (PHARLAP|X32VM|POWERPAK)) 00913 ReadRealMem (head, rm_base + rxBuf, rxLen); 00914 00915 #elif (DOSX & DJGPP) 00916 if (_pkt_inf->use_near_ptr) 00917 memcpy (head, (void*)(rm_base+rxBuf+__djgpp_conventional_base), rxLen); 00918 else DOSMEMGETL (rm_base + rxBuf, (rxLen+3)/4, head); 00919 00920 #else /* real-mode targets */ 00921 _fmemcpy (head, rxBuf, rxLen); 00922 #endif 00923 00924 /* Zero-fill remaining old data in this buffer. 00925 */ 00926 head += rxLen; 00927 while (padLen--) 00928 *head++ = '\0'; 00929 q->in_index = index; /* update buffer tail-index */ 00930 } 00931 else 00932 q->num_drop++; /* no room, increment drop count */ 00933 } 00934 00935 00936 /* 00937 * We have allocated a real-mode callback (RMCB) to gain control 00938 * here when the packet-driver makes an upcall. 00939 * 00940 * Entry AL = 0; driver requests a buffer. We return ES:DI of real-mode buffer 00941 * BX = handle (IP, ARP or RARP) 00942 * CX = length of packet 00943 * 00944 * Entry AL = 1; driver has put the data in buffer, we then enqueues the buffer 00945 * BX = handle (IP, ARP or RARP) 00946 * CX = length of packet (same as CX above) 00947 * DS:SI = *must* be same as ES:DI returned above. 00948 * ES:DI = should be same as ES:DI returned above (but don't count on it). 00949 * 00950 * Interrupts are disabled on entry. 00951 * Note: This function MUST be declared cdecl (not register called). 00952 */ 00953 #if (DOSX & (PHARLAP|X32VM)) 00954 static void cdecl pkt_receiver_pm (SWI_REGS *r) 00955 { 00956 PUSHF_CLI(); 00957 00958 if ((BYTE)r->r_ax == 0) /* AL == 0; rx-buffer request */ 00959 { 00960 if (!_pkt_inf || (WORD)r->r_cx > ETH_MAX) 00961 { 00962 r->r_es = 0; 00963 r->r_di = 0; 00964 } 00965 else 00966 { 00967 r->r_es = RP_SEGM(); 00968 r->r_di = RX_BUF(); 00969 } 00970 } 00971 else if ((WORD)r->r_si && _pkt_inf) /* AL != 0; rx-buffer filled */ 00972 { 00973 pkt_enqueue (RX_BUF(), (WORD)r->r_cx); 00974 } 00975 POPF(); 00976 } 00977 00978 #elif (DOSX & DJGPP) 00979 static void cdecl pkt_receiver_pm (__dpmi_regs *r) 00980 { 00981 WORD fs, gs; 00982 00983 PUSHF_CLI(); /* "cld" already done in RMCB wrapper */ 00984 00985 fs = get_fs_reg(); 00986 gs = get_gs_reg(); 00987 00988 if (r->h.al == 0) 00989 { 00990 if (!_pkt_inf || r->x.cx > ETH_MAX) 00991 { 00992 r->x.es = 0; 00993 r->x.di = 0; 00994 } 00995 else 00996 { 00997 r->x.es = RP_SEGM(); 00998 r->x.di = RX_BUF(); 00999 } 01000 } 01001 else if (r->x.si && _pkt_inf) 01002 { 01003 pkt_enqueue (RX_BUF(), r->x.cx); 01004 } 01005 01006 set_fs_reg (fs); 01007 set_gs_reg (gs); 01008 01009 POPF(); 01010 } 01011 01012 #elif (DOSX & POWERPAK) 01013 static void cdecl pkt_receiver_pm (void) 01014 { 01015 REAL_regs *r; 01016 01017 PUSHF_CLI(); 01018 r = &rm_cb.rm_regs; 01019 01020 if ((BYTE)r->r_ax == 0) 01021 { 01022 if (!_pkt_inf || (WORD)r->r_cx > ETH_MAX) 01023 { 01024 r->r_es = 0; 01025 r->r_di = 0; 01026 } 01027 else 01028 { 01029 r->r_es = RP_SEGM(); 01030 r->r_di = RX_BUF(); 01031 } 01032 } 01033 else if (r->r_si && _pkt_inf) 01034 { 01035 pkt_enqueue (RX_BUF(), (WORD)r->r_cx); 01036 } 01037 POPF(); 01038 } 01039 #endif 01040 01041 void _pkt_end (void) {} 01042 01043 #if defined(__WATCOMC__) 01044 #pragma alloc_text (pkt_lock_TEXT, pkt_enqueue, pkt_receiver_pm, _pkt_end); 01045 #endif 01046 01047 #endif /* !(DOSX & DOS4GW) && !USE_FAST_PKT */ 01048 01049 01060 int pkt_send (const void *tx, int length) 01061 { 01062 IREGS regs; 01063 WORD tx_seg, tx_ofs; 01064 BOOL fail = FALSE; 01065 int tx_cnt; 01066 01067 if (!_pkt_inf) 01068 return (0); 01069 01070 PROFILE_START ("pkt_send"); 01071 01072 memset (&regs, 0, sizeof(regs)); 01073 01074 #if (DOSX & (PHARLAP|POWERPAK)) 01075 tx_seg = RP_SEGM(); 01076 tx_ofs = TX_BUF(); 01077 WriteRealMem (rm_base + tx_ofs, (void*)tx, length); 01078 01079 #elif (DOSX & (DOS4GW|X32VM)) 01080 tx_seg = RP_SEGM(); 01081 tx_ofs = TX_BUF(); 01082 WATT_ASSERT (tx == pkt_tx_buf()); /* no need to copy anything */ 01083 01084 #elif (DOSX & DJGPP) 01085 tx_seg = RP_SEGM(); 01086 tx_ofs = TX_BUF(); 01087 if (_pkt_inf->use_near_ptr) 01088 WATT_ASSERT (tx == pkt_tx_buf()); 01089 else DOSMEMPUTL (tx, (length+3)/4, rm_base + tx_ofs); 01090 01091 #else 01092 tx_seg = FP_SEG (tx); 01093 tx_ofs = FP_OFF (tx); 01094 #endif 01095 01096 for (tx_cnt = 0; tx_cnt <= pkt_txretries; tx_cnt++) 01097 { 01098 regs.r_cx = length; 01099 regs.r_ax = PD_SEND; 01100 regs.r_ds = tx_seg; 01101 regs.r_si = tx_ofs; 01102 01103 fail = FALSE; 01104 01105 if (PKT_API(&regs)) /* success */ 01106 break; 01107 01108 fail = TRUE; 01109 if (pkt_txwait > 0) 01110 Wait (pkt_txwait); 01111 } 01112 01113 if (tx_cnt > 0) 01114 STAT (macstats.num_tx_retry += tx_cnt-1); 01115 01116 if (fail) 01117 length = 0; 01118 01119 if (length == 0) 01120 STAT (macstats.num_tx_err++); 01121 01122 PROFILE_STOP(); 01123 return (length); 01124 } 01125 01129 int pkt_get_addr (mac_address *mac) 01130 { 01131 IREGS regs; 01132 WORD seg, ofs; 01133 int rc; 01134 01135 ASSERT_PKT_INF (0); 01136 01137 PROFILE_START ("pkt_get_addr"); 01138 01139 regs.r_ax = PD_GET_ADDRESS; 01140 regs.r_bx = _pkt_inf->handle; 01141 regs.r_cx = sizeof (*mac); 01142 01143 #if (DOSX) 01144 regs.r_es = seg = RP_SEGM(); 01145 regs.r_di = ofs = PKT_TMP(); 01146 #else 01147 regs.r_es = seg = FP_SEG (mac); 01148 regs.r_di = ofs = FP_OFF (mac); 01149 #endif 01150 01151 if (!PKT_API(&regs)) 01152 { 01153 PKT_ERR ("Cannot read own MAC address: ", _pkt_errno); 01154 rc = 0; 01155 } 01156 else 01157 { 01158 get_rmode_data (mac, sizeof(*mac), seg, ofs); 01159 rc = 1; 01160 } 01161 PROFILE_STOP(); 01162 return (rc); 01163 } 01164 01168 int pkt_set_addr (const void *addr) 01169 { 01170 IREGS regs; 01171 01172 ASSERT_PKT_INF (0); 01173 01174 regs.r_ax = PD_SET_ADDR; 01175 regs.r_cx = sizeof (mac_address); 01176 01177 #if (DOSX & DJGPP) 01178 DOSMEMPUT (addr, sizeof(mac_address), rm_base + PKT_TMP()); 01179 regs.r_es = RP_SEGM(); 01180 regs.r_di = PKT_TMP(); 01181 01182 #elif (DOSX & DOS4GW) 01183 memcpy ((void*)(rm_base + PKT_TMP()), addr, sizeof(mac_address)); 01184 regs.r_es = RP_SEGM(); 01185 regs.r_di = PKT_TMP(); 01186 01187 #elif (DOSX & (PHARLAP|X32VM|POWERPAK)) 01188 WriteRealMem (rm_base + PKT_TMP(), (void*)addr, sizeof(mac_address)); 01189 regs.r_es = RP_SEGM(); 01190 regs.r_di = PKT_TMP(); 01191 01192 #else 01193 { 01194 mac_address tmp; 01195 memcpy (&tmp, addr, sizeof(tmp)); /* prevent driver modifying '*addr' */ 01196 regs.r_es = FP_SEG (&tmp); 01197 regs.r_di = FP_OFF (&tmp); 01198 } 01199 #endif 01200 01201 if (!PKT_API(&regs)) 01202 return (0); 01203 return (1); 01204 } 01205 01206 #if defined(USE_STATISTICS) 01207 01213 int pkt_get_stats (struct PktStats *stats, struct PktStats *total) 01214 { 01215 IREGS regs; 01216 int rc = 0; 01217 01218 PROFILE_START ("pkt_get_stats"); 01219 DISABLE(); 01220 01221 /* Handle in BX is optional for 1.11 drivers 01222 */ 01223 regs.r_bx = _pkt_inf ? _pkt_inf->handle : 0; 01224 regs.r_ax = PD_GET_STATS; 01225 01226 if (!PKT_API(&regs)) 01227 goto fail; 01228 01229 rc = 1; 01230 get_rmode_data (stats, sizeof(*stats), regs.r_ds, regs.r_si); 01231 01232 if (total) 01233 *total = *stats; 01234 01235 stats->in_packets -= init_stats.in_packets; 01236 stats->out_packets -= init_stats.out_packets; 01237 stats->in_bytes -= init_stats.in_bytes; 01238 stats->out_bytes -= init_stats.out_bytes; 01239 stats->in_errors -= init_stats.in_errors; 01240 stats->out_errors -= init_stats.out_errors; 01241 stats->lost -= init_stats.lost; 01242 fail: 01243 ENABLE(); 01244 PROFILE_STOP(); 01245 return (rc); 01246 } 01247 01248 static void get_init_stats (void) 01249 { 01250 IREGS regs; 01251 01252 regs.r_ax = PD_GET_STATS; 01253 regs.r_bx = _pkt_inf->handle; 01254 memset (&init_stats, 0, sizeof(init_stats)); 01255 01256 DISABLE(); 01257 if (PKT_API(&regs)) 01258 get_rmode_data (&init_stats, sizeof(init_stats), regs.r_ds, regs.r_si); 01259 ENABLE(); 01260 } 01261 01262 01267 static WORD cstate_dseg = 0; 01268 01269 int pkt_get_vjstats (struct slcompress *vjstats) 01270 { 01271 IREGS regs; 01272 int rc = 0; 01273 01274 regs.r_ax = PD_GET_VJSTATS; 01275 regs.r_bx = sizeof (*vjstats); 01276 01277 DISABLE(); 01278 if (PKT_API(&regs)) 01279 { 01280 get_rmode_data (vjstats, sizeof(*vjstats), regs.r_ds, regs.r_si); 01281 cstate_dseg = regs.r_ds; 01282 rc = 1; 01283 } 01284 ENABLE(); 01285 return (rc); 01286 } 01287 01288 int pkt_get_cstate (struct cstate *cs, WORD cstate_ofs) 01289 { 01290 if (cstate_dseg == 0 || cstate_ofs == 0) 01291 return (0); 01292 01293 DISABLE(); 01294 get_rmode_data (cs, sizeof(*cs), cstate_dseg, cstate_ofs); 01295 ENABLE(); 01296 return (1); 01297 } 01298 #endif /* USE_STATISTICS */ 01299 01300 01304 int pkt_buf_wipe (void) 01305 { 01306 #if defined(USE_FAST_PKT) 01307 pktq_clear (NULL); 01308 #else 01309 ASSERT_PKT_INF (0); 01310 pktq_clear (&_pkt_inf->pkt_queue); 01311 #endif 01312 return (1); 01313 } 01314 01319 void pkt_free_pkt (const void *pkt) 01320 { 01321 #if !defined(USE_FAST_PKT) /* packet already copied in pcsed.c */ 01322 struct pkt_ringbuf *q; 01323 01324 if (!_pkt_inf || !pkt) 01325 return; 01326 01327 q = &_pkt_inf->pkt_queue; 01328 pkt_drop_cnt = q->num_drop; 01329 01330 if (pkt != (const void*) (pktq_out_buf(q) + _pkt_ip_ofs)) 01331 { 01332 TCP_CONSOLE_MSG (0, ("%s: freeing illegal packet 0x%p.\n", __FILE__, pkt)); 01333 pktq_clear (q); 01334 } 01335 else 01336 pktq_inc_out (q); 01337 #else 01338 if (rm_base && rm_base < (DWORD)-1) 01339 pkt_drop_cnt = FAR_PEEK_DWORD (struct pkt_info, pkt_queue.num_drop); 01340 ARGSUSED (pkt); 01341 #endif 01342 } 01343 01344 01348 int pkt_waiting (void) 01349 { 01350 #if defined(USE_FAST_PKT) 01351 if (rm_base && rm_base < (DWORD)-1) 01352 return pkt_buffers_used(); 01353 return (-1); 01354 #else 01355 if (_pkt_inf) 01356 return pktq_queued (&_pkt_inf->pkt_queue); 01357 return (-1); 01358 #endif 01359 } 01360 01364 DWORD pkt_dropped (void) 01365 { 01366 #if defined(USE_FAST_PKT) 01367 if (rm_base && rm_base < (DWORD)-1) 01368 return pkt_rx_dropped(); 01369 #else 01370 if (_pkt_inf) 01371 return (_pkt_inf->pkt_queue.num_drop); 01372 #endif 01373 return (pkt_drop_cnt); /* return last known value */ 01374 } 01375 01380 static int parse_config_pass_1 (void) 01381 { 01382 static int vect = 0; 01383 static const struct config_table pkt_init_cfg[] = { 01384 { "PKT.VECTOR", ARG_ATOX_B, (void*)&vect }, 01385 { "PKT.TXRETRIES", ARG_ATOB, (void*)&pkt_txretries }, 01386 { "PKT.TXWAIT", ARG_ATOI, (void*)&pkt_txwait }, 01387 { "PKT.RXMODE", ARG_ATOI, (void*)&_pkt_forced_rxmode }, 01388 { "PKT.RXBUFS", ARG_ATOI, (void*)&pkt_num_rx_bufs }, 01389 { "PKT.NEAR_PTR", ARG_ATOI, (void*)&pkt_use_near }, 01390 { "PKT.RESET", ARG_ATOI, (void*)&pkt_do_reset }, 01391 { NULL, 0, NULL } 01392 }; 01393 const struct config_table *cfg_save = watt_init_cfg; 01394 void (*init_save) (const char*, const char*) = usr_init; 01395 int rc; 01396 01397 watt_init_cfg = pkt_init_cfg; 01398 usr_init = NULL; /* only pkt_init_cfg[] gets parsed */ 01399 rc = tcp_config (NULL); 01400 usr_init = init_save; 01401 watt_init_cfg = cfg_save; 01402 if (!rc) 01403 return (0); 01404 return (vect); 01405 } 01406 01419 int pkt_eth_init (mac_address *addr) 01420 { 01421 int vector, rc = -1; 01422 01423 if (_watt_no_config && !_watt_user_config_fn) 01424 vector = 0; 01425 else vector = parse_config_pass_1(); 01426 01427 if (vector) 01428 { 01429 pkt_interrupt = vector; 01430 if (pkt_interrupt < PKT_FIRST_VEC_11 || /* 0x20-0xFF range for 1.11 drvr */ 01431 pkt_interrupt > PKT_LAST_VEC_11) 01432 pkt_interrupt = 0; /* discard illegal value */ 01433 } 01434 else 01435 pkt_interrupt = 0; 01436 01437 { 01438 #if (DOSX) 01439 int pm_driver = pkt32_drvr_probe (pm_driver_list); 01440 01441 if (pm_driver > -1) 01442 { 01443 rc = pkt32_drvr_init (pm_driver, addr); 01444 if (rc == 0) 01445 TCP_CONSOLE_MSG (2, ("Using Pmode `%s' driver at %08lX\n", 01446 pkt32_drvr_name(pm_driver), (DWORD)_pkt32_drvr)); 01447 } 01448 if (rc) /* pmode driver failed, try real-mode driver */ 01449 #endif 01450 rc = pkt16_drvr_init (addr); 01451 01452 if (rc) 01453 return (rc); /* no suitable driver found */ 01454 } 01455 01456 #if defined(USE_FAST_PKT) 01457 FAR_POKE_WORD (struct pkt_info, handle, _pkt_inf->handle); 01458 FAR_POKE_WORD (struct pkt_info, is_serial, _pkt_inf->is_serial); 01459 FAR_POKE_WORD (struct pkt_info, pkt_ip_ofs, _pkt_inf->pkt_ip_ofs); 01460 FAR_POKE_WORD (struct pkt_info, pkt_type_ofs, _pkt_inf->pkt_type_ofs); 01461 01462 #if (DOSX & X32VM) && 0 01463 if (!pkt_test_upcall()) 01464 { 01465 pkt_release(); 01466 return (-1); 01467 } 01468 #endif 01469 #endif 01470 01471 return (0); 01472 } 01473 01477 #if (DOSX & (PHARLAP|X32VM)) 01478 static BOOL check_intr_num (WORD intr_num) 01479 { 01480 REALPTR rp; 01481 char temp[16]; 01482 01483 _dx_rmiv_get (intr_num, &rp); 01484 if (rp) 01485 { 01486 ReadRealMem (&temp, rp, sizeof(temp)); 01487 if (!memcmp(temp+3, pkt_sign, strlen(pkt_sign))) 01488 return (TRUE); 01489 } 01490 return (FALSE); 01491 } 01492 01493 #elif (DOSX & DJGPP) 01494 static BOOL check_intr_num (WORD intr_num) 01495 { 01496 char temp[16]; 01497 DWORD rp; 01498 __dpmi_raddr realAdr; 01499 01500 __dpmi_get_real_mode_interrupt_vector (intr_num, &realAdr); 01501 rp = (realAdr.segment << 4) + realAdr.offset16; 01502 if (rp) 01503 { 01504 dosmemget (rp, sizeof(temp), &temp); 01505 if (!memcmp(temp+3, pkt_sign, strlen(pkt_sign))) 01506 return (TRUE); 01507 } 01508 return (FALSE); 01509 } 01510 01511 #elif (DOSX & DOS4GW) 01512 static BOOL check_intr_num (WORD intr_num) 01513 { 01514 const BYTE *addr = (const BYTE*) dpmi_get_real_vector (intr_num); 01515 01516 if (addr && !memcmp(addr+3, pkt_sign, strlen(pkt_sign))) 01517 return (TRUE); 01518 return (FALSE); 01519 } 01520 01521 #elif (DOSX & POWERPAK) 01522 static BOOL check_intr_num (WORD intr_num) 01523 { 01524 char temp[16]; 01525 DWORD addr = (DWORD) dpmi_get_real_vector (intr_num); 01526 REALPTR rp; 01527 01528 RP_SET (rp, addr & 0xF, addr >> 4); 01529 ReadRealMem (&temp, rp, sizeof(temp)); 01530 if (!memcmp(temp+3, pkt_sign, strlen(pkt_sign))) 01531 return (TRUE); 01532 return (FALSE); 01533 } 01534 01535 #else /* real-mode version */ 01536 static BOOL check_intr_num (WORD intr_num) 01537 { 01538 char _far *addr = (char _far*) getvect (intr_num); 01539 01540 #if !defined(USE_FAST_PKT) 01541 pkt_enque_ptr = pkt_enqueue; 01542 _pkt_enque_ptr = pkt_enqueue; 01543 #endif 01544 01545 if (addr && !_fmemcmp(addr+3, pkt_sign, strlen(pkt_sign))) 01546 return (TRUE); 01547 return (FALSE); 01548 } 01549 #endif 01550 01551 /* 01552 * Find the interrupt-number for the PKTDRVR by searching interrupt 01553 * handler entries (at vector+3) for signature string "PKT DRVR". 01554 */ 01555 static int find_vector (int first, int num) 01556 { 01557 int inum; 01558 01559 for (inum = first; inum < first + num; inum++) 01560 { 01561 if (inum != 0x67 && /* can never be at EMS vector */ 01562 check_intr_num(inum)) 01563 return (inum); 01564 } 01565 return (0); 01566 } 01567 01568 #if !defined(USE_FAST_PKT) 01569 /* 01570 * DOS-extender functions for allocation a real-mode callback that 01571 * the real-mode PKTDRVR will call when a packet is received. 01572 * Lock down all code and data that is touched in this callback. 01573 */ 01574 #if (DOSX & (PHARLAP|X32VM)) 01575 static int setup_rmode_callback (void) 01576 { 01577 rm_base = _dx_alloc_rmode_wrapper_retf (pkt_receiver_pm, NULL, 01578 RDATA_SIZE, 1024); 01579 if (!rm_base) 01580 return (-1); 01581 return (0); 01582 } 01583 01584 static int lock_code_and_data (void) /* Needed for 386|VMM only (?) */ 01585 { 01586 UINT size = (UINT)_pkt_end - (UINT)pkt_enqueue; 01587 01588 _dx_lock_pgsn ((void*)pkt_enqueue, size); 01589 _dx_lock_pgsn ((void*)ReadRealMem, 100); 01590 _dx_lock_pgsn ((void*)_pkt_inf, sizeof(*_pkt_inf)); 01591 _dx_lock_pgsn ((void*)&_pkt_inf, sizeof(_pkt_inf)); 01592 01593 #if (DOSX & X32VM) 01594 _dx_lock_pgsn ((void*)memcpy, 200); 01595 #endif 01596 return (0); 01597 } 01598 01599 static int unlock_code_and_data (void) 01600 { 01601 UINT size = (UINT)_pkt_end - (UINT)pkt_enqueue; 01602 01603 _dx_ulock_pgsn ((void*)pkt_enqueue, size); 01604 _dx_ulock_pgsn ((void*)ReadRealMem, 100); 01605 _dx_ulock_pgsn ((void*)_pkt_inf, sizeof(*_pkt_inf)); 01606 _dx_ulock_pgsn ((void*)&_pkt_inf, sizeof(_pkt_inf)); 01607 01608 #if (DOSX & X32VM) 01609 _dx_ulock_pgsn ((void*)memcpy, 200); 01610 #endif 01611 return (0); 01612 } 01613 01614 #elif (DOSX & DJGPP) 01615 static int setup_rmode_callback (void) 01616 { 01617 static __dpmi_regs rm_reg; 01618 int seg = __dpmi_allocate_dos_memory ((RDATA_SIZE + 15) / 16, 01619 &_pkt_inf->rm_sel); 01620 if (seg < 0) 01621 return (-2); 01622 01623 _pkt_inf->rm_seg = seg; 01624 rm_cb.pm_offset = (DWORD) pkt_receiver_pm; 01625 01626 memset (&rm_reg, 0, sizeof(rm_reg)); 01627 if (_pkt_dpmi_allocate_real_mode_callback_retf (&rm_cb,&rm_reg)) 01628 return (-1); 01629 01630 rm_base = (_pkt_inf->rm_seg << 4); 01631 01632 DOSMEMCLR (rm_base, RDATA_SIZE); 01633 return (0); 01634 } 01635 01636 static int lock_code_and_data (void) 01637 { 01638 DWORD size = (DWORD)_pkt_end - (DWORD)pkt_enqueue; 01639 01640 WATT_ASSERT ((DWORD)_pkt_end > (DWORD)pkt_enqueue); 01641 01642 if (_go32_dpmi_lock_code((void*)pkt_enqueue, size) || 01643 _go32_dpmi_lock_code((void*)__movedata, 30) || 01644 _go32_dpmi_lock_code((void*)_movedatal, 30) || 01645 _go32_dpmi_lock_code((void*)__dj_movedata, 100) || 01646 _go32_dpmi_lock_data(&_pkt_inf, sizeof(_pkt_inf)) || 01647 _go32_dpmi_lock_data(_pkt_inf, sizeof(*_pkt_inf))) 01648 return (-1); 01649 /* rm_reg is already locked */ 01650 return (0); 01651 } 01652 01653 static void _unlock (const void *addr, DWORD size) 01654 { 01655 __dpmi_meminfo mem; 01656 DWORD base = 0; 01657 01658 __dpmi_get_segment_base_address (_my_ds(), &base); 01659 mem.address = base + (DWORD)addr; 01660 mem.size = size; 01661 __dpmi_unlock_linear_region (&mem); 01662 } 01663 01664 static int unlock_code_and_data (void) 01665 { 01666 _unlock ((void*)pkt_enqueue, (DWORD)_pkt_end - (DWORD)pkt_enqueue); 01667 _unlock ((void*)__movedata, 30); 01668 _unlock ((void*)_movedatal, 30); 01669 _unlock ((void*)__dj_movedata, 100); 01670 _unlock (_pkt_inf, sizeof(*_pkt_inf)); 01671 _unlock (&_pkt_inf, sizeof(_pkt_inf)); 01672 return (0); 01673 } 01674 01675 #elif (DOSX & DOS4GW) 01676 static int setup_rmode_callback (void) 01677 { 01678 int length; 01679 01680 /* test for asmpkt4.asm/pcpkt.h mismatch 01681 */ 01682 if (asmpkt_size_chk != sizeof(*_pkt_inf)) 01683 { 01684 #ifdef USE_DEBUG 01685 fprintf (stderr, 01686 "%s (%u): Development error:\n" 01687 " sizeof(pkt_info) = %u pcpkt.h\n" 01688 " sizeof(pkt_info) = %u asmpkt4.asm, (diff %d)\n", 01689 __FILE__, __LINE__, 01690 sizeof(*_pkt_inf), asmpkt_size_chk, 01691 sizeof(*_pkt_inf) - asmpkt_size_chk); 01692 #endif 01693 return (-3); 01694 } 01695 01696 /* Allocate DOS-memory for pkt_receiver4_rm() and temp/Tx buffers. 01697 */ 01698 length = TX_BUF() + RX_SIZE; 01699 _pkt_inf->rm_seg = dpmi_real_malloc (length, &_pkt_inf->rm_sel); 01700 if (!_pkt_inf->rm_seg) 01701 return (-2); 01702 01703 rm_base = ((DWORD)_pkt_inf->rm_seg) << 4; 01704 01705 /* Clear DOS area and copy code down into it. 01706 */ 01707 memset ((void*)rm_base, 0, length); 01708 length = PKT_TMP() - 1; 01709 memcpy ((void*)rm_base, pkt_receiver4_start, length); 01710 return (0); 01711 } 01712 01713 /* No need (?) to lock anything. 01714 */ 01715 static int lock_code_and_data (void) 01716 { 01717 return (0); 01718 } 01719 01720 static int unlock_code_and_data (void) 01721 { 01722 return (0); 01723 } 01724 01725 #elif (DOSX & POWERPAK) 01726 static int setup_rmode_callback (void) 01727 { 01728 /* Allocate DOS-memory for temp/Tx buffers. 01729 */ 01730 _pkt_inf->rm_seg = dpmi_real_malloc (RDATA_SIZE, &_pkt_inf->rm_sel); 01731 if (!_pkt_inf->rm_seg) 01732 return (-2); 01733 01734 rm_base = (REALPTR) ((DWORD)_pkt_inf->rm_seg << 16); 01735 01736 rm_cb.pm_func = pkt_receiver_pm; 01737 if (!dpmi_alloc_callback_retf(&rm_cb)) 01738 return (-1); 01739 return (0); 01740 } 01741 01742 static int lock_code_and_data (void) 01743 { 01744 unsigned size = (unsigned)_pkt_end - (unsigned)pkt_enqueue; 01745 01746 if (!dpmi_lock_region ((void*)pkt_enqueue, size) || 01747 !dpmi_lock_region ((void*)ReadRealMem, 100) || 01748 !dpmi_lock_region ((void*)_pkt_inf, sizeof(*_pkt_inf)) || 01749 !dpmi_lock_region ((void*)&_pkt_inf, sizeof(_pkt_inf))) 01750 return (-1); 01751 return (0); 01752 } 01753 01754 static int unlock_code_and_data (void) 01755 { 01756 unsigned size = (unsigned)_pkt_end - (unsigned)pkt_enqueue; 01757 01758 if (!dpmi_unlock_region ((void*)pkt_enqueue, size) || 01759 !dpmi_unlock_region ((void*)ReadRealMem, 100) || 01760 !dpmi_unlock_region ((void*)_pkt_inf, sizeof(*_pkt_inf)) || 01761 !dpmi_unlock_region ((void*)&_pkt_inf, sizeof(_pkt_inf))) 01762 return (-1); 01763 return (0); 01764 } 01765 #endif 01766 #endif /* !USE_FAST_PKT */ 01767 01768 01769 /* 01770 * For DOS4GW targets, allocate the '_pkt_inf' structure 01771 * from DOS memory. All others allocate from heap. 01772 */ 01773 static int setup_pkt_inf (void) 01774 { 01779 int size = sizeof (*_pkt_inf); 01780 01781 #if (DOSX & DOS4GW) && !defined(USE_FAST_PKT) 01782 DWORD seg; 01783 01784 WATT_ASSERT (size < USHRT_MAX); /* max alloc from DOS is 64k */ 01785 01786 seg = dpmi_real_malloc (size, &pkt_inf_sel); 01787 01788 asmpkt_inf = (struct pkt_info*) (seg << 16); /* run-time location */ 01789 _pkt_inf = (struct pkt_info*) (seg << 4); 01790 01791 #else 01792 _pkt_inf = malloc (size); 01793 #endif 01794 01795 if (!_pkt_inf) /* Allocation failed */ 01796 return (0); 01797 01798 memset (_pkt_inf, 0, size); /* Clear area */ 01799 01800 #if defined(USE_FAST_PKT) 01801 rm_base = setup_pkt_inf_fast(); 01802 if (!rm_base) 01803 return (0); 01804 01805 #else 01806 pktq_init (&_pkt_inf->pkt_queue, 01807 sizeof(_pkt_inf->rx_buf[0]), /* RX_SIZE */ 01808 DIM(_pkt_inf->rx_buf), /* RX_BUFS */ 01809 (char*)&_pkt_inf->rx_buf); 01810 #endif 01811 01812 #if (DOSX & DOS4GW) && !defined(USE_FAST_PKT) 01813 _pkt_inf->pkt_queue.dos_ofs = offsetof (struct pkt_info, rx_buf[0]); 01814 #elif (DOSX & DJGPP) 01815 _pkt_inf->dos_ds = _dos_ds; 01816 #endif 01817 01818 #if (DOSX & DJGPP) 01819 if (pkt_use_near) 01820 { 01821 if (!(_crt0_startup_flags & _CRT0_FLAG_NEARPTR)) 01822 TCP_CONSOLE_MSG (1, ("Near-pointers not enabled\n")); 01823 else 01824 { 01825 _pkt_inf->use_near_ptr = TRUE; 01826 TCP_CONSOLE_MSG (1, ("Near-pointers enabled\n")); 01827 } 01828 } 01829 else if (_crt0_startup_flags & _CRT0_FLAG_NEARPTR) 01830 TCP_CONSOLE_MSG (1, ("Near-pointers on, but \"PKT.NEAR_PTR = 0\"\n")); 01831 #endif 01832 01833 return (1); 01834 } 01835 01836 01840 static void get_rmode_data (void *dest, unsigned size, WORD seg, WORD ofs) 01841 { 01842 #if (DOSX & (PHARLAP|X32VM|POWERPAK)) 01843 REALPTR rp; 01844 RP_SET (rp, ofs, seg); 01845 ReadRealMem (dest, rp, size); 01846 01847 #elif (DOSX & DOS4GW) 01848 memcpy (dest, SEG_OFS_TO_LIN(seg,ofs), size); 01849 01850 #elif (DOSX & DJGPP) 01851 dosmemget (ofs + (seg << 4), size, dest); 01852 01853 #else 01854 _fmemcpy (dest, MK_FP(seg,ofs), size); 01855 #endif 01856 } 01857 01858 01866 static BOOL pkt_api_entry (IREGS *reg, unsigned line) 01867 { 01868 _pkt_errno = 0; 01869 reg->r_flags = 0; 01870 01871 #if (DOSX) 01872 01874 if (_pkt32_drvr) 01875 { 01876 if (!(*_pkt32_drvr)(reg)) /* call the pmode interface */ 01877 { 01878 /* _pkt_errno should be set above */ 01879 reg->r_flags |= CARRY_BIT; 01880 return (FALSE); 01881 } 01882 return (TRUE); 01883 } 01884 #endif 01885 01886 if (!pkt_interrupt) 01887 { 01888 #if defined(USE_DEBUG) 01889 fprintf (stderr, "%s (%d): API called after deinit.\n", __FILE__, line); 01890 #endif 01891 reg->r_flags |= CARRY_BIT; 01892 ARGSUSED (line); 01893 _pkt_errno = PDERR_BAD_COMMAND; 01894 return (FALSE); 01895 } 01896 01897 /* Use the 16-bit real-mode PKTDRVR API. 01898 */ 01899 GEN_INTERRUPT (pkt_interrupt, reg); 01900 01901 if (reg->r_flags & CARRY_BIT) 01902 { 01903 _pkt_errno = hiBYTE (reg->r_dx); /* DH has error-code */ 01904 return (FALSE); 01905 } 01906 return (TRUE); 01907 } 01908 01909 01924 int pkt_set_rcv_mode (int mode) 01925 { 01926 IREGS regs; 01927 01928 if (!_pkt_inf) 01929 { 01930 _pkt_errno = PDERR_BAD_HANDLE; 01931 return (0); 01932 } 01933 01934 regs.r_ax = PD_SET_RCV; 01935 regs.r_bx = _pkt_inf->handle; 01936 regs.r_cx = mode; 01937 01938 /* This needs an Extended driver. SLIP/PPP is point-to-point. 01939 */ 01940 if (_pktdevlevel < 2 || _pktserial) 01941 { 01942 _pkt_errno = PDERR_CANT_SET; 01943 return (0); 01944 } 01945 01946 if (!PKT_API(&regs)) 01947 { 01948 PKT_ERR ("Error setting receiver mode: ", _pkt_errno); 01949 return (0); 01950 } 01951 _pkt_rxmode = mode; 01952 return (1); 01953 } 01954 01968 int pkt_get_rcv_mode (void) 01969 { 01970 IREGS regs; 01971 01972 ASSERT_PKT_INF (-1); 01973 01974 regs.r_ax = PD_GET_RCV; 01975 regs.r_bx = _pkt_inf->handle; 01976 01977 /* This needs an Extended driver (not SLIP/PPP) 01978 */ 01979 if (_pktdevlevel < 2 || _pktserial) 01980 { 01981 _pkt_errno = PDERR_BAD_COMMAND; 01982 return (0); 01983 } 01984 01985 if (!PKT_API(&regs)) 01986 { 01987 PKT_ERR ("Error getting receive mode: ", _pkt_errno); 01988 return (0); 01989 } 01990 _pkt_rxmode = regs.r_ax; 01991 return (regs.r_ax); 01992 } 01993 01994 01995 #if defined(USE_MULTICAST) 01996 02006 int pkt_get_multicast_list (mac_address *listbuf, int *lenp) 02007 { 02008 IREGS regs; 02009 int len = *lenp; 02010 02011 ASSERT_PKT_INF (0); 02012 02013 regs.r_ax = PD_GET_MULTI; 02014 _pkt_errno = PDERR_NO_MULTICAST; 02015 02016 /* Basic drivers don't support multicast 02017 */ 02018 if (_pktdevlevel < 2 || _pktserial || 02019 (got_params && pkt_params.multicast_avail == 0) || 02020 !PKT_API(&regs)) 02021 { 02022 if (debug_on > 0) 02023 PKT_ERR ("Error getting multicast list: ", _pkt_errno); 02024 return (0); 02025 } 02026 02027 if ((WORD)regs.r_cx == 0) /* no MC addresses, okay */ 02028 { 02029 memset (listbuf, 0, len); 02030 *lenp = 0; 02031 return (1); 02032 } 02033 02034 /* move it into the caller's buffer 02035 */ 02036 DISABLE(); 02037 len = min (len, (WORD)regs.r_cx); 02038 get_rmode_data (listbuf, len, regs.r_es, regs.r_di); 02039 *lenp = len; 02040 ENABLE(); 02041 return (1); 02042 } 02043 02053 int pkt_set_multicast_list (const void *listbuf, int len) 02054 { 02055 IREGS regs; 02056 WORD seg, ofs; 02057 02058 ASSERT_PKT_INF (0); 02059 02060 /* Basic drivers don't support multicast 02061 */ 02062 if (_pktdevlevel < 2 || _pktserial || 02063 (got_params && pkt_params.multicast_avail == 0)) /* no point in trying */ 02064 { 02065 _pkt_errno = PDERR_NO_MULTICAST; 02066 return (0); 02067 } 02068 02069 #if (DOSX) 02070 if (len > PKT_TMP_SIZE) 02071 { 02072 _pkt_errno = PDERR_NO_SPACE; 02073 return (0); 02074 } 02075 #endif 02076 02077 DISABLE(); 02078 02079 #if (DOSX & (PHARLAP|X32VM|POWERPAK)) 02080 seg = RP_SEGM(); 02081 ofs = PKT_TMP(); 02082 WriteRealMem (rm_base + PKT_TMP(), (void*)listbuf, len); 02083 02084 #elif (DOSX & DOS4GW) 02085 seg = RP_SEGM(); 02086 ofs = PKT_TMP(); 02087 memcpy ((void*)(rm_base + PKT_TMP()), listbuf, len); 02088 02089 #elif (DOSX & DJGPP) 02090 seg = RP_SEGM(); 02091 ofs = PKT_TMP(); 02092 DOSMEMPUT (listbuf, len, rm_base + PKT_TMP()); 02093 02094 #else 02095 seg = FP_SEG (listbuf); 02096 ofs = FP_OFF (listbuf); 02097 #endif 02098 02099 ENABLE(); 02100 02101 regs.r_ax = PD_SET_MULTI; 02102 regs.r_cx = len; 02103 regs.r_es = seg; 02104 regs.r_di = ofs; 02105 02106 if (!PKT_API(&regs)) 02107 { 02108 if (debug_on > 0) 02109 PKT_ERR ("Error setting multicast list: ", _pkt_errno); 02110 return (0); 02111 } 02112 return (1); 02113 } 02114 #endif /* USE_MULTICAST */ 02115 #endif /* !WIN32 && !_WIN32 */ 02116

Generated on Wed Aug 4 08:55:52 2010 for Watt-32 tcp/ip by doxygen 1.3.8