diff -Naur como-0.4/base/sniffer-sk98.c como-0.4.fix1/base/sniffer-sk98.c
--- como-0.4/base/sniffer-sk98.c	2005-06-14 13:39:11.000000000 +0100
+++ como-0.4.fix1/base/sniffer-sk98.c	2005-08-12 10:45:19.224778379 +0100
@@ -25,9 +25,10 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: sniffer-sk98.c,v 1.6 2005/06/14 12:39:11 iannak1 Exp $
+ * $Id: sniffer-sk98.c,v 1.13 2005/07/13 15:37:20 sos22 Exp $
  */
 
+#include <assert.h>
 #include <errno.h>
 #include <string.h>
 #include <unistd.h>
@@ -38,6 +39,7 @@
 #include "como.h"
 #include "sniffers.h"
 #include "sk98_timers.h"
+#include "sk98_uspace_if.h"
 
 /* 
  * SNIFFER  ---    SysKonnect card SK98
@@ -58,54 +60,21 @@
 
 
 /* 
- * Rings with packet tokens. Modified by kernel and user 
- */
-#define RING_SIZE 65535
-struct map_area_header {
-    /* Stuff mostly written by userspace */
-    unsigned k2u_cons;
-    unsigned u2k_prod;
-    unsigned u2k_tokens[RING_SIZE];
-
-    /* Stuff mostly written by kernel */
-    unsigned u2k_cons;
-    unsigned k2u_prod;
-    struct {
-	unsigned token;
-	unsigned tstamp;
-	unsigned short len;
-	unsigned short interface;
-    } k2u_pipe[RING_SIZE];
-};
-
-#define mb() asm volatile("lock; addl $0, (%%esp)" ::: "memory")
-
-
-/* 
- * IOCTL structure used to pass info to the driver
- */
-struct sk98_ioctl_map {
-    void *start_addr;
-    unsigned long len;
-    unsigned offset;
-};
-#define SK98_IOCTL_MAP 1
-
-
-/* 
  * Sniffer state variables for SK98 card (include packets, tokens
  * and time-synchronization information).  
  */
 struct _snifferinfo { 
-    struct map_area_header * m;	
+    struct sk98_map_area_header * m;	
     struct packet_data_area * packet_pool;	
     unsigned retimer_size;		
     clock_retimer_t ** clock_retimers;	
-    int tokens[RING_SIZE];
+    int tokens[SK98_RING_SIZE];
     int no_tokens; 
 };
 
 
+#define mb() asm volatile("lock; addl $0, 0(%%esp)\n" ::: "memory")
+
 /* 
  * -- discard_packets 
  * 
@@ -113,12 +82,12 @@
  * 
  */
 static void
