2 * This file is part of DOS-libpcap
3 * Ported to DOS/DOSX by G. Vanem <gvanem@yahoo.no>
5 * pcap-dos.c: Interface to PKTDRVR, NDIS2 and 32-bit pmode
17 #if defined(USE_32BIT_DRIVERS)
18 #include "msdos/pm_drvr/pmdrvr.h"
19 #include "msdos/pm_drvr/pci.h"
20 #include "msdos/pm_drvr/bios32.h"
21 #include "msdos/pm_drvr/module.h"
22 #include "msdos/pm_drvr/3c501.h"
23 #include "msdos/pm_drvr/3c503.h"
24 #include "msdos/pm_drvr/3c509.h"
25 #include "msdos/pm_drvr/3c59x.h"
26 #include "msdos/pm_drvr/3c515.h"
27 #include "msdos/pm_drvr/3c90x.h"
28 #include "msdos/pm_drvr/3c575_cb.h"
29 #include "msdos/pm_drvr/ne.h"
30 #include "msdos/pm_drvr/wd.h"
31 #include "msdos/pm_drvr/accton.h"
32 #include "msdos/pm_drvr/cs89x0.h"
33 #include "msdos/pm_drvr/rtl8139.h"
34 #include "msdos/pm_drvr/ne2k-pci.h"
40 #include "msdos/pktdrvr.h"
43 #include "msdos/ndis2.h"
46 #include <arpa/inet.h>
48 #include <net/if_arp.h>
49 #include <net/if_ether.h>
50 #include <net/if_packe.h>
53 #if defined(USE_32BIT_DRIVERS)
54 #define FLUSHK() do { _printk_safe = 1; _printk_flush(); } while (0)
55 #define NDIS_NEXT_DEV &rtl8139_dev
57 static char *rx_pool = NULL;
58 static void init_32bit (void);
60 static int pktq_init (struct rx_ringbuf *q, int size, int num, char *pool);
61 static int pktq_check (struct rx_ringbuf *q);
62 static int pktq_inc_out (struct rx_ringbuf *q);
63 static int pktq_in_index (struct rx_ringbuf *q) LOCKED_FUNC;
64 static void pktq_clear (struct rx_ringbuf *q) LOCKED_FUNC;
66 static struct rx_elem *pktq_in_elem (struct rx_ringbuf *q) LOCKED_FUNC;
67 static struct rx_elem *pktq_out_elem (struct rx_ringbuf *q);
70 #define FLUSHK() ((void)0)
71 #define NDIS_NEXT_DEV NULL
75 * Internal variables/functions in Watt-32
77 extern WORD _pktdevclass;
78 extern BOOL _eth_is_init;
79 extern int _w32_dynamic_host;
80 extern int _watt_do_exit;
81 extern int _watt_is_init;
82 extern int _w32__bootp_on, _w32__dhcp_on, _w32__rarp_on, _w32__do_mask_req;
83 extern void (*_w32_usr_post_init) (void);
84 extern void (*_w32_print_hook)();
86 extern void dbug_write (const char *); /* Watt-32 lib, pcdbug.c */
87 extern int pkt_get_mtu (void);
89 static int ref_count = 0;
91 static u_long mac_count = 0;
92 static u_long filter_count = 0;
94 static volatile BOOL exc_occured = 0;
96 static struct device *handle_to_device [20];
98 static int pcap_activate_dos (pcap_t *p);
99 static int pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback,
101 static void pcap_cleanup_dos (pcap_t *p);
102 static int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps);
103 static int pcap_sendpacket_dos (pcap_t *p, const void *buf, size_t len);
104 static int pcap_setfilter_dos (pcap_t *p, struct bpf_program *fp);
106 static int ndis_probe (struct device *dev);
107 static int pkt_probe (struct device *dev);
109 static void close_driver (void);
110 static int init_watt32 (struct pcap *pcap, const char *dev_name, char *err_buf);
111 static int first_init (const char *name, char *ebuf, int promisc);
113 static void watt32_recv_hook (u_char *dummy, const struct pcap_pkthdr *pcap,
117 * These are the device we always support
119 static struct device ndis_dev = {
124 NDIS_NEXT_DEV, /* NULL or a 32-bit device */
128 static struct device pkt_dev = {
137 static struct device *get_device (int fd)
139 if (fd <= 0 || fd >= sizeof(handle_to_device)/sizeof(handle_to_device[0]))
141 return handle_to_device [fd-1];
145 * Private data for capturing on MS-DOS.
148 void (*wait_proc)(void); /* call proc while waiting */
149 struct pcap_stat stat;
152 pcap_t *pcap_create_interface (const char *device _U_, char *ebuf)
156 p = pcap_create_common(ebuf, sizeof (struct pcap_dos));
160 p->activate_op = pcap_activate_dos;
165 * Open MAC-driver with name 'device_name' for live capture of
168 static int pcap_activate_dos (pcap_t *pcap)
170 if (pcap->opt.rfmon) {
172 * No monitor mode on DOS.
174 return (PCAP_ERROR_RFMON_NOTSUP);
178 * Turn a negative snapshot value (invalid), a snapshot value of
179 * 0 (unspecified), or a value bigger than the normal maximum
180 * value, into the maximum allowed value.
182 * If some application really *needs* a bigger snapshot
183 * length, we should just increase MAXIMUM_SNAPLEN.
185 if (pcap->snapshot <= 0 || pcap->snapshot > MAXIMUM_SNAPLEN)
186 pcap->snapshot = MAXIMUM_SNAPLEN;
188 if (pcap->snapshot < ETH_MIN+8)
189 pcap->snapshot = ETH_MIN+8;
191 if (pcap->snapshot > ETH_MAX) /* silently accept and truncate large MTUs */
192 pcap->snapshot = ETH_MAX;
194 pcap->linktype = DLT_EN10MB; /* !! */
195 pcap->cleanup_op = pcap_cleanup_dos;
196 pcap->read_op = pcap_read_dos;
197 pcap->stats_op = pcap_stats_dos;
198 pcap->inject_op = pcap_sendpacket_dos;
199 pcap->setfilter_op = pcap_setfilter_dos;
200 pcap->setdirection_op = NULL; /* Not implemented.*/
201 pcap->fd = ++ref_count;
203 pcap->bufsize = ETH_MAX+100; /* add some margin */
204 pcap->buffer = calloc (pcap->bufsize, 1);
206 if (pcap->fd == 1) /* first time we're called */
208 if (!init_watt32(pcap, pcap->opt.device, pcap->errbuf) ||
209 !first_init(pcap->opt.device, pcap->errbuf, pcap->opt.promisc))
211 /* XXX - free pcap->buffer? */
214 atexit (close_driver);
216 else if (stricmp(active_dev->name,pcap->opt.device))
218 pcap_snprintf (pcap->errbuf, PCAP_ERRBUF_SIZE,
219 "Cannot use different devices simultaneously "
220 "(`%s' vs. `%s')", active_dev->name, pcap->opt.device);
221 /* XXX - free pcap->buffer? */
224 handle_to_device [pcap->fd-1] = active_dev;
229 * Poll the receiver queue and call the pcap callback-handler
233 pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data)
235 struct pcap_dos *pd = p->priv;
236 struct pcap_pkthdr pcap;
237 struct timeval now, expiry = { 0,0 };
240 if (p->opt.timeout > 0)
242 gettimeofday2 (&now, NULL);
243 expiry.tv_usec = now.tv_usec + 1000UL * p->opt.timeout;
244 expiry.tv_sec = now.tv_sec;
245 while (expiry.tv_usec >= 1000000L)
247 expiry.tv_usec -= 1000000L;
254 volatile struct device *dev; /* might be reset by sig_handler */
256 dev = get_device (p->fd);
260 PCAP_ASSERT (dev->copy_rx_buf || dev->peek_rx_buf);
263 /* If driver has a zero-copy receive facility, peek at the queue,
264 * filter it, do the callback and release the buffer.
266 if (dev->peek_rx_buf)
268 PCAP_ASSERT (dev->release_rx_buf);
269 rx_len = (*dev->peek_rx_buf) (&p->buffer);
273 rx_len = (*dev->copy_rx_buf) (p->buffer, p->snapshot);
276 if (rx_len > 0) /* got a packet */
282 pcap.caplen = min (rx_len, p->snapshot);
286 (!p->fcode.bf_insns || bpf_filter(p->fcode.bf_insns, p->buffer, pcap.len, pcap.caplen)))
290 /* Fix-me!! Should be time of arrival. Not time of
293 gettimeofday2 (&pcap.ts, NULL);
294 (*callback) (data, &pcap, p->buffer);
297 if (dev->release_rx_buf)
298 (*dev->release_rx_buf) (p->buffer);
300 if (pcap_pkt_debug > 0)
302 if (callback == watt32_recv_hook)
303 dbug_write ("pcap_recv_hook\n");
304 else dbug_write ("pcap_read_op\n");
310 /* Has "pcap_breakloop()" been called?
314 * Yes - clear the flag that indicates that it
315 * has, and return -2 to indicate that we were
316 * told to break out of the loop.
322 /* If not to wait for a packet or pcap_cleanup_dos() called from
323 * e.g. SIGINT handler, exit loop now.
325 if (p->opt.timeout <= 0 || (volatile int)p->fd <= 0)
328 gettimeofday2 (&now, NULL);
330 if (timercmp(&now, &expiry, >))
334 kbhit(); /* a real CPU hog */
338 (*pd->wait_proc)(); /* call yield func */
341 if (rx_len < 0) /* receive error */
344 #ifdef USE_32BIT_DRIVERS
345 if (pcap_pkt_debug > 1)
346 printk ("pkt-err %s\n", pktInfo.error);
354 pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback, u_char *data)
358 while (num <= cnt || PACKET_COUNT_IS_UNLIMITED(cnt))
362 rc = pcap_read_one (p, callback, data);
367 _w32_os_yield(); /* allow SIGINT generation, yield to Win95/NT */
373 * Return network statistics
375 static int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps)
377 struct net_device_stats *stats;
379 struct device *dev = p ? get_device(p->fd) : NULL;
383 strcpy (p->errbuf, "illegal pcap handle");
387 if (!dev->get_stats || (stats = (*dev->get_stats)(dev)) == NULL)
389 strcpy (p->errbuf, "device statistics not available");
396 pd->stat.ps_recv = stats->rx_packets;
397 pd->stat.ps_drop += stats->rx_missed_errors;
398 pd->stat.ps_ifdrop = stats->rx_dropped + /* queue full */
399 stats->rx_errors; /* HW errors */
407 * Return detailed network/device statistics.
408 * May be called after 'dev->close' is called.
410 int pcap_stats_ex (pcap_t *p, struct pcap_stat_ex *se)
412 struct device *dev = p ? get_device (p->fd) : NULL;
414 if (!dev || !dev->get_stats)
416 strlcpy (p->errbuf, "detailed device statistics not available",
421 if (!strnicmp(dev->name,"pkt",3))
423 strlcpy (p->errbuf, "pktdrvr doesn't have detailed statistics",
427 memcpy (se, (*dev->get_stats)(dev), sizeof(*se));
432 * Simply store the filter-code for the pcap_read_dos() callback
433 * Some day the filter-code could be handed down to the active
434 * device (pkt_rx1.s or 32-bit device interrupt handler).
436 static int pcap_setfilter_dos (pcap_t *p, struct bpf_program *fp)
445 * Return # of packets received in pcap_read_dos()
447 u_long pcap_mac_packets (void)
453 * Return # of packets passed through filter in pcap_read_dos()
455 u_long pcap_filter_packets (void)
457 return (filter_count);
461 * Close pcap device. Not called for offline captures.
463 static void pcap_cleanup_dos (pcap_t *p)
470 if (pcap_stats(p,NULL) < 0)
471 pd->stat.ps_drop = 0;
472 if (!get_device(p->fd))
475 handle_to_device [p->fd-1] = NULL;
483 /* XXX - call pcap_cleanup_live_common? */
487 * Return the name of the 1st network interface,
488 * or NULL if none can be found.
490 char *pcap_lookupdev (char *ebuf)
494 #ifdef USE_32BIT_DRIVERS
498 for (dev = (struct device*)dev_base; dev; dev = dev->next)
500 PCAP_ASSERT (dev->probe);
502 if ((*dev->probe)(dev))
505 probed_dev = (struct device*) dev; /* remember last probed device */
506 return (char*) dev->name;
511 strcpy (ebuf, "No driver found");
516 * Gets localnet & netmask from Watt-32.
518 int pcap_lookupnet (const char *device, bpf_u_int32 *localnet,
519 bpf_u_int32 *netmask, char *errbuf)
525 strcpy (errbuf, "pcap_open_offline() or pcap_activate() must be "
530 mask = _w32_sin_mask;
531 net = my_ip_addr & mask;
534 if (IN_CLASSA(*netmask))
536 else if (IN_CLASSB(*netmask))
538 else if (IN_CLASSC(*netmask))
542 pcap_snprintf (errbuf, PCAP_ERRBUF_SIZE, "inet class for 0x%lx unknown", mask);
546 *localnet = htonl (net);
547 *netmask = htonl (mask);
554 * Get a list of all interfaces that are present and that we probe okay.
555 * Returns -1 on error, 0 otherwise.
556 * The list may be NULL epty if no interfaces were up and could be opened.
558 int pcap_platform_finddevs (pcap_if_list_t *devlistp, char *errbuf)
562 #if 0 /* Pkt drivers should have no addresses */
563 struct sockaddr_in sa_ll_1, sa_ll_2;
564 struct sockaddr *addr, *netmask, *broadaddr, *dstaddr;
569 for (dev = (struct device*)dev_base; dev; dev = dev->next)
571 PCAP_ASSERT (dev->probe);
573 if (!(*dev->probe)(dev))
576 PCAP_ASSERT (dev->close); /* set by probe routine */
581 * XXX - find out whether it's up or running? Does that apply here?
582 * Can we find out if anything's plugged into the adapter, if it's
583 * a wired device, and set PCAP_IF_CONNECTION_STATUS_CONNECTED
584 * or PCAP_IF_CONNECTION_STATUS_DISCONNECTED?
586 if ((curdev = add_dev(devlistp, dev->name, 0,
587 dev->long_name, errbuf)) == NULL)
593 #if 0 /* Pkt drivers should have no addresses */
594 memset (&sa_ll_1, 0, sizeof(sa_ll_1));
595 memset (&sa_ll_2, 0, sizeof(sa_ll_2));
596 sa_ll_1.sin_family = AF_INET;
597 sa_ll_2.sin_family = AF_INET;
599 addr = (struct sockaddr*) &sa_ll_1;
600 netmask = (struct sockaddr*) &sa_ll_1;
601 dstaddr = (struct sockaddr*) &sa_ll_1;
602 broadaddr = (struct sockaddr*) &sa_ll_2;
603 memset (&sa_ll_2.sin_addr, 0xFF, sizeof(sa_ll_2.sin_addr));
605 if (add_addr_to_dev(curdev, addr, sizeof(*addr),
606 netmask, sizeof(*netmask),
607 broadaddr, sizeof(*broadaddr),
608 dstaddr, sizeof(*dstaddr), errbuf) < 0)
616 if (ret == 0 && !found)
617 strcpy (errbuf, "No drivers found");
623 * pcap_assert() is mainly used for debugging
625 void pcap_assert (const char *what, const char *file, unsigned line)
628 fprintf (stderr, "%s (%u): Assertion \"%s\" failed\n",
635 * For pcap_offline_read(): wait and yield between printing packets
636 * to simulate the pace packets where actually recorded.
638 void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait)
642 struct pcap_dos *pd = p->priv;
644 pd->wait_proc = yield;
645 p->opt.timeout = wait;
650 * Initialise a named network device.
652 static struct device *
653 open_driver (const char *dev_name, char *ebuf, int promisc)
657 for (dev = (struct device*)dev_base; dev; dev = dev->next)
659 PCAP_ASSERT (dev->name);
661 if (strcmp (dev_name,dev->name))
664 if (!probed_dev) /* user didn't call pcap_lookupdev() first */
666 PCAP_ASSERT (dev->probe);
668 if (!(*dev->probe)(dev)) /* call the xx_probe() function */
670 pcap_snprintf (ebuf, PCAP_ERRBUF_SIZE, "failed to detect device `%s'", dev_name);
673 probed_dev = dev; /* device is probed okay and may be used */
675 else if (dev != probed_dev)
682 /* Select what traffic to receive
685 dev->flags |= (IFF_ALLMULTI | IFF_PROMISC);
686 else dev->flags &= ~(IFF_ALLMULTI | IFF_PROMISC);
688 PCAP_ASSERT (dev->open);
690 if (!(*dev->open)(dev))
692 pcap_snprintf (ebuf, PCAP_ERRBUF_SIZE, "failed to activate device `%s'", dev_name);
693 if (pktInfo.error && !strncmp(dev->name,"pkt",3))
696 strcat (ebuf, pktInfo.error);
701 /* Some devices need this to operate in promiscous mode
703 if (promisc && dev->set_multicast_list)
704 (*dev->set_multicast_list) (dev);
706 active_dev = dev; /* remember our active device */
710 /* 'dev_name' not matched in 'dev_base' list.
714 pcap_snprintf (ebuf, PCAP_ERRBUF_SIZE, "device `%s' not supported", dev_name);
721 pcap_snprintf (ebuf, PCAP_ERRBUF_SIZE, "device `%s' not probed", dev_name);
728 * Deinitialise MAC driver.
729 * Set receive mode back to default mode.
731 static void close_driver (void)
733 /* !!todo: loop over all 'handle_to_device[]' ? */
734 struct device *dev = active_dev;
736 if (dev && dev->close)
744 #ifdef USE_32BIT_DRIVERS
757 static void setup_signals (void (*handler)(int))
759 signal (SIGSEGV,handler);
760 signal (SIGILL, handler);
761 signal (SIGFPE, handler);
764 static void exc_handler (int sig)
766 #ifdef USE_32BIT_DRIVERS
767 if (active_dev->irq > 0) /* excludes IRQ 0 */
769 disable_irq (active_dev->irq);
770 irq_eoi_cmd (active_dev->irq);
778 fputs ("Catching SIGSEGV.\n", stderr);
781 fputs ("Catching SIGILL.\n", stderr);
785 fputs ("Catching SIGFPE.\n", stderr);
788 fprintf (stderr, "Catching signal %d.\n", sig);
793 #endif /* __DJGPP__ */
797 * Open the pcap device for the first client calling pcap_activate()
799 static int first_init (const char *name, char *ebuf, int promisc)
803 #ifdef USE_32BIT_DRIVERS
804 rx_pool = k_calloc (RECEIVE_BUF_SIZE, RECEIVE_QUEUE_SIZE);
807 strcpy (ebuf, "Not enough memory (Rx pool)");
813 setup_signals (exc_handler);
816 #ifdef USE_32BIT_DRIVERS
820 dev = open_driver (name, ebuf, promisc);
823 #ifdef USE_32BIT_DRIVERS
829 setup_signals (SIG_DFL);
834 #ifdef USE_32BIT_DRIVERS
836 * If driver is NOT a 16-bit "pkt/ndis" driver (having a 'copy_rx_buf'
837 * set in it's probe handler), initialise near-memory ring-buffer for
840 if (dev->copy_rx_buf == NULL)
842 dev->get_rx_buf = get_rxbuf;
843 dev->peek_rx_buf = peek_rxbuf;
844 dev->release_rx_buf = release_rxbuf;
845 pktq_init (&dev->queue, RECEIVE_BUF_SIZE, RECEIVE_QUEUE_SIZE, rx_pool);
851 #ifdef USE_32BIT_DRIVERS
852 static void init_32bit (void)
854 static int init_pci = 0;
857 _printk_init (64*1024, NULL); /* calls atexit(printk_exit) */
860 (void)pci_init(); /* init BIOS32+PCI interface */
867 * Hook functions for using Watt-32 together with pcap
869 static char rxbuf [ETH_MAX+100]; /* rx-buffer with some margin */
871 static pcap_t pcap_save;
873 static void watt32_recv_hook (u_char *dummy, const struct pcap_pkthdr *pcap,
876 /* Fix me: assumes Ethernet II only */
877 struct ether_header *ep = (struct ether_header*) buf;
879 memcpy (rxbuf, buf, pcap->caplen);
880 etype = ep->ether_type;
884 #if (WATTCP_VER >= 0x0224)
886 * This function is used by Watt-32 to poll for a packet.
887 * i.e. it's set to bypass _eth_arrived()
889 static void *pcap_recv_hook (WORD *type)
891 int len = pcap_read_dos (&pcap_save, 1, watt32_recv_hook, NULL);
897 return (void*) &rxbuf;
901 * This function is called by Watt-32 (via _eth_xmit_hook).
902 * If dbug_init() was called, we should trace packets sent.
904 static int pcap_xmit_hook (const void *buf, unsigned len)
908 if (pcap_pkt_debug > 0)
909 dbug_write ("pcap_xmit_hook: ");
911 if (active_dev && active_dev->xmit)
912 if ((*active_dev->xmit) (active_dev, buf, len) > 0)
915 if (pcap_pkt_debug > 0)
916 dbug_write (rc ? "ok\n" : "fail\n");
921 static int pcap_sendpacket_dos (pcap_t *p, const void *buf, size_t len)
923 struct device *dev = p ? get_device(p->fd) : NULL;
925 if (!dev || !dev->xmit)
927 return (*dev->xmit) (dev, buf, len);
931 * This function is called by Watt-32 in tcp_post_init().
932 * We should prevent Watt-32 from using BOOTP/DHCP/RARP etc.
934 static void (*prev_post_hook) (void);
936 static void pcap_init_hook (void)
938 _w32__bootp_on = _w32__dhcp_on = _w32__rarp_on = 0;
939 _w32__do_mask_req = 0;
940 _w32_dynamic_host = 0;
946 * Supress PRINT message from Watt-32's sock_init()
948 static void null_print (void) {}
951 * To use features of Watt-32 (netdb functions and socket etc.)
952 * we must call sock_init(). But we set various hooks to prevent
953 * using normal PKTDRVR functions in pcpkt.c. This should hopefully
954 * make Watt-32 and pcap co-operate.
956 static int init_watt32 (struct pcap *pcap, const char *dev_name, char *err_buf)
959 int rc, MTU, has_ip_addr;
960 int using_pktdrv = 1;
962 /* If user called sock_init() first, we need to reinit in
963 * order to open debug/trace-file properly
968 env = getenv ("PCAP_TRACE");
969 if (env && atoi(env) > 0 &&
970 pcap_pkt_debug < 0) /* if not already set */
973 pcap_pkt_debug = atoi (env);
976 _watt_do_exit = 0; /* prevent sock_init() calling exit() */
977 prev_post_hook = _w32_usr_post_init;
978 _w32_usr_post_init = pcap_init_hook;
979 _w32_print_hook = null_print;
981 if (dev_name && strncmp(dev_name,"pkt",3))
982 using_pktdrv = FALSE;
985 has_ip_addr = (rc != 8); /* IP-address assignment failed */
987 /* if pcap is using a 32-bit driver w/o a pktdrvr loaded, we
988 * just pretend Watt-32 is initialised okay.
990 * !! fix-me: The Watt-32 config isn't done if no pktdrvr
991 * was found. In that case my_ip_addr + sin_mask
992 * have default values. Should be taken from another
993 * ini-file/environment in any case (ref. tcpdump.ini)
997 if (!using_pktdrv || !has_ip_addr) /* for now .... */
999 static const char myip[] = "192.168.0.1";
1000 static const char mask[] = "255.255.255.0";
1002 printf ("Just guessing, using IP %s and netmask %s\n", myip, mask);
1003 my_ip_addr = aton (myip);
1004 _w32_sin_mask = aton (mask);
1006 else if (rc && using_pktdrv)
1008 pcap_snprintf (err_buf, PCAP_ERRBUF_SIZE, "sock_init() failed, code %d", rc);
1012 /* Set recv-hook for peeking in _eth_arrived().
1014 #if (WATTCP_VER >= 0x0224)
1015 _eth_recv_hook = pcap_recv_hook;
1016 _eth_xmit_hook = pcap_xmit_hook;
1019 /* Free the pkt-drvr handle allocated in pkt_init().
1020 * The above hooks should thus use the handle reopened in open_driver()
1025 /* _eth_is_init = 1; */ /* hack to get Rx/Tx-hooks in Watt-32 working */
1028 memcpy (&pcap_save, pcap, sizeof(pcap_save));
1029 MTU = pkt_get_mtu();
1030 pcap_save.fcode.bf_insns = NULL;
1031 pcap_save.linktype = _eth_get_hwtype (NULL, NULL);
1032 pcap_save.snapshot = MTU > 0 ? MTU : ETH_MAX; /* assume 1514 */
1035 /* prevent use of resolve() and resolve_ip()
1037 last_nameserver = 0;
1042 int EISA_bus = 0; /* Where is natural place for this? */
1045 * Application config hooks to set various driver parameters.
1048 static const struct config_table debug_tab[] = {
1049 { "PKT.DEBUG", ARG_ATOI, &pcap_pkt_debug },
1050 { "PKT.VECTOR", ARG_ATOX_W, NULL },
1051 { "NDIS.DEBUG", ARG_ATOI, NULL },
1052 #ifdef USE_32BIT_DRIVERS
1053 { "3C503.DEBUG", ARG_ATOI, &ei_debug },
1054 { "3C503.IO_BASE", ARG_ATOX_W, &el2_dev.base_addr },
1055 { "3C503.MEMORY", ARG_ATOX_W, &el2_dev.mem_start },
1056 { "3C503.IRQ", ARG_ATOI, &el2_dev.irq },
1057 { "3C505.DEBUG", ARG_ATOI, NULL },
1058 { "3C505.BASE", ARG_ATOX_W, NULL },
1059 { "3C507.DEBUG", ARG_ATOI, NULL },
1060 { "3C509.DEBUG", ARG_ATOI, &el3_debug },
1061 { "3C509.ILOOP", ARG_ATOI, &el3_max_loop },
1062 { "3C529.DEBUG", ARG_ATOI, NULL },
1063 { "3C575.DEBUG", ARG_ATOI, &debug_3c575 },
1064 { "3C59X.DEBUG", ARG_ATOI, &vortex_debug },
1065 { "3C59X.IFACE0", ARG_ATOI, &vortex_options[0] },
1066 { "3C59X.IFACE1", ARG_ATOI, &vortex_options[1] },
1067 { "3C59X.IFACE2", ARG_ATOI, &vortex_options[2] },
1068 { "3C59X.IFACE3", ARG_ATOI, &vortex_options[3] },
1069 { "3C90X.DEBUG", ARG_ATOX_W, &tc90xbc_debug },
1070 { "ACCT.DEBUG", ARG_ATOI, ðpk_debug },
1071 { "CS89.DEBUG", ARG_ATOI, &cs89_debug },
1072 { "RTL8139.DEBUG", ARG_ATOI, &rtl8139_debug },
1073 /* { "RTL8139.FDUPLEX", ARG_ATOI, &rtl8139_options }, */
1074 { "SMC.DEBUG", ARG_ATOI, &ei_debug },
1075 /* { "E100.DEBUG", ARG_ATOI, &e100_debug }, */
1076 { "PCI.DEBUG", ARG_ATOI, &pci_debug },
1077 { "BIOS32.DEBUG", ARG_ATOI, &bios32_debug },
1078 { "IRQ.DEBUG", ARG_ATOI, &irq_debug },
1079 { "TIMER.IRQ", ARG_ATOI, &timer_irq },
1085 * pcap_config_hook() is an extension to application's config
1086 * handling. Uses Watt-32's config-table function.
1088 int pcap_config_hook (const char *keyword, const char *value)
1090 return parse_config_table (debug_tab, NULL, keyword, value);
1094 * Linked list of supported devices
1096 struct device *active_dev = NULL; /* the device we have opened */
1097 struct device *probed_dev = NULL; /* the device we have probed */
1098 const struct device *dev_base = &pkt_dev; /* list of network devices */
1101 * PKTDRVR device functions
1103 int pcap_pkt_debug = -1;
1105 static void pkt_close (struct device *dev)
1107 BOOL okay = PktExitDriver();
1109 if (pcap_pkt_debug > 1)
1110 fprintf (stderr, "pkt_close(): %d\n", okay);
1117 static int pkt_open (struct device *dev)
1121 if (dev->flags & IFF_PROMISC)
1122 mode = PDRX_ALL_PACKETS;
1123 else mode = PDRX_BROADCAST;
1125 if (!PktInitDriver(mode))
1128 PktResetStatistics (pktInfo.handle);
1129 PktQueueBusy (FALSE);
1133 static int pkt_xmit (struct device *dev, const void *buf, int len)
1135 struct net_device_stats *stats = (struct net_device_stats*) dev->priv;
1137 if (pcap_pkt_debug > 0)
1138 dbug_write ("pcap_xmit\n");
1140 if (!PktTransmit(buf,len))
1148 static void *pkt_stats (struct device *dev)
1150 struct net_device_stats *stats = (struct net_device_stats*) dev->priv;
1152 if (!stats || !PktSessStatistics(pktInfo.handle))
1155 stats->rx_packets = pktStat.inPackets;
1156 stats->rx_errors = pktStat.lost;
1157 stats->rx_missed_errors = PktRxDropped();
1161 static int pkt_probe (struct device *dev)
1163 if (!PktSearchDriver())
1166 dev->open = pkt_open;
1167 dev->xmit = pkt_xmit;
1168 dev->close = pkt_close;
1169 dev->get_stats = pkt_stats;
1170 dev->copy_rx_buf = PktReceive; /* farmem peek and copy routine */
1171 dev->get_rx_buf = NULL;
1172 dev->peek_rx_buf = NULL;
1173 dev->release_rx_buf = NULL;
1174 dev->priv = calloc (sizeof(struct net_device_stats), 1);
1181 * NDIS device functions
1183 static void ndis_close (struct device *dev)
1191 static int ndis_open (struct device *dev)
1193 int promis = (dev->flags & IFF_PROMISC);
1196 if (!NdisInit(promis))
1205 static void *ndis_stats (struct device *dev)
1207 static struct net_device_stats stats;
1214 static int ndis_probe (struct device *dev)
1221 dev->open = ndis_open;
1223 dev->close = ndis_close;
1224 dev->get_stats = ndis_stats;
1225 dev->copy_rx_buf = NULL; /* to-do */
1226 dev->get_rx_buf = NULL; /* upcall is from rmode driver */
1227 dev->peek_rx_buf = NULL;
1228 dev->release_rx_buf = NULL;
1233 * Search & probe for supported 32-bit (pmode) pcap devices
1235 #if defined(USE_32BIT_DRIVERS)
1237 struct device el2_dev LOCKED_VAR = {
1246 struct device el3_dev LOCKED_VAR = {
1255 struct device tc515_dev LOCKED_VAR = {
1264 struct device tc59_dev LOCKED_VAR = {
1273 struct device tc90xbc_dev LOCKED_VAR = {
1282 struct device wd_dev LOCKED_VAR = {
1291 struct device ne_dev LOCKED_VAR = {
1300 struct device acct_dev LOCKED_VAR = {
1302 "Accton EtherPocket",
1309 struct device cs89_dev LOCKED_VAR = {
1311 "Crystal Semiconductor",
1318 struct device rtl8139_dev LOCKED_VAR = {
1324 rtl8139_probe /* dev->probe routine */
1328 * Dequeue routine is called by polling.
1329 * NOTE: the queue-element is not copied, only a pointer is
1330 * returned at '*buf'
1332 int peek_rxbuf (BYTE **buf)
1334 struct rx_elem *tail, *head;
1336 PCAP_ASSERT (pktq_check (&active_dev->queue));
1339 tail = pktq_out_elem (&active_dev->queue);
1340 head = pktq_in_elem (&active_dev->queue);
1345 PCAP_ASSERT (tail->size < active_dev->queue.elem_size-4-2);
1347 *buf = &tail->data[0];
1348 return (tail->size);
1355 * Release buffer we peeked at above.
1357 int release_rxbuf (BYTE *buf)
1360 struct rx_elem *tail = pktq_out_elem (&active_dev->queue);
1362 PCAP_ASSERT (&tail->data[0] == buf);
1366 pktq_inc_out (&active_dev->queue);
1371 * get_rxbuf() routine (in locked code) is called from IRQ handler
1372 * to request a buffer. Interrupts are disabled and we have a 32kB stack.
1374 BYTE *get_rxbuf (int len)
1378 if (len < ETH_MIN || len > ETH_MAX)
1381 idx = pktq_in_index (&active_dev->queue);
1385 static int fan_idx LOCKED_VAR = 0;
1386 writew ("-\\|/"[fan_idx++] | (15 << 8), /* white on black colour */
1387 0xB8000 + 2*79); /* upper-right corner, 80-col colour screen */
1390 /* writew (idx + '0' + 0x0F00, 0xB8000 + 2*78); */
1393 if (idx != active_dev->queue.out_index)
1395 struct rx_elem *head = pktq_in_elem (&active_dev->queue);
1398 active_dev->queue.in_index = idx;
1399 return (&head->data[0]);
1402 /* !!to-do: drop 25% of the oldest element
1404 pktq_clear (&active_dev->queue);
1409 * Simple ring-buffer queue handler for reception of packets
1410 * from network driver.
1412 #define PKTQ_MARKER 0xDEADBEEF
1414 static int pktq_check (struct rx_ringbuf *q)
1421 if (!q || !q->num_elem || !q->buf_start)
1427 for (i = 0; i < q->num_elem; i++)
1429 buf += q->elem_size;
1430 if (*(DWORD*)(buf - sizeof(DWORD)) != PKTQ_MARKER)
1437 static int pktq_init (struct rx_ringbuf *q, int size, int num, char *pool)
1441 q->elem_size = size;
1443 q->buf_start = pool;
1447 PCAP_ASSERT (size >= sizeof(struct rx_elem) + sizeof(DWORD));
1451 for (i = 0; i < num; i++)
1454 struct rx_elem *elem = (struct rx_elem*) pool;
1456 /* assert dword aligned elements
1458 PCAP_ASSERT (((unsigned)(&elem->data[0]) & 3) == 0);
1461 *(DWORD*) (pool - sizeof(DWORD)) = PKTQ_MARKER;
1467 * Increment the queue 'out_index' (tail).
1470 static int pktq_inc_out (struct rx_ringbuf *q)
1473 if (q->out_index >= q->num_elem)
1475 return (q->out_index);
1479 * Return the queue's next 'in_index' (head).
1482 static int pktq_in_index (struct rx_ringbuf *q)
1484 volatile int index = q->in_index + 1;
1486 if (index >= q->num_elem)
1492 * Return the queue's head-buffer.
1494 static struct rx_elem *pktq_in_elem (struct rx_ringbuf *q)
1496 return (struct rx_elem*) (q->buf_start + (q->elem_size * q->in_index));
1500 * Return the queue's tail-buffer.
1502 static struct rx_elem *pktq_out_elem (struct rx_ringbuf *q)
1504 return (struct rx_elem*) (q->buf_start + (q->elem_size * q->out_index));
1508 * Clear the queue ring-buffer by setting head=tail.
1510 static void pktq_clear (struct rx_ringbuf *q)
1512 q->in_index = q->out_index;
1516 * Symbols that must be linkable for "gcc -O0"
1524 #include "msdos/pm_drvr/ioport.h"
1525 #include "msdos/pm_drvr/dma.h"
1527 #endif /* USE_32BIT_DRIVERS */
1530 * Libpcap version string.
1533 pcap_lib_version(void)
1535 return ("DOS-" PCAP_VERSION_STRING);