Home | History | Annotate | Download | only in libpcap
      1 /*
      2  *  This file is part of DOS-libpcap
      3  *  Ported to DOS/DOSX by G. Vanem <giva (at) 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 
    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  */
    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
    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
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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  */
    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 *
    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  */
    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__
    703 static void setup_signals (void (*handler)(int))
    704 {
    705   signal (SIGSEGV,handler);
    706   signal (SIGILL, handler);
    707   signal (SIGFPE, handler);
    708 }
    709 
    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  */
    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
    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 
    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  */
    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  */
    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 
    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 
    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  */
    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  */
    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  */
   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 
   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 
   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 
   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 
   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 
   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  */
   1129 static void ndis_close (struct device *dev)
   1130 {
   1131 #ifdef USE_NDIS2
   1132   NdisShutdown();
   1133 #endif
   1134   ARGSUSED (dev);
   1135 }
   1136 
   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 
   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 
   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  */
   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  */
   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  */
   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 
   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 
   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  */
   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  */
   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  */
   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  */
   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  */
   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