-discard_packets(struct map_area_header * m)
+discard_packets(struct sk98_map_area_header * m)
 {
     /* Return packets to the OS without examining them */
-    while (m->k2u_prod > m->k2u_cons) {
-	m->u2k_tokens[m->u2k_prod % RING_SIZE] = 
-		m->k2u_pipe[m->k2u_cons % RING_SIZE].token;
+    while (m->k2u_prod != m->k2u_cons) {
+	m->u2k_tokens[m->u2k_prod % SK98_RING_SIZE] = 
+		m->k2u_pipe[m->k2u_cons % SK98_RING_SIZE].token;
 	mb();
 	m->u2k_prod++;
 	m->k2u_cons++;
@@ -136,7 +105,7 @@
 void 
 calibrate(struct _snifferinfo * info)
 {
-    struct map_area_header * m = info->m; 
+    struct sk98_map_area_header * m = info->m; 
     clock_retimer_t ** cr = info->clock_retimers;	
     uint size = info->retimer_size; 
     uint num;
@@ -149,17 +118,18 @@
 	struct timeval now;
 	uint s, t;
 
-        while (m->k2u_cons >= m->k2u_prod)
+        discard_packets(m);
+        while (m->k2u_cons == m->k2u_prod)
             mb();
         t = m->k2u_prod;
 
         mb();
         gettimeofday(&now, NULL);
-        for (s = m->k2u_cons; s < t; s++) {
+        for (s = m->k2u_cons; s != t; s++) {
             uint iface;
             int ind;
 
-            ind = s % RING_SIZE;
+            ind = s % SK98_RING_SIZE;
             iface = m->k2u_pipe[ind].interface;
             if (iface == (unsigned short)-1)
                 continue;
@@ -174,13 +144,12 @@
 
             if (cr[iface] == NULL) {
                 logmsg(V_LOGSNIFFER, "Found interface %d\n", iface);
-                cr[iface] = new_clock_retimer("", 0);
+                cr[iface] = new_clock_retimer("", iface);
                 num++;
             }
-            calibrated += doTimer(cr[iface], m->k2u_pipe[ind].tstamp, 0, &now);
+            calibrated += doTimer(cr[iface], m->k2u_pipe[ind].tstamp, &now);
         }
-        discard_packets(m);
-    } while (calibrated != num);
+    } while (num != calibrated);
 
     info->retimer_size = size; 
     info->clock_retimers = cr;
@@ -208,9 +177,12 @@
 
     /* Start up the timestamps library 
      * 
-     * XXX where do we get 78110207 from? (initial frequency?) 
+     * 78110207 is an initial frequency estimate from the card's data
+     * sheet, in Hz.  There are also some cards in existence which
+     * need about half this; in that case, timer calibration may take
+     * a little longer but it should still work.
      */
-    initialise_timestamps(1, 78110207, NULL);
+    initialise_timestamps(31250000);
 
     /* open the device */
     fd = open(src->device, O_RDWR);
@@ -227,7 +199,7 @@
      * mmap the region that contains the ring buffers 
      * with the tokens. 
      */ 
-    info->m = mmap(NULL, sizeof(struct map_area_header), 
+    info->m = mmap(NULL, sizeof(struct sk98_map_area_header), 
 			PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
     if (info->m == MAP_FAILED) {
         logmsg(LOGWARN, "sniffer-sk98: failed to mmap %s: %s\n", 
@@ -238,7 +210,8 @@
 
     /* inform the driver of where the packets should go */
     args.len = 1024 * 1024 * BUFFER_MB;
-    args.offset = 0;
+    args.offset = 24;
+    args.version = SK98_CURRENT_VERSION;
     info->packet_pool = safe_malloc(args.len);
     args.start_addr = info->packet_pool;
     if (ioctl(fd, SK98_IOCTL_MAP, &args) < 0) {
@@ -249,14 +222,18 @@
     } 
 
     /* we have no packets */
-    info->no_tokens = -1; 
+    info->no_tokens = 0;
 
+    logmsg(LOGSNIFFER, "starting sk98 timer calibration...\n");
     /* do timer calibration */
     calibrate(info); 
+    logmsg(LOGSNIFFER, "done sk98 timer calibration.\n");
+
+    discard_packets(info->m);
 
     src->fd = fd; 
-    src->flags = SNIFF_POLL;
-    src->polling = TIME2TS(0, 1000); 
+    src->flags = SNIFF_SELECT;
+    src->polling = 0;
     return 0;	/* success */
 }
 
@@ -267,10 +244,10 @@
  * gives token back to kernel
  */
 static void
-return_token(struct map_area_header * m, unsigned token)
+return_token(struct sk98_map_area_header * m, unsigned token)
 {
     unsigned ind;
-    ind = m->u2k_prod % RING_SIZE;
+    ind = m->u2k_prod % SK98_RING_SIZE;
     m->u2k_tokens[ind] = token;
     mb();
     m->u2k_prod++;
@@ -289,14 +266,30 @@
     struct _snifferinfo * info = (struct _snifferinfo *) src->ptr; 
     pkt_t * pkt;
     int npkts;                 /* processed pkts */
+    unsigned pending;
+    static unsigned max_pending;
+    static unsigned last_drop;
+    int x;
+    unsigned new_drop;
 
     /* return all tokens of previous round */
-    for (; info->no_tokens >= 0; info->no_tokens--) 
-	return_token(info->m, info->tokens[info->no_tokens]);
-
-    info->no_tokens = 0; 
-
-    for (npkts = 0, pkt = out; npkts < max_no; npkts++, pkt++) { 
+    mb();
+    for (x = 0; x < info->no_tokens; x++)
+	if (info->tokens[x] != -1)
+	    return_token(info->m, info->tokens[x]);
+    info->no_tokens = 0;
+
+    npkts = 0;
+    pkt = out;
+    last_drop = new_drop;
+
+    pending = info->m->k2u_prod - info->m->k2u_cons;
+    if (pending > max_pending)
+	max_pending = pending;
+    rlimit_logmsg(1000, LOGSNIFFER,
+		  "Current ring fullness %d, max %d, drop %d.\n",
+		  pending, max_pending, info->m->drop_counter);
+    for (; npkts < max_no; npkts++, pkt++) { 
 	uint ind;
 	uint token;
 	ushort iface;
@@ -305,22 +298,27 @@
         if (info->m->k2u_cons == info->m->k2u_prod) 
 	    break; 	/* no more tokens */
 	mb();
-	ind = info->m->k2u_cons % RING_SIZE;
+	ind = info->m->k2u_cons % SK98_RING_SIZE;
 	token = info->m->k2u_pipe[ind].token;
 
 	iface = info->m->k2u_pipe[ind].interface;
 	if (iface == (ushort)-1) {
 	    /* Kernel decided not to use this token.  Return it. */
-	    return_token(info->m, token);
+	    mb();
 	    info->m->k2u_cons++;
+	    mb();
+	    return_token(info->m, token);
+	    info->no_tokens = npkts;
 	    return npkts;
 	}
 
 	if (iface >= info->retimer_size || info->clock_retimers[iface] == NULL){
 	    /* Clock calibration was incomplete.  Uh oh. */
 	    logmsg(LOGWARN, "calibration incomplete, returning token\n"); 
-	    return_token(info->m, token);
+	    mb();
 	    info->m->k2u_cons++;
+	    mb();
+	    return_token(info->m, token);
 	    return -1;
 	}
 
@@ -337,7 +335,8 @@
          * update layer2 information and offsets of layer 3 and above. 
          * this sniffer only runs on ethernet frames. 
          */
-        updateofs(pkt, COMOTYPE_ETH); 
+        updateofs(pkt, COMOTYPE_ETH);
+	mb();
 	info->m->k2u_cons++;
     }
 
@@ -351,7 +350,7 @@
 {
     struct _snifferinfo * info = (struct _snifferinfo *) src->ptr;
 
-    munmap(info->m,  sizeof(struct map_area_header));
+    munmap(info->m,  sizeof(struct sk98_map_area_header));
     free(info->packet_pool); 
     free(src->ptr);
 }
diff -Naur como-0.4/extra/sk98_timers.c como-0.4.fix1/extra/sk98_timers.c
--- como-0.4/extra/sk98_timers.c	2005-06-01 18:19:04.000000000 +0100
+++ como-0.4.fix1/extra/sk98_timers.c	2005-08-11 16:40:28.000000000 +0100
@@ -24,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: sk98_timers.c,v 1.1 2005/06/01 17:19:04 iannak1 Exp $
+ * $Id: sk98_timers.c,v 1.3 2005/07/06 12:22:26 sos22 Exp $
  */
 
 #include <sys/types.h>
@@ -101,52 +101,17 @@
 				  final answer, but we can use them to
 				  make initial estimates for the next
 				  phase. */
+    unsigned long tstamp_freq;
 };
 
 
 
 static unsigned long drift_period = 1500000; // min= 48ms, max=0.432s
-static unsigned long nictstamp_freq = 31250000;
-
-static int do_clock_retime;
-static FILE *drift_file;
+static unsigned long def_nictstamp_freq = 312500000;
 
 /*************************************************************************/
 
 
-static void record_tstamp_drift_file(unsigned long nictstamp,
-				     struct timeval *now,
-				     unsigned total_pkts,
-				     unsigned dev_num)
-{
-    unsigned long data[5];
-    if(drift_file) {
-	data[0] = nictstamp;
-	data[1] = (unsigned long) now->tv_sec;
-	data[2] = (unsigned long) now->tv_usec;
-	data[3] = total_pkts;
-	data[4] = dev_num;
-	fwrite(data, sizeof(unsigned long), 5, drift_file);
-	fflush(drift_file);
-    }
-}
-
-static void record_endrec_drift_file(struct timeval *timebase,
-				     unsigned dev_num)
-{
-    unsigned long data[5];
-    if(drift_file)
-    {
-	data[0] = 0;
-	data[1] = (unsigned long) timebase->tv_sec;
-	data[2] = (unsigned long) timebase->tv_usec;
-	data[3] = 0;
-	data[4] = dev_num;
-	fwrite(data, sizeof(unsigned long), 5, drift_file);
-	fflush(drift_file);
-    }
-}
-
 /* Is x >= y, allowing for overflow? */
 #define TSTAMP_GREATEREQ(x, y) \
 	( (x) >= (y) ? ((x) - (y) < 1 << 30) : ((y) - (x) > 1 << 30) )
@@ -209,6 +174,7 @@
 	err(1, "allocating timer recalibration structure");
     work->name = strdup(name);
     work->dev_num = dev_num;
+    work->tstamp_freq = def_nictstamp_freq;
     return work;
 }
 
@@ -219,7 +185,7 @@
    Returns 1 if we just went from an uncalibrated to a calibrated
    state. */
 int doTimer(clock_retimer_t *timer, unsigned long nictstamp,
-	    unsigned total_pkts, struct timeval *now)
+	    struct timeval *now)
 {
     struct timeval est_time; /* Estimated packet arrival time */
     double timed; /* Difference between est_time and time, seconds */
@@ -239,14 +205,16 @@
 
     if (timer->mode == clock_mode_prestart) {
 	reset_timer(timer, nictstamp, now);
-	if(do_clock_retime)
-	    timer->mode = clock_mode_find_intercept;
-	else
-	    timer->mode = clock_mode_constant_output;
+	timer->mode = clock_mode_find_intercept;
 	timer->samples_bad = 0;
 	return 0;
     }
 
+    if (timer->mode == clock_mode_constant_output) {
+	/* That's all we need to do for now. */
+	return 0;
+    }
+
     if (!TSTAMP_GREATEREQ(nictstamp, timer->nextdrift)) {
 	/* It's too early to do the next phase. */
 	return 0;
@@ -254,13 +222,6 @@
 
     timer->nextdrift += drift_interval();
 
-    record_tstamp_drift_file(nictstamp, now, total_pkts, timer->dev_num);
-
-    if (timer->mode == clock_mode_constant_output) {
-	/* That's all we need to do for now. */
-	return 0;
-    }
-
     getTime(timer, nictstamp, &est_time, NULL);
 
     timed = tv_to_secs(&est_time) - tv_to_secs(now);
@@ -307,7 +268,6 @@
 	return 0;
     }
 
-
     /* Interesting times:
 
        -- We start a calibration run, system clock (A)
@@ -347,11 +307,11 @@
     s2_r = s_yy - (grad * grad * s_xx) / (timer->samples - 2);
     uncerc2 = s2_r * (1 + 1.0 / timer->samples + m_x * m_x / s_xx);
 
-    logmsg(LOGCAPTURE, "Interface %d: timer uncerc %e, grad %e.\n",
-	   timer->dev_num, sqrt(uncerc2), grad);
-
     /* Guess the nictstamp frequency from the data we've collected. */
-    nictstamp_freq = ((1.0 + grad) * (double) nictstamp_freq)+0.5;
+    timer->tstamp_freq = ((1.0 + grad) * (double) timer->tstamp_freq)+0.5;
+
+    logmsg(LOGSNIFFER, "Interface %d: timer uncerc %e, grad %e, freq %d.\n",
+	   timer->dev_num, sqrt(uncerc2), grad, timer->tstamp_freq);
 
     if (grad > 1e-6 || grad < -1e-6 || timer->samples_bad) {
 	/* We don't trust the calculated intercept if we've had to
@@ -365,9 +325,10 @@
     secs_to_tv(&timer->time_base,
 	       tv_to_secs(&timer->time_base) - inter);
 
-    record_endrec_drift_file(&timer->time_base, timer->dev_num);
     timer->mode = clock_mode_constant_output;
 
+    logmsg(LOGSNIFFER, "Interface %d: frequency estimate %d.\n",
+	   timer->dev_num, timer->tstamp_freq);
     return 1;
 }
 
@@ -397,9 +358,9 @@
        that to be safe, so we have to fart about with fixed point
        arithmetic, like so. */
     tics = timer->tic_cur - timer->tic_base;
-    t.tv_sec = tics / nictstamp_freq;
-    t.tv_nsec = (1000000000ull * (tics % nictstamp_freq)) /
-	nictstamp_freq;
+    t.tv_sec = tics / timer->tstamp_freq;
+    t.tv_nsec = (1000000000ull * (tics % timer->tstamp_freq)) /
+	timer->tstamp_freq;
     assert(t.tv_nsec >= 0);
     assert(t.tv_nsec < 1000000000);
 
@@ -448,21 +409,8 @@
     return;
 }
 
-void initialise_timestamps(unsigned do_retime, unsigned long initial_freq,
-			   const char *drift_fname)
+void initialise_timestamps(unsigned long initial_freq)
 {
-    char hostname[256];
-
-    if (!do_retime)
-	abort();
-    do_clock_retime = do_retime;
     if (initial_freq != 0)
-	nictstamp_freq = initial_freq;
-    if (drift_fname != NULL) {
-	drift_file = fopen(drift_fname, "w");
-	if (drift_file == NULL)
-	    err(1, "openning drift file %s", drift_fname);
-
-	gethostname(hostname, 256);
-    }
+	def_nictstamp_freq = initial_freq;
 }
diff -Naur como-0.4/extra/sk98_timers.h como-0.4.fix1/extra/sk98_timers.h
--- como-0.4/extra/sk98_timers.h	2005-06-01 18:19:04.000000000 +0100
+++ como-0.4.fix1/extra/sk98_timers.h	2005-08-11 16:40:28.000000000 +0100
@@ -24,7 +24,7 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * $Id: sk98_timers.h,v 1.1 2005/06/01 17:19:04 iannak1 Exp $
+ * $Id: sk98_timers.h,v 1.2 2005/06/23 11:43:59 sos22 Exp $
  */
 
 
@@ -37,10 +37,8 @@
 void getTime(clock_retimer_t *timer, unsigned long nictstamp,
 	     struct timeval *tv, struct timespec *ts);
 int doTimer(clock_retimer_t *timer, unsigned long nictstamp,
-	    unsigned total_pkts, struct timeval *now);
+	    struct timeval *now);
 
 clock_retimer_t *new_clock_retimer(const char *name, unsigned dev_num);
 
-void initialise_timestamps(unsigned do_clock_retime,
-			   unsigned long initial_freq,
-			   const char *drift_fname);
+void initialise_timestamps(unsigned long initial_freq);
diff -Naur como-0.4/include/sk98_uspace_if.h como-0.4.fix1/include/sk98_uspace_if.h
--- como-0.4/include/sk98_uspace_if.h	1970-01-01 01:00:00.000000000 +0100
+++ como-0.4.fix1/include/sk98_uspace_if.h	2005-08-11 16:40:28.000000000 +0100
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2005 Intel Corporation 
+ * Copyright (c) 2005 Steven Smith, University of Cambridge Computer Laboratory.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $Id: sk98_uspace_if.h,v 1.1 2005/06/20 13:40:00 sos22 Exp $
+ */
+
+/* Can't cope with any packets bigger than this.  This must be a
+   factor of the page size. */
+#define SK98_EXPECTED_PACKET_SIZE 2048
+
+#define SK98_RING_SIZE 65534
+struct sk98_map_area_header {
+	/* Stuff mostly written by userspace */
+	unsigned k2u_cons;
+	unsigned u2k_prod;
+	unsigned u2k_tokens[SK98_RING_SIZE];
+
+	/* Stuff mostly written by kernel space */
+	unsigned u2k_cons;
+	unsigned k2u_prod;
+	struct {
+		unsigned token;
+		unsigned tstamp;
+		unsigned short len;
+		unsigned short interface;
+	} k2u_pipe[SK98_RING_SIZE];
+
+	unsigned drop_counter;
+};
+
+struct sk98_ioctl_map {
+	void *start_addr;
+	unsigned long len;
+	unsigned offset;
+	unsigned version;
+#define SK98_CURRENT_VERSION 4
+};
+#define SK98_IOCTL_MAP 1
+
