1 /* $NetBSD: pcap-dos.c,v 1.8 2024/09/02 15:33:37 christos Exp $ */ 2 3 /* 4 * This file is part of DOS-libpcap 5 * Ported to DOS/DOSX by G. Vanem <gvanem@yahoo.no> 6 * 7 * pcap-dos.c: Interface to PKTDRVR, NDIS2 and 32-bit pmode 8 * network drivers. 9 */ 10 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include <string.h> 14 #include <signal.h> 15 #include <float.h> 16 #include <fcntl.h> 17 #include <limits.h> /* for INT_MAX */ 18 #include <io.h> 19 20 #if defined(USE_32BIT_DRIVERS) 21 #include "msdos/pm_drvr/pmdrvr.h" 22 #include "msdos/pm_drvr/pci.h" 23 #include "msdos/pm_drvr/bios32.h" 24 #include "msdos/pm_drvr/module.h" 25 #include "msdos/pm_drvr/3c501.h" 26 #include "msdos/pm_drvr/3c503.h" 27 #include "msdos/pm_drvr/3c509.h" 28 #include "msdos/pm_drvr/3c59x.h" 29 #include "msdos/pm_drvr/3c515.h" 30 #include "msdos/pm_drvr/3c90x.h" 31 #include "msdos/pm_drvr/3c575_cb.h" 32 #include "msdos/pm_drvr/ne.h" 33 #include "msdos/pm_drvr/wd.h" 34 #include "msdos/pm_drvr/accton.h" 35 #include "msdos/pm_drvr/cs89x0.h" 36 #include "msdos/pm_drvr/rtl8139.h" 37 #include "msdos/pm_drvr/ne2k-pci.h" 38 #endif 39 40 #include "pcap.h" 41 #include "pcap-dos.h" 42 #include "pcap-int.h" 43 #include "msdos/pktdrvr.h" 44 45 #ifdef USE_NDIS2 46 #include "msdos/ndis2.h" 47 #endif 48 49 #include <arpa/inet.h> 50 #include <net/if.h> 51 #include <net/if_arp.h> 52 #include <net/if_ether.h> 53 #include <net/if_packe.h> 54 #include <tcp.h> 55 56 #if defined(USE_32BIT_DRIVERS) 57 #define FLUSHK() do { _printk_safe = 1; _printk_flush(); } while (0) 58 #define NDIS_NEXT_DEV &rtl8139_dev 59 60 static char *rx_pool = NULL; 61 static void init_32bit (void); 62 63 static int pktq_init (struct rx_ringbuf *q, int size, int num, char *pool); 64 static int pktq_check (struct rx_ringbuf *q); 65 static int pktq_inc_out (struct rx_ringbuf *q); 66 static int pktq_in_index (struct rx_ringbuf *q) LOCKED_FUNC; 67 static void pktq_clear (struct rx_ringbuf *q) LOCKED_FUNC; 68 69 static struct rx_elem *pktq_in_elem (struct rx_ringbuf *q) LOCKED_FUNC; 70 static struct rx_elem *pktq_out_elem (struct rx_ringbuf *q); 71 72 #else 73 #define FLUSHK() ((void)0) 74 #define NDIS_NEXT_DEV NULL 75 #endif 76 77 /* 78 * Internal variables/functions in Watt-32 79 */ 80 extern WORD _pktdevclass; 81 extern BOOL _eth_is_init; 82 extern int _w32_dynamic_host; 83 extern int _watt_do_exit; 84 extern int _watt_is_init; 85 extern int _w32__bootp_on, _w32__dhcp_on, _w32__rarp_on, _w32__do_mask_req; 86 extern void (*_w32_usr_post_init) (void); 87 extern void (*_w32_print_hook)(); 88 89 extern void dbug_write (const char *); /* Watt-32 lib, pcdbug.c */ 90 extern int pkt_get_mtu (void); 91 92 static int ref_count = 0; 93 94 static u_long mac_count = 0; 95 static u_long filter_count = 0; 96 97 static volatile BOOL exc_occurred = 0; 98 99 static struct device *handle_to_device [20]; 100 101 static int pcap_activate_dos (pcap_t *p); 102 static int pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback, 103 u_char *data); 104 static void pcap_cleanup_dos (pcap_t *p); 105 static int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps); 106 static int pcap_sendpacket_dos (pcap_t *p, const void *buf, size_t len); 107 static int pcap_setfilter_dos (pcap_t *p, struct bpf_program *fp); 108 109 static int ndis_probe (struct device *dev); 110 static int pkt_probe (struct device *dev); 111 112 static void close_driver (void); 113 static int init_watt32 (struct pcap *pcap, const char *dev_name, char *err_buf); 114 static int first_init (const char *name, char *ebuf, int promisc); 115 116 static void watt32_recv_hook (u_char *dummy, const struct pcap_pkthdr *pcap, 117 const u_char *buf); 118 119 /* 120 * These are the device we always support 121 */ 122 static struct device ndis_dev = { 123 "ndis", 124 "NDIS2 LanManager", 125 0, 126 0,0,0,0,0,0, 127 NDIS_NEXT_DEV, /* NULL or a 32-bit device */ 128 ndis_probe 129 }; 130 131 static struct device pkt_dev = { 132 "pkt", 133 "Packet-Driver", 134 0, 135 0,0,0,0,0,0, 136 &ndis_dev, 137 pkt_probe 138 }; 139 140 static struct device *get_device (int fd) 141 { 142 if (fd <= 0 || fd >= sizeof(handle_to_device)/sizeof(handle_to_device[0])) 143 return (NULL); 144 return handle_to_device [fd-1]; 145 } 146 147 /* 148 * Private data for capturing on MS-DOS. 149 */ 150 struct pcap_dos { 151 void (*wait_proc)(void); /* call proc while waiting */ 152 struct pcap_stat stat; 153 }; 154 155 pcap_t *pcap_create_interface (const char *device _U_, char *ebuf) 156 { 157 pcap_t *p; 158 159 p = PCAP_CREATE_COMMON(ebuf, struct pcap_dos); 160 if (p == NULL) 161 return (NULL); 162 163 p->activate_op = pcap_activate_dos; 164 return (p); 165 } 166 167 /* 168 * Open MAC-driver with name 'device_name' for live capture of 169 * network packets. 170 */ 171 static int pcap_activate_dos (pcap_t *pcap) 172 { 173 if (pcap->opt.rfmon) { 174 /* 175 * No monitor mode on DOS. 176 */ 177 return (PCAP_ERROR_RFMON_NOTSUP); 178 } 179 180 /* 181 * Turn a negative snapshot value (invalid), a snapshot value of 182 * 0 (unspecified), or a value bigger than the normal maximum 183 * value, into the maximum allowed value. 184 * 185 * If some application really *needs* a bigger snapshot 186 * length, we should just increase MAXIMUM_SNAPLEN. 187 */ 188 if (pcap->snapshot <= 0 || pcap->snapshot > MAXIMUM_SNAPLEN) 189 pcap->snapshot = MAXIMUM_SNAPLEN; 190 191 if (pcap->snapshot < ETH_MIN+8) 192 pcap->snapshot = ETH_MIN+8; 193 194 if (pcap->snapshot > ETH_MAX) /* silently accept and truncate large MTUs */ 195 pcap->snapshot = ETH_MAX; 196 197 pcap->linktype = DLT_EN10MB; /* !! */ 198 pcap->cleanup_op = pcap_cleanup_dos; 199 pcap->read_op = pcap_read_dos; 200 pcap->stats_op = pcap_stats_dos; 201 pcap->inject_op = pcap_sendpacket_dos; 202 pcap->setfilter_op = pcap_setfilter_dos; 203 pcap->setdirection_op = NULL; /* Not implemented.*/ 204 pcap->fd = ++ref_count; 205 206 pcap->bufsize = ETH_MAX+100; /* add some margin */ 207 pcap->buffer = calloc (pcap->bufsize, 1); 208 209 if (pcap->fd == 1) /* first time we're called */ 210 { 211 if (!init_watt32(pcap, pcap->opt.device, pcap->errbuf) || 212 !first_init(pcap->opt.device, pcap->errbuf, pcap->opt.promisc)) 213 { 214 /* XXX - free pcap->buffer? */ 215 return (PCAP_ERROR); 216 } 217 atexit (close_driver); 218 } 219 else if (stricmp(active_dev->name,pcap->opt.device)) 220 { 221 snprintf (pcap->errbuf, PCAP_ERRBUF_SIZE, 222 "Cannot use different devices simultaneously " 223 "(`%s' vs. `%s')", active_dev->name, pcap->opt.device); 224 /* XXX - free pcap->buffer? */ 225 return (PCAP_ERROR); 226 } 227 handle_to_device [pcap->fd-1] = active_dev; 228 return (0); 229 } 230 231 /* 232 * Poll the receiver queue and call the pcap callback-handler 233 * with the packet. 234 */ 235 static int 236 pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data) 237 { 238 struct pcap_dos *pd = p->priv; 239 struct pcap_pkthdr pcap; 240 struct timeval now, expiry = { 0,0 }; 241 int rx_len = 0; 242 243 if (p->opt.timeout > 0) 244 { 245 gettimeofday2 (&now, NULL); 246 expiry.tv_usec = now.tv_usec + 1000UL * p->opt.timeout; 247 expiry.tv_sec = now.tv_sec; 248 while (expiry.tv_usec >= 1000000L) 249 { 250 expiry.tv_usec -= 1000000L; 251 expiry.tv_sec++; 252 } 253 } 254 255 while (!exc_occurred) 256 { 257 volatile struct device *dev; /* might be reset by sig_handler */ 258 259 dev = get_device (p->fd); 260 if (!dev) 261 break; 262 263 PCAP_ASSERT (dev->copy_rx_buf || dev->peek_rx_buf); 264 FLUSHK(); 265 266 /* If driver has a zero-copy receive facility, peek at the queue, 267 * filter it, do the callback and release the buffer. 268 */ 269 if (dev->peek_rx_buf) 270 { 271 PCAP_ASSERT (dev->release_rx_buf); 272 rx_len = (*dev->peek_rx_buf) (&p->buffer); 273 } 274 else 275 { 276 rx_len = (*dev->copy_rx_buf) (p->buffer, p->snapshot); 277 } 278 279 if (rx_len > 0) /* got a packet */ 280 { 281 mac_count++; 282 283 FLUSHK(); 284 285 pcap.caplen = min (rx_len, p->snapshot); 286 pcap.len = rx_len; 287 288 if (callback && 289 (!p->fcode.bf_insns || pcap_filter(p->fcode.bf_insns, p->buffer, pcap.len, pcap.caplen))) 290 { 291 filter_count++; 292 293 /* Fix-me!! Should be time of arrival. Not time of 294 * capture. 295 */ 296 gettimeofday2 (&pcap.ts, NULL); 297 (*callback) (data, &pcap, p->buffer); 298 } 299 300 if (dev->release_rx_buf) 301 (*dev->release_rx_buf) (p->buffer); 302 303 if (pcap_pkt_debug > 0) 304 { 305 if (callback == watt32_recv_hook) 306 dbug_write ("pcap_recv_hook\n"); 307 else dbug_write ("pcap_read_op\n"); 308 } 309 FLUSHK(); 310 return (1); 311 } 312 313 /* Has "pcap_breakloop()" been called? 314 */ 315 if (p->break_loop) { 316 /* 317 * Yes - clear the flag that indicates that it 318 * has, and return -2 to indicate that we were 319 * told to break out of the loop. 320 */ 321 p->break_loop = 0; 322 return (-2); 323 } 324 325 /* If not to wait for a packet or pcap_cleanup_dos() called from 326 * e.g. SIGINT handler, exit loop now. 327 */ 328 if (p->opt.timeout <= 0 || (volatile int)p->fd <= 0) 329 break; 330 331 gettimeofday2 (&now, NULL); 332 333 if (timercmp(&now, &expiry, >)) 334 break; 335 336 #ifndef DJGPP 337 kbhit(); /* a real CPU hog */ 338 #endif 339 340 if (pd->wait_proc) 341 (*pd->wait_proc)(); /* call yield func */ 342 } 343 344 if (rx_len < 0) /* receive error */ 345 { 346 pd->stat.ps_drop++; 347 #ifdef USE_32BIT_DRIVERS 348 if (pcap_pkt_debug > 1) 349 printk ("pkt-err %s\n", pktInfo.error); 350 #endif 351 return (-1); 352 } 353 return (0); 354 } 355 356 static int 357 pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback, u_char *data) 358 { 359 int rc, num = 0; 360 361 /* 362 * This can conceivably process more than INT_MAX packets, 363 * which would overflow the packet count, causing it either 364 * to look like a negative number, and thus cause us to 365 * return a value that looks like an error, or overflow 366 * back into positive territory, and thus cause us to 367 * return a too-low count. 368 * 369 * Therefore, if the packet count is unlimited, we clip 370 * it at INT_MAX; this routine is not expected to 371 * process packets indefinitely, so that's not an issue. 372 */ 373 if (PACKET_COUNT_IS_UNLIMITED(cnt)) 374 cnt = INT_MAX; 375 376 while (num <= cnt) 377 { 378 if (p->fd <= 0) 379 return (-1); 380 rc = pcap_read_one (p, callback, data); 381 if (rc > 0) 382 num++; 383 if (rc < 0) 384 break; 385 _w32_os_yield(); /* allow SIGINT generation, yield to Win95/NT */ 386 } 387 return (num); 388 } 389 390 /* 391 * Return network statistics 392 */ 393 static int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps) 394 { 395 struct net_device_stats *stats; 396 struct pcap_dos *pd; 397 struct device *dev = p ? get_device(p->fd) : NULL; 398 399 if (!dev) 400 { 401 strcpy (p->errbuf, "illegal pcap handle"); 402 return (-1); 403 } 404 405 if (!dev->get_stats || (stats = (*dev->get_stats)(dev)) == NULL) 406 { 407 strcpy (p->errbuf, "device statistics not available"); 408 return (-1); 409 } 410 411 FLUSHK(); 412 413 pd = p->priv; 414 pd->stat.ps_recv = stats->rx_packets; 415 pd->stat.ps_drop += stats->rx_missed_errors; 416 pd->stat.ps_ifdrop = stats->rx_dropped + /* queue full */ 417 stats->rx_errors; /* HW errors */ 418 if (ps) 419 *ps = pd->stat; 420 421 return (0); 422 } 423 424 /* 425 * Return detailed network/device statistics. 426 * May be called after 'dev->close' is called. 427 */ 428 int pcap_stats_ex (pcap_t *p, struct pcap_stat_ex *se) 429 { 430 struct device *dev = p ? get_device (p->fd) : NULL; 431 432 if (!dev || !dev->get_stats) 433 { 434 pcap_strlcpy (p->errbuf, "detailed device statistics not available", 435 PCAP_ERRBUF_SIZE); 436 return (-1); 437 } 438 439 if (!strnicmp(dev->name,"pkt",3)) 440 { 441 pcap_strlcpy (p->errbuf, "pktdrvr doesn't have detailed statistics", 442 PCAP_ERRBUF_SIZE); 443 return (-1); 444 } 445 memcpy (se, (*dev->get_stats)(dev), sizeof(*se)); 446 return (0); 447 } 448 449 /* 450 * Simply store the filter-code for the pcap_read_dos() callback 451 * Some day the filter-code could be handed down to the active 452 * device (pkt_rx1.s or 32-bit device interrupt handler). 453 */ 454 static int pcap_setfilter_dos (pcap_t *p, struct bpf_program *fp) 455 { 456 if (!p) 457 return (-1); 458 p->fcode = *fp; 459 return (0); 460 } 461 462 /* 463 * Return # of packets received in pcap_read_dos() 464 */ 465 u_long pcap_mac_packets (void) 466 { 467 return (mac_count); 468 } 469 470 /* 471 * Return # of packets passed through filter in pcap_read_dos() 472 */ 473 u_long pcap_filter_packets (void) 474 { 475 return (filter_count); 476 } 477 478 /* 479 * Close pcap device. Not called for offline captures. 480 */ 481 static void pcap_cleanup_dos (pcap_t *p) 482 { 483 struct pcap_dos *pd; 484 485 if (!exc_occurred) 486 { 487 pd = p->priv; 488 if (pcap_stats(p,NULL) < 0) 489 pd->stat.ps_drop = 0; 490 if (!get_device(p->fd)) 491 return; 492 493 handle_to_device [p->fd-1] = NULL; 494 p->fd = 0; 495 if (ref_count > 0) 496 ref_count--; 497 if (ref_count > 0) 498 return; 499 } 500 close_driver(); 501 /* XXX - call pcap_cleanup_live_common? */ 502 } 503 504 /* 505 * Return the name of the 1st network interface, 506 * or NULL if none can be found. 507 */ 508 char *pcap_lookupdev (char *ebuf) 509 { 510 struct device *dev; 511 512 #ifdef USE_32BIT_DRIVERS 513 init_32bit(); 514 #endif 515 516 for (dev = (struct device*)dev_base; dev; dev = dev->next) 517 { 518 PCAP_ASSERT (dev->probe); 519 520 if ((*dev->probe)(dev)) 521 { 522 FLUSHK(); 523 probed_dev = (struct device*) dev; /* remember last probed device */ 524 return (char*) dev->name; 525 } 526 } 527 528 if (ebuf) 529 strcpy (ebuf, "No driver found"); 530 return (NULL); 531 } 532 533 /* 534 * Gets localnet & netmask from Watt-32. 535 */ 536 int pcap_lookupnet (const char *device, bpf_u_int32 *localnet, 537 bpf_u_int32 *netmask, char *errbuf) 538 { 539 DWORD mask, net; 540 541 if (!_watt_is_init) 542 { 543 strcpy (errbuf, "pcap_open_offline() or pcap_activate() must be " 544 "called first"); 545 return (-1); 546 } 547 548 mask = _w32_sin_mask; 549 net = my_ip_addr & mask; 550 if (net == 0) 551 { 552 if (IN_CLASSA(*netmask)) 553 net = IN_CLASSA_NET; 554 else if (IN_CLASSB(*netmask)) 555 net = IN_CLASSB_NET; 556 else if (IN_CLASSC(*netmask)) 557 net = IN_CLASSC_NET; 558 else 559 { 560 snprintf (errbuf, PCAP_ERRBUF_SIZE, "inet class for 0x%lx unknown", mask); 561 return (-1); 562 } 563 } 564 *localnet = htonl (net); 565 *netmask = htonl (mask); 566 567 ARGSUSED (device); 568 return (0); 569 } 570 571 /* 572 * Get a list of all interfaces that are present and that we probe okay. 573 * Returns -1 on error, 0 otherwise. 574 * The list may be NULL empty if no interfaces were up and could be opened. 575 */ 576 int pcap_platform_finddevs (pcap_if_list_t *devlistp, char *errbuf) 577 { 578 struct device *dev; 579 pcap_if_t *curdev; 580 #if 0 /* Pkt drivers should have no addresses */ 581 struct sockaddr_in sa_ll_1, sa_ll_2; 582 struct sockaddr *addr, *netmask, *broadaddr, *dstaddr; 583 #endif 584 int ret = 0; 585 int found = 0; 586 587 for (dev = (struct device*)dev_base; dev; dev = dev->next) 588 { 589 PCAP_ASSERT (dev->probe); 590 591 if (!(*dev->probe)(dev)) 592 continue; 593 594 PCAP_ASSERT (dev->close); /* set by probe routine */ 595 FLUSHK(); 596 (*dev->close) (dev); 597 598 /* 599 * XXX - find out whether it's up or running? Does that apply here? 600 * Can we find out if anything's plugged into the adapter, if it's 601 * a wired device, and set PCAP_IF_CONNECTION_STATUS_CONNECTED 602 * or PCAP_IF_CONNECTION_STATUS_DISCONNECTED? 603 */ 604 if ((curdev = pcap_add_dev(devlistp, dev->name, 0, 605 dev->long_name, errbuf)) == NULL) 606 { 607 ret = -1; 608 break; 609 } 610 found = 1; 611 #if 0 /* Pkt drivers should have no addresses */ 612 memset (&sa_ll_1, 0, sizeof(sa_ll_1)); 613 memset (&sa_ll_2, 0, sizeof(sa_ll_2)); 614 sa_ll_1.sin_family = AF_INET; 615 sa_ll_2.sin_family = AF_INET; 616 617 addr = (struct sockaddr*) &sa_ll_1; 618 netmask = (struct sockaddr*) &sa_ll_1; 619 dstaddr = (struct sockaddr*) &sa_ll_1; 620 broadaddr = (struct sockaddr*) &sa_ll_2; 621 memset (&sa_ll_2.sin_addr, 0xFF, sizeof(sa_ll_2.sin_addr)); 622 623 if (pcap_add_addr_to_dev(curdev, addr, sizeof(*addr), 624 netmask, sizeof(*netmask), 625 broadaddr, sizeof(*broadaddr), 626 dstaddr, sizeof(*dstaddr), errbuf) < 0) 627 { 628 ret = -1; 629 break; 630 } 631 #endif 632 } 633 634 if (ret == 0 && !found) 635 strcpy (errbuf, "No drivers found"); 636 637 return (ret); 638 } 639 640 /* 641 * pcap_assert() is mainly used for debugging 642 */ 643 void pcap_assert (const char *what, const char *file, unsigned line) 644 { 645 FLUSHK(); 646 fprintf (stderr, "%s (%u): Assertion \"%s\" failed\n", 647 file, line, what); 648 close_driver(); 649 _exit (-1); 650 } 651 652 /* 653 * For pcap_offline_read(): wait and yield between printing packets 654 * to simulate the pace packets where actually recorded. 655 */ 656 void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait) 657 { 658 if (p) 659 { 660 struct pcap_dos *pd = p->priv; 661 662 pd->wait_proc = yield; 663 p->opt.timeout = wait; 664 } 665 } 666 667 /* 668 * Initialize a named network device. 669 */ 670 static struct device * 671 open_driver (const char *dev_name, char *ebuf, int promisc) 672 { 673 struct device *dev; 674 675 for (dev = (struct device*)dev_base; dev; dev = dev->next) 676 { 677 PCAP_ASSERT (dev->name); 678 679 if (strcmp (dev_name,dev->name)) 680 continue; 681 682 if (!probed_dev) /* user didn't call pcap_lookupdev() first */ 683 { 684 PCAP_ASSERT (dev->probe); 685 686 if (!(*dev->probe)(dev)) /* call the xx_probe() function */ 687 { 688 snprintf (ebuf, PCAP_ERRBUF_SIZE, "failed to detect device `%s'", dev_name); 689 return (NULL); 690 } 691 probed_dev = dev; /* device is probed okay and may be used */ 692 } 693 else if (dev != probed_dev) 694 { 695 goto not_probed; 696 } 697 698 FLUSHK(); 699 700 /* Select what traffic to receive 701 */ 702 if (promisc) 703 dev->flags |= (IFF_ALLMULTI | IFF_PROMISC); 704 else dev->flags &= ~(IFF_ALLMULTI | IFF_PROMISC); 705 706 PCAP_ASSERT (dev->open); 707 708 if (!(*dev->open)(dev)) 709 { 710 snprintf (ebuf, PCAP_ERRBUF_SIZE, "failed to activate device `%s'", dev_name); 711 if (pktInfo.error && !strncmp(dev->name,"pkt",3)) 712 { 713 strcat (ebuf, ": "); 714 strcat (ebuf, pktInfo.error); 715 } 716 return (NULL); 717 } 718 719 /* Some devices need this to operate in promiscuous mode 720 */ 721 if (promisc && dev->set_multicast_list) 722 (*dev->set_multicast_list) (dev); 723 724 active_dev = dev; /* remember our active device */ 725 break; 726 } 727 728 /* 'dev_name' not matched in 'dev_base' list. 729 */ 730 if (!dev) 731 { 732 snprintf (ebuf, PCAP_ERRBUF_SIZE, "device `%s' not supported", dev_name); 733 return (NULL); 734 } 735 736 not_probed: 737 if (!probed_dev) 738 { 739 snprintf (ebuf, PCAP_ERRBUF_SIZE, "device `%s' not probed", dev_name); 740 return (NULL); 741 } 742 return (dev); 743 } 744 745 /* 746 * Deinitialize MAC driver. 747 * Set receive mode back to default mode. 748 */ 749 static void close_driver (void) 750 { 751 /* !!todo: loop over all 'handle_to_device[]' ? */ 752 struct device *dev = active_dev; 753 754 if (dev && dev->close) 755 { 756 (*dev->close) (dev); 757 FLUSHK(); 758 } 759 760 active_dev = NULL; 761 762 #ifdef USE_32BIT_DRIVERS 763 if (rx_pool) 764 { 765 k_free (rx_pool); 766 rx_pool = NULL; 767 } 768 if (dev) 769 pcibios_exit(); 770 #endif 771 } 772 773 774 #ifdef __DJGPP__ 775 static void setup_signals (void (*handler)(int)) 776 { 777 signal (SIGSEGV,handler); 778 signal (SIGILL, handler); 779 signal (SIGFPE, handler); 780 } 781 782 static void exc_handler (int sig) 783 { 784 #ifdef USE_32BIT_DRIVERS 785 if (active_dev->irq > 0) /* excludes IRQ 0 */ 786 { 787 disable_irq (active_dev->irq); 788 irq_eoi_cmd (active_dev->irq); 789 _printk_safe = 1; 790 } 791 #endif 792 793 switch (sig) 794 { 795 case SIGSEGV: 796 fputs ("Catching SIGSEGV.\n", stderr); 797 break; 798 case SIGILL: 799 fputs ("Catching SIGILL.\n", stderr); 800 break; 801 case SIGFPE: 802 _fpreset(); 803 fputs ("Catching SIGFPE.\n", stderr); 804 break; 805 default: 806 fprintf (stderr, "Catching signal %d.\n", sig); 807 } 808 exc_occurred = 1; 809 close_driver(); 810 } 811 #endif /* __DJGPP__ */ 812 813 814 /* 815 * Open the pcap device for the first client calling pcap_activate() 816 */ 817 static int first_init (const char *name, char *ebuf, int promisc) 818 { 819 struct device *dev; 820 821 #ifdef USE_32BIT_DRIVERS 822 rx_pool = k_calloc (RECEIVE_BUF_SIZE, RECEIVE_QUEUE_SIZE); 823 if (!rx_pool) 824 { 825 strcpy (ebuf, "Not enough memory (Rx pool)"); 826 return (0); 827 } 828 #endif 829 830 #ifdef __DJGPP__ 831 setup_signals (exc_handler); 832 #endif 833 834 #ifdef USE_32BIT_DRIVERS 835 init_32bit(); 836 #endif 837 838 dev = open_driver (name, ebuf, promisc); 839 if (!dev) 840 { 841 #ifdef USE_32BIT_DRIVERS 842 k_free (rx_pool); 843 rx_pool = NULL; 844 #endif 845 846 #ifdef __DJGPP__ 847 setup_signals (SIG_DFL); 848 #endif 849 return (0); 850 } 851 852 #ifdef USE_32BIT_DRIVERS 853 /* 854 * If driver is NOT a 16-bit "pkt/ndis" driver (having a 'copy_rx_buf' 855 * set in it's probe handler), initialize near-memory ring-buffer for 856 * the 32-bit device. 857 */ 858 if (dev->copy_rx_buf == NULL) 859 { 860 dev->get_rx_buf = get_rxbuf; 861 dev->peek_rx_buf = peek_rxbuf; 862 dev->release_rx_buf = release_rxbuf; 863 pktq_init (&dev->queue, RECEIVE_BUF_SIZE, RECEIVE_QUEUE_SIZE, rx_pool); 864 } 865 #endif 866 return (1); 867 } 868 869 #ifdef USE_32BIT_DRIVERS 870 static void init_32bit (void) 871 { 872 static int init_pci = 0; 873 874 if (!_printk_file) 875 _printk_init (64*1024, NULL); /* calls atexit(printk_exit) */ 876 877 if (!init_pci) 878 (void)pci_init(); /* init BIOS32+PCI interface */ 879 init_pci = 1; 880 } 881 #endif 882 883 884 /* 885 * Hook functions for using Watt-32 together with pcap 886 */ 887 static char rxbuf [ETH_MAX+100]; /* rx-buffer with some margin */ 888 static WORD etype; 889 static pcap_t pcap_save; 890 891 static void watt32_recv_hook (u_char *dummy, const struct pcap_pkthdr *pcap, 892 const u_char *buf) 893 { 894 /* Fix me: assumes Ethernet II only */ 895 struct ether_header *ep = (struct ether_header*) buf; 896 897 memcpy (rxbuf, buf, pcap->caplen); 898 etype = ep->ether_type; 899 ARGSUSED (dummy); 900 } 901 902 #if (WATTCP_VER >= 0x0224) 903 /* 904 * This function is used by Watt-32 to poll for a packet. 905 * i.e. it's set to bypass _eth_arrived() 906 */ 907 static void *pcap_recv_hook (WORD *type) 908 { 909 int len = pcap_read_dos (&pcap_save, 1, watt32_recv_hook, NULL); 910 911 if (len < 0) 912 return (NULL); 913 914 *type = etype; 915 return (void*) &rxbuf; 916 } 917 918 /* 919 * This function is called by Watt-32 (via _eth_xmit_hook). 920 * If dbug_init() was called, we should trace packets sent. 921 */ 922 static int pcap_xmit_hook (const void *buf, unsigned len) 923 { 924 int rc = 0; 925 926 if (pcap_pkt_debug > 0) 927 dbug_write ("pcap_xmit_hook: "); 928 929 if (active_dev && active_dev->xmit) 930 if ((*active_dev->xmit) (active_dev, buf, len) > 0) 931 rc = len; 932 933 if (pcap_pkt_debug > 0) 934 dbug_write (rc ? "ok\n" : "fail\n"); 935 return (rc); 936 } 937 #endif 938 939 static int pcap_sendpacket_dos (pcap_t *p, const void *buf, size_t len) 940 { 941 struct device *dev = p ? get_device(p->fd) : NULL; 942 943 if (!dev || !dev->xmit) 944 return (-1); 945 return (*dev->xmit) (dev, buf, len); 946 } 947 948 /* 949 * This function is called by Watt-32 in tcp_post_init(). 950 * We should prevent Watt-32 from using BOOTP/DHCP/RARP etc. 951 */ 952 static void (*prev_post_hook) (void); 953 954 static void pcap_init_hook (void) 955 { 956 _w32__bootp_on = _w32__dhcp_on = _w32__rarp_on = 0; 957 _w32__do_mask_req = 0; 958 _w32_dynamic_host = 0; 959 if (prev_post_hook) 960 (*prev_post_hook)(); 961 } 962 963 /* 964 * Suppress PRINT message from Watt-32's sock_init() 965 */ 966 static void null_print (void) {} 967 968 /* 969 * To use features of Watt-32 (netdb functions and socket etc.) 970 * we must call sock_init(). But we set various hooks to prevent 971 * using normal PKTDRVR functions in pcpkt.c. This should hopefully 972 * make Watt-32 and pcap co-operate. 973 */ 974 static int init_watt32 (struct pcap *pcap, const char *dev_name, char *err_buf) 975 { 976 char *env; 977 int rc, MTU, has_ip_addr; 978 int using_pktdrv = 1; 979 980 /* If user called sock_init() first, we need to reinit in 981 * order to open debug/trace-file properly 982 */ 983 if (_watt_is_init) 984 sock_exit(); 985 986 env = getenv ("PCAP_TRACE"); 987 if (env && atoi(env) > 0 && 988 pcap_pkt_debug < 0) /* if not already set */ 989 { 990 dbug_init(); 991 pcap_pkt_debug = atoi (env); 992 } 993 994 _watt_do_exit = 0; /* prevent sock_init() calling exit() */ 995 prev_post_hook = _w32_usr_post_init; 996 _w32_usr_post_init = pcap_init_hook; 997 _w32_print_hook = null_print; 998 999 if (dev_name && strncmp(dev_name,"pkt",3)) 1000 using_pktdrv = FALSE; 1001 1002 rc = sock_init(); 1003 has_ip_addr = (rc != 8); /* IP-address assignment failed */ 1004 1005 /* if pcap is using a 32-bit driver w/o a pktdrvr loaded, we 1006 * just pretend Watt-32 is initialized okay. 1007 * 1008 * !! fix-me: The Watt-32 config isn't done if no pktdrvr 1009 * was found. In that case my_ip_addr + sin_mask 1010 * have default values. Should be taken from another 1011 * ini-file/environment in any case (ref. tcpdump.ini) 1012 */ 1013 _watt_is_init = 1; 1014 1015 if (!using_pktdrv || !has_ip_addr) /* for now .... */ 1016 { 1017 static const char myip[] = "192.168.0.1"; 1018 static const char mask[] = "255.255.255.0"; 1019 1020 printf ("Just guessing, using IP %s and netmask %s\n", myip, mask); 1021 my_ip_addr = aton (myip); 1022 _w32_sin_mask = aton (mask); 1023 } 1024 else if (rc && using_pktdrv) 1025 { 1026 snprintf (err_buf, PCAP_ERRBUF_SIZE, "sock_init() failed, code %d", rc); 1027 return (0); 1028 } 1029 1030 /* Set recv-hook for peeking in _eth_arrived(). 1031 */ 1032 #if (WATTCP_VER >= 0x0224) 1033 _eth_recv_hook = pcap_recv_hook; 1034 _eth_xmit_hook = pcap_xmit_hook; 1035 #endif 1036 1037 /* Free the pkt-drvr handle allocated in pkt_init(). 1038 * The above hooks should thus use the handle reopened in open_driver() 1039 */ 1040 if (using_pktdrv) 1041 { 1042 _eth_release(); 1043 /* _eth_is_init = 1; */ /* hack to get Rx/Tx-hooks in Watt-32 working */ 1044 } 1045 1046 memcpy (&pcap_save, pcap, sizeof(pcap_save)); 1047 MTU = pkt_get_mtu(); 1048 pcap_save.fcode.bf_insns = NULL; 1049 pcap_save.linktype = _eth_get_hwtype (NULL, NULL); 1050 pcap_save.snapshot = MTU > 0 ? MTU : ETH_MAX; /* assume 1514 */ 1051 1052 /* prevent use of resolve() and resolve_ip() 1053 */ 1054 last_nameserver = 0; 1055 return (1); 1056 } 1057 1058 int EISA_bus = 0; /* Where is natural place for this? */ 1059 1060 /* 1061 * Application config hooks to set various driver parameters. 1062 */ 1063 1064 static const struct config_table debug_tab[] = { 1065 { "PKT.DEBUG", ARG_ATOI, &pcap_pkt_debug }, 1066 { "PKT.VECTOR", ARG_ATOX_W, NULL }, 1067 { "NDIS.DEBUG", ARG_ATOI, NULL }, 1068 #ifdef USE_32BIT_DRIVERS 1069 { "3C503.DEBUG", ARG_ATOI, &ei_debug }, 1070 { "3C503.IO_BASE", ARG_ATOX_W, &el2_dev.base_addr }, 1071 { "3C503.MEMORY", ARG_ATOX_W, &el2_dev.mem_start }, 1072 { "3C503.IRQ", ARG_ATOI, &el2_dev.irq }, 1073 { "3C505.DEBUG", ARG_ATOI, NULL }, 1074 { "3C505.BASE", ARG_ATOX_W, NULL }, 1075 { "3C507.DEBUG", ARG_ATOI, NULL }, 1076 { "3C509.DEBUG", ARG_ATOI, &el3_debug }, 1077 { "3C509.ILOOP", ARG_ATOI, &el3_max_loop }, 1078 { "3C529.DEBUG", ARG_ATOI, NULL }, 1079 { "3C575.DEBUG", ARG_ATOI, &debug_3c575 }, 1080 { "3C59X.DEBUG", ARG_ATOI, &vortex_debug }, 1081 { "3C59X.IFACE0", ARG_ATOI, &vortex_options[0] }, 1082 { "3C59X.IFACE1", ARG_ATOI, &vortex_options[1] }, 1083 { "3C59X.IFACE2", ARG_ATOI, &vortex_options[2] }, 1084 { "3C59X.IFACE3", ARG_ATOI, &vortex_options[3] }, 1085 { "3C90X.DEBUG", ARG_ATOX_W, &tc90xbc_debug }, 1086 { "ACCT.DEBUG", ARG_ATOI, ðpk_debug }, 1087 { "CS89.DEBUG", ARG_ATOI, &cs89_debug }, 1088 { "RTL8139.DEBUG", ARG_ATOI, &rtl8139_debug }, 1089 /* { "RTL8139.FDUPLEX", ARG_ATOI, &rtl8139_options }, */ 1090 { "SMC.DEBUG", ARG_ATOI, &ei_debug }, 1091 /* { "E100.DEBUG", ARG_ATOI, &e100_debug }, */ 1092 { "PCI.DEBUG", ARG_ATOI, &pci_debug }, 1093 { "BIOS32.DEBUG", ARG_ATOI, &bios32_debug }, 1094 { "IRQ.DEBUG", ARG_ATOI, &irq_debug }, 1095 { "TIMER.IRQ", ARG_ATOI, &timer_irq }, 1096 #endif 1097 { NULL } 1098 }; 1099 1100 /* 1101 * pcap_config_hook() is an extension to application's config 1102 * handling. Uses Watt-32's config-table function. 1103 */ 1104 int pcap_config_hook (const char *keyword, const char *value) 1105 { 1106 return parse_config_table (debug_tab, NULL, keyword, value); 1107 } 1108 1109 /* 1110 * Linked list of supported devices 1111 */ 1112 struct device *active_dev = NULL; /* the device we have opened */ 1113 struct device *probed_dev = NULL; /* the device we have probed */ 1114 const struct device *dev_base = &pkt_dev; /* list of network devices */ 1115 1116 /* 1117 * PKTDRVR device functions 1118 */ 1119 int pcap_pkt_debug = -1; 1120 1121 static void pkt_close (struct device *dev) 1122 { 1123 BOOL okay = PktExitDriver(); 1124 1125 if (pcap_pkt_debug > 1) 1126 fprintf (stderr, "pkt_close(): %d\n", okay); 1127 1128 if (dev->priv) 1129 free (dev->priv); 1130 dev->priv = NULL; 1131 } 1132 1133 static int pkt_open (struct device *dev) 1134 { 1135 PKT_RX_MODE mode; 1136 1137 if (dev->flags & IFF_PROMISC) 1138 mode = PDRX_ALL_PACKETS; 1139 else mode = PDRX_BROADCAST; 1140 1141 if (!PktInitDriver(mode)) 1142 return (0); 1143 1144 PktResetStatistics (pktInfo.handle); 1145 PktQueueBusy (FALSE); 1146 return (1); 1147 } 1148 1149 static int pkt_xmit (struct device *dev, const void *buf, int len) 1150 { 1151 struct net_device_stats *stats = (struct net_device_stats*) dev->priv; 1152 1153 if (pcap_pkt_debug > 0) 1154 dbug_write ("pcap_xmit\n"); 1155 1156 if (!PktTransmit(buf,len)) 1157 { 1158 stats->tx_errors++; 1159 return (0); 1160 } 1161 return (len); 1162 } 1163 1164 static void *pkt_stats (struct device *dev) 1165 { 1166 struct net_device_stats *stats = (struct net_device_stats*) dev->priv; 1167 1168 if (!stats || !PktSessStatistics(pktInfo.handle)) 1169 return (NULL); 1170 1171 stats->rx_packets = pktStat.inPackets; 1172 stats->rx_errors = pktStat.lost; 1173 stats->rx_missed_errors = PktRxDropped(); 1174 return (stats); 1175 } 1176 1177 static int pkt_probe (struct device *dev) 1178 { 1179 if (!PktSearchDriver()) 1180 return (0); 1181 1182 dev->open = pkt_open; 1183 dev->xmit = pkt_xmit; 1184 dev->close = pkt_close; 1185 dev->get_stats = pkt_stats; 1186 dev->copy_rx_buf = PktReceive; /* farmem peek and copy routine */ 1187 dev->get_rx_buf = NULL; 1188 dev->peek_rx_buf = NULL; 1189 dev->release_rx_buf = NULL; 1190 dev->priv = calloc (sizeof(struct net_device_stats), 1); 1191 if (!dev->priv) 1192 return (0); 1193 return (1); 1194 } 1195 1196 /* 1197 * NDIS device functions 1198 */ 1199 static void ndis_close (struct device *dev) 1200 { 1201 #ifdef USE_NDIS2 1202 NdisShutdown(); 1203 #endif 1204 ARGSUSED (dev); 1205 } 1206 1207 static int ndis_open (struct device *dev) 1208 { 1209 int promisc = (dev->flags & IFF_PROMISC); 1210 1211 #ifdef USE_NDIS2 1212 if (!NdisInit(promisc)) 1213 return (0); 1214 return (1); 1215 #else 1216 ARGSUSED (promisc); 1217 return (0); 1218 #endif 1219 } 1220 1221 static void *ndis_stats (struct device *dev) 1222 { 1223 static struct net_device_stats stats; 1224 1225 /* to-do */ 1226 ARGSUSED (dev); 1227 return (&stats); 1228 } 1229 1230 static int ndis_probe (struct device *dev) 1231 { 1232 #ifdef USE_NDIS2 1233 if (!NdisOpen()) 1234 return (0); 1235 #endif 1236 1237 dev->open = ndis_open; 1238 dev->xmit = NULL; 1239 dev->close = ndis_close; 1240 dev->get_stats = ndis_stats; 1241 dev->copy_rx_buf = NULL; /* to-do */ 1242 dev->get_rx_buf = NULL; /* upcall is from rmode driver */ 1243 dev->peek_rx_buf = NULL; 1244 dev->release_rx_buf = NULL; 1245 return (0); 1246 } 1247 1248 /* 1249 * Search & probe for supported 32-bit (pmode) pcap devices 1250 */ 1251 #if defined(USE_32BIT_DRIVERS) 1252 1253 struct device el2_dev LOCKED_VAR = { 1254 "3c503", 1255 "EtherLink II", 1256 0, 1257 0,0,0,0,0,0, 1258 NULL, 1259 el2_probe 1260 }; 1261 1262 struct device el3_dev LOCKED_VAR = { 1263 "3c509", 1264 "EtherLink III", 1265 0, 1266 0,0,0,0,0,0, 1267 &el2_dev, 1268 el3_probe 1269 }; 1270 1271 struct device tc515_dev LOCKED_VAR = { 1272 "3c515", 1273 "EtherLink PCI", 1274 0, 1275 0,0,0,0,0,0, 1276 &el3_dev, 1277 tc515_probe 1278 }; 1279 1280 struct device tc59_dev LOCKED_VAR = { 1281 "3c59x", 1282 "EtherLink PCI", 1283 0, 1284 0,0,0,0,0,0, 1285 &tc515_dev, 1286 tc59x_probe 1287 }; 1288 1289 struct device tc90xbc_dev LOCKED_VAR = { 1290 "3c90x", 1291 "EtherLink 90X", 1292 0, 1293 0,0,0,0,0,0, 1294 &tc59_dev, 1295 tc90xbc_probe 1296 }; 1297 1298 struct device wd_dev LOCKED_VAR = { 1299 "wd", 1300 "Western Digital", 1301 0, 1302 0,0,0,0,0,0, 1303 &tc90xbc_dev, 1304 wd_probe 1305 }; 1306 1307 struct device ne_dev LOCKED_VAR = { 1308 "ne", 1309 "NEx000", 1310 0, 1311 0,0,0,0,0,0, 1312 &wd_dev, 1313 ne_probe 1314 }; 1315 1316 struct device acct_dev LOCKED_VAR = { 1317 "acct", 1318 "Accton EtherPocket", 1319 0, 1320 0,0,0,0,0,0, 1321 &ne_dev, 1322 ethpk_probe 1323 }; 1324 1325 struct device cs89_dev LOCKED_VAR = { 1326 "cs89", 1327 "Crystal Semiconductor", 1328 0, 1329 0,0,0,0,0,0, 1330 &acct_dev, 1331 cs89x0_probe 1332 }; 1333 1334 struct device rtl8139_dev LOCKED_VAR = { 1335 "rtl8139", 1336 "RealTek PCI", 1337 0, 1338 0,0,0,0,0,0, 1339 &cs89_dev, 1340 rtl8139_probe /* dev->probe routine */ 1341 }; 1342 1343 /* 1344 * Dequeue routine is called by polling. 1345 * NOTE: the queue-element is not copied, only a pointer is 1346 * returned at '*buf' 1347 */ 1348 int peek_rxbuf (BYTE **buf) 1349 { 1350 struct rx_elem *tail, *head; 1351 1352 PCAP_ASSERT (pktq_check (&active_dev->queue)); 1353 1354 DISABLE(); 1355 tail = pktq_out_elem (&active_dev->queue); 1356 head = pktq_in_elem (&active_dev->queue); 1357 ENABLE(); 1358 1359 if (head != tail) 1360 { 1361 PCAP_ASSERT (tail->size < active_dev->queue.elem_size-4-2); 1362 1363 *buf = &tail->data[0]; 1364 return (tail->size); 1365 } 1366 *buf = NULL; 1367 return (0); 1368 } 1369 1370 /* 1371 * Release buffer we peeked at above. 1372 */ 1373 int release_rxbuf (BYTE *buf) 1374 { 1375 #ifndef NDEBUG 1376 struct rx_elem *tail = pktq_out_elem (&active_dev->queue); 1377 1378 PCAP_ASSERT (&tail->data[0] == buf); 1379 #else 1380 ARGSUSED (buf); 1381 #endif 1382 pktq_inc_out (&active_dev->queue); 1383 return (1); 1384 } 1385 1386 /* 1387 * get_rxbuf() routine (in locked code) is called from IRQ handler 1388 * to request a buffer. Interrupts are disabled and we have a 32kB stack. 1389 */ 1390 BYTE *get_rxbuf (int len) 1391 { 1392 int idx; 1393 1394 if (len < ETH_MIN || len > ETH_MAX) 1395 return (NULL); 1396 1397 idx = pktq_in_index (&active_dev->queue); 1398 1399 #ifdef DEBUG 1400 { 1401 static int fan_idx LOCKED_VAR = 0; 1402 writew ("-\\|/"[fan_idx++] | (15 << 8), /* white on black colour */ 1403 0xB8000 + 2*79); /* upper-right corner, 80-col colour screen */ 1404 fan_idx &= 3; 1405 } 1406 /* writew (idx + '0' + 0x0F00, 0xB8000 + 2*78); */ 1407 #endif 1408 1409 if (idx != active_dev->queue.out_index) 1410 { 1411 struct rx_elem *head = pktq_in_elem (&active_dev->queue); 1412 1413 head->size = len; 1414 active_dev->queue.in_index = idx; 1415 return (&head->data[0]); 1416 } 1417 1418 /* !!to-do: drop 25% of the oldest element 1419 */ 1420 pktq_clear (&active_dev->queue); 1421 return (NULL); 1422 } 1423 1424 /* 1425 * Simple ring-buffer queue handler for reception of packets 1426 * from network driver. 1427 */ 1428 #define PKTQ_MARKER 0xDEADBEEF 1429 1430 static int pktq_check (struct rx_ringbuf *q) 1431 { 1432 #ifndef NDEBUG 1433 int i; 1434 char *buf; 1435 #endif 1436 1437 if (!q || !q->num_elem || !q->buf_start) 1438 return (0); 1439 1440 #ifndef NDEBUG 1441 buf = q->buf_start; 1442 1443 for (i = 0; i < q->num_elem; i++) 1444 { 1445 buf += q->elem_size; 1446 if (*(DWORD*)(buf - sizeof(DWORD)) != PKTQ_MARKER) 1447 return (0); 1448 } 1449 #endif 1450 return (1); 1451 } 1452 1453 static int pktq_init (struct rx_ringbuf *q, int size, int num, char *pool) 1454 { 1455 int i; 1456 1457 q->elem_size = size; 1458 q->num_elem = num; 1459 q->buf_start = pool; 1460 q->in_index = 0; 1461 q->out_index = 0; 1462 1463 PCAP_ASSERT (size >= sizeof(struct rx_elem) + sizeof(DWORD)); 1464 PCAP_ASSERT (num); 1465 PCAP_ASSERT (pool); 1466 1467 for (i = 0; i < num; i++) 1468 { 1469 #if 0 1470 struct rx_elem *elem = (struct rx_elem*) pool; 1471 1472 /* assert dword aligned elements 1473 */ 1474 PCAP_ASSERT (((unsigned)(&elem->data[0]) & 3) == 0); 1475 #endif 1476 pool += size; 1477 *(DWORD*) (pool - sizeof(DWORD)) = PKTQ_MARKER; 1478 } 1479 return (1); 1480 } 1481 1482 /* 1483 * Increment the queue 'out_index' (tail). 1484 * Check for wraps. 1485 */ 1486 static int pktq_inc_out (struct rx_ringbuf *q) 1487 { 1488 q->out_index++; 1489 if (q->out_index >= q->num_elem) 1490 q->out_index = 0; 1491 return (q->out_index); 1492 } 1493 1494 /* 1495 * Return the queue's next 'in_index' (head). 1496 * Check for wraps. 1497 */ 1498 static int pktq_in_index (struct rx_ringbuf *q) 1499 { 1500 volatile int index = q->in_index + 1; 1501 1502 if (index >= q->num_elem) 1503 index = 0; 1504 return (index); 1505 } 1506 1507 /* 1508 * Return the queue's head-buffer. 1509 */ 1510 static struct rx_elem *pktq_in_elem (struct rx_ringbuf *q) 1511 { 1512 return (struct rx_elem*) (q->buf_start + (q->elem_size * q->in_index)); 1513 } 1514 1515 /* 1516 * Return the queue's tail-buffer. 1517 */ 1518 static struct rx_elem *pktq_out_elem (struct rx_ringbuf *q) 1519 { 1520 return (struct rx_elem*) (q->buf_start + (q->elem_size * q->out_index)); 1521 } 1522 1523 /* 1524 * Clear the queue ring-buffer by setting head=tail. 1525 */ 1526 static void pktq_clear (struct rx_ringbuf *q) 1527 { 1528 q->in_index = q->out_index; 1529 } 1530 1531 /* 1532 * Symbols that must be linkable for "gcc -O0" 1533 */ 1534 #undef __IOPORT_H 1535 #undef __DMA_H 1536 1537 #define extern 1538 #define __inline__ 1539 1540 #include "msdos/pm_drvr/ioport.h" 1541 #include "msdos/pm_drvr/dma.h" 1542 1543 #endif /* USE_32BIT_DRIVERS */ 1544 1545 /* 1546 * Libpcap version string. 1547 */ 1548 const char * 1549 pcap_lib_version(void) 1550 { 1551 return ("DOS-" PCAP_VERSION_STRING); 1552 } 1553