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