$NetBSD$

--- bsd/kernel.cc.orig	2006-02-18 08:36:06.000000000 +0100
+++ bsd/kernel.cc	2007-12-17 21:23:26.000000000 +0100
@@ -115,8 +115,16 @@
 // in __NetBSD_Version__ for us if needed.
 #if defined(XOSVIEW_NETBSD) && defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 106010000)
 #define NETBSD_1_6A
+#ifdef HW_DISKSTATS
+static int dmib[3] = {CTL_HW, HW_DISKSTATS, sizeof(struct disk_sysctl)};
+#endif
+#ifdef HW_IOSTATS
+static int dmib[3] = {CTL_HW, HW_IOSTATS, sizeof(struct io_sysctl)};
+#include <sys/iostat.h>
+#endif
 #endif
 
+#include "netmeter.h"		/*  For netIface_  */
 #include "general.h"
 #include "kernel.h"		/*  To grab CVSID stuff.  */
 
@@ -303,9 +311,11 @@
 
 void
 OpenKDIfNeeded() {
+  static int initialized = 0;
   char unusederrorstring[_POSIX2_LINE_MAX];
 
-  if (kd) return; //  kd is non-NULL, so it has been initialized.  BCG
+  if (initialized) return;
+  initialized = 1;
 
     /*  Open it read-only, for a little added safety.  */
     /*  If the first character of kernelFileName is not '\0', then use
@@ -313,8 +323,10 @@
 	specifying NULL.  */
   if ((kd = kvm_openfiles ((kernelFileName[0]) ? kernelFileName : NULL,
 			    NULL, NULL, O_RDONLY, unusederrorstring))
-      == NULL)
-	  err (-1, "OpenKDIfNeeded():kvm-open()");
+      == NULL) {
+	  warn ("OpenKDIfNeeded():kvm-open()");
+	  return;
+  }
   // Parenthetical note:  FreeBSD kvm_openfiles() uses getbootfile() to get
   // the correct kernel file if the 1st arg is NULL.  As far as I can see,
   // one should always use NULL in FreeBSD, but I suppose control is never a
@@ -400,6 +412,8 @@
   static int mib[] = { CTL_KERN, KERN_CPUSTATS };
 #endif
 #if defined(XOSVIEW_NETBSD) && (__NetBSD_Version__ >= 104260000)
+  uint64_t cp_time[CPUSTATES];
+  size_t size = sizeof(cp_time[0]) * CPUSTATES;
   static int mib[] = { CTL_KERN, KERN_CP_TIME };
 #endif
 
@@ -407,14 +421,11 @@
   if (CPUSTATES != 5)
     errx (-1, "Error:  xosview for *BSD expects 5 cpu states!\n");
 #if defined(__NetBSD_Version__) && __NetBSD_Version__ > 104260000 /* > 1.4Z */
