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