-  struct schedstate_percpu ssp;
-  size_t size = sizeof(ssp.spc_cp_time);
-  if (sysctl(mib, 2, ssp.spc_cp_time, &size, NULL, 0) < 0) {
-    fprintf(stderr, "can't get schedstate_percpu: %s\n", strerror(errno));
-    memset(&ssp, 0, sizeof(ssp));
+  if (sysctl(mib, 2, cp_time, &size, NULL, 0) < 0) {
+    fprintf(stderr, "xosview: sysctl kern.cp_time failed: %s\n", strerror(errno));
+    bzero(&cp_time, size);
   }
-  for (size = 0; size < CPUSTATES; size++)
-    timeArray[size] = (long) ssp.spc_cp_time[size];
+  bcopy (cp_time, timeArray, size);
 #else
 #ifdef XOSVIEW_BSDI
   if (sysctl(mib, 2, &cpu, &size, NULL, 0) < 0) {
@@ -441,7 +452,7 @@
 }
 
 void
-BSDGetNetInOut (long long * inbytes, long long * outbytes) {
+NetMeter::BSDGetNetInOut (long long * inbytes, long long * outbytes) {
 
 
   struct ifnet * ifnetp;
@@ -466,7 +477,8 @@
   while (ifnetp) {
     //  Now, dereference the pointer to get the ifnet struct.
     safe_kvm_read ((u_long) ifnetp, &ifnet, sizeof(ifnet));
-#ifdef NET_DEBUG
+#ifdef XOSVIEW_NETBSD
+    if (netIface_ != "False" ) {
     char ifname[256];
 #ifdef NETBSD_OLD_IFACE
     //  In pre-1.2A, getting the interface name was more complicated.
@@ -476,15 +488,21 @@
     safe_kvm_read ((u_long) (((char*)ifnetp) + (&ifnet.if_xname[0] - (char*)&ifnet)), ifname, 256);
     snprintf (ifname, 256, "%s", ifname);
 #endif
+#ifdef NET_DEBUG
     printf ("Interface name is %s\n", ifname);
     printf ("Ibytes: %8llu Obytes %8llu\n",
 	(unsigned long long) ifnet.if_ibytes,
 	(unsigned long long) ifnet.if_obytes);
     printf ("Ipackets:  %8llu\n", (unsigned long long) ifnet.if_ipackets);
-#endif
+#endif /* NET_DEBUG */
+      if (ifname != netIface_)
+       goto skipif;
+    }
+#endif /* XOSVIEW_NETBSD */
     *inbytes  += ifnet.if_ibytes;
     *outbytes += ifnet.if_obytes;
 
+    skipif:
     //  Linked-list step taken from if.c in netstat source, line 120.
 #ifdef XOSVIEW_FREEBSD
 #if (__FreeBSD_version >= 300000) 
@@ -773,13 +791,12 @@
 #ifdef NETBSD_1_6A
   // Do a sysctl with a NULL data pointer to get the size that would
   // have been returned, and use that to figure out # drives.
-  int mib[3] = {CTL_HW, HW_DISKSTATS, sizeof(struct disk_sysctl)};
   size_t size;
-  if (sysctl(mib, 3, NULL, &size, NULL, 0) < 0) {
+  if (sysctl(dmib, 3, NULL, &size, NULL, 0) < 0) {
     warnx("!!! The DiskMeter sysctl failed.  Disabling DiskMeter.");
     return 0;
   }
-  NetBSD_N_Drives = size / sizeof(struct disk_sysctl);
+  NetBSD_N_Drives = size / dmib[2];
   return 1;
 #endif
   return ValidSymbol(DISKLIST_SYM_INDEX);
@@ -816,19 +833,29 @@
 #else
 #if defined(NETBSD_1_6A)
   // Use the new sysctl to do this for us.
-  int mib[3] = {CTL_HW, HW_DISKSTATS, sizeof(struct disk_sysctl)};
-  size_t sysctl_sz = NetBSD_N_Drives * sizeof(struct disk_sysctl);
+  size_t sysctl_sz = NetBSD_N_Drives * dmib[2];
+#ifdef HW_DISKSTATS
   struct disk_sysctl drive_stats[NetBSD_N_Drives];
+#endif
+#ifdef HW_IOSTATS
+  struct io_sysctl drive_stats[NetBSD_N_Drives];
+#endif
 
   // Do the sysctl.
-  if (sysctl(mib, 3, drive_stats, &sysctl_sz, NULL, 0) < 0) {
+  if (sysctl(dmib, 3, drive_stats, &sysctl_sz, NULL, 0) < 0) {
     err(1, "sysctl hw.diskstats failed");
   }
 
   // Now accumulate the total.
   unsigned long long xferred = 0;
   for (unsigned int i = 0; i < NetBSD_N_Drives; i++) {
+#ifdef HW_DISKSTATS
     xferred += drive_stats[i].dk_rbytes + drive_stats[i].dk_wbytes;
+#endif
+#ifdef HW_IOSTATS
+    if (drive_stats[i].type == IOSTAT_DISK)
+	xferred += drive_stats[i].rbytes + drive_stats[i].wbytes;
+#endif
   }
   *bytesXferred = xferred;
 #else
@@ -1016,7 +1043,7 @@
 
     while (evptr && i < NUM_INTR) {
 
-      safe_kvm_read((unsigned int)evptr, &evcnt, sizeof(evcnt));
+      safe_kvm_read((u_long)evptr, &evcnt, sizeof(evcnt));
 
       evptr = evcnt.ev_list.tqe_next;
 
@@ -1024,7 +1051,7 @@
       if (evcnt.ev_type != EVCNT_TYPE_INTR)
 	continue;
 
-      safe_kvm_read((unsigned int)evcnt.ev_name, evname, evcnt.ev_namelen);
+      safe_kvm_read((u_long)evcnt.ev_name, evname, evcnt.ev_namelen);
       // If it's a soft interrupt (has a name that starts with "soft"), skip it.
       if (!strncmp(evname, "soft", 4))
 	continue;
