--- eeprom/decode-dimms.orig	2014-06-19 15:50:29.000000000 -0400
+++ eeprom/decode-dimms	2014-06-19 16:18:34.000000000 -0400
@@ -42,7 +42,7 @@
 use Fcntl qw(:DEFAULT :seek);
 use File::Basename;
 use vars qw($opt_html $opt_bodyonly $opt_side_by_side $opt_merge
-	    $opt_igncheck $use_sysfs $use_hexdump $sbs_col_width
+	    $opt_igncheck $opt_smbdev $use_smbdev $use_hexdump $sbs_col_width
 	    @vendors %decode_callback $revision @dimm $current %hexdump_cache);
 
 use constant LITTLEENDIAN	=> "little-endian";
@@ -305,7 +305,7 @@
  "Silicon Space Technology"]
 );
 
-$use_sysfs = -d '/sys/bus';
+$use_smbdev = '/dev/smb0';
 
 # We consider that no data was written to this area of the SPD EEPROM if
 # all bytes read 0x00 or all bytes read 0xff
@@ -1079,6 +1079,9 @@
 	printl("Module Configuration Type",
 	       sdram_module_configuration_type($bytes->[11]));
 
+	printl("Module Configuration Type",
+	       sdram_module_configuration_type($bytes->[11]));
+
 	printl("Refresh Rate", ddr2_refresh_rate($bytes->[12]));
 
 	my @burst;
@@ -1289,8 +1292,9 @@
 	printl("DLL-Off Mode supported?", ($bytes->[30] & 128) ? "Yes" : "No");
 	printl("Operating temperature range", sprintf "0-%d degrees C",
 		($bytes->[31] & 1) ? 95 : 85);
-	printl("Refresh Rate in extended temp range",
-		($bytes->[31] & 2) ? "2X" : "1X");
+	printl_cond($bytes->[31] & 1,
+		    "Refresh Rate in extended temp range",
+		    ($bytes->[31] & 2) ? "1X" : "2X");
 	printl("Auto Self-Refresh?", ($bytes->[31] & 4) ? "Yes" : "No");
 	printl("On-Die Thermal Sensor readout?",
 		($bytes->[31] & 8) ? "Yes" : "No");
@@ -1624,6 +1628,28 @@
 	}
 }
 
+sub freebsd_readbyte ($$) {
+	my ($offset, $dimm_i) = @_;
+
+	my $command = sprintf('/usr/sbin/smbmsg -f %s -s %#02x -c %d -i 1 -F %%02x 2>/dev/null',
+			      $use_smbdev, $dimm_i, $offset);
+	my $output = `$command`;
+	chomp($output);
+	my $byte = hex($output);
+	return $byte;
+}
+
+sub freebsd_readword ($$) {
+	my ($offset, $dimm_i) = @_;
+
+	my $command = sprintf('/usr/sbin/smbmsg -f %s -s %#02x -c %d -w -i 2 -F %%04x 2>/dev/null',
+			      $use_smbdev, $dimm_i, $offset);
+	my $output = `$command`;
+	chomp($output);
+	my $word = hex($output);
+	return $word;
+}
+
 # Read bytes from SPD-EEPROM
 # Note: offset must be a multiple of 16!
 sub readspd($$$)
@@ -1633,22 +1659,14 @@
 	if ($use_hexdump) {
 		@bytes = read_hexdump($dimm_i);
 		return @bytes[$offset..($offset + $size - 1)];
-	} elsif ($use_sysfs) {
-		# Kernel 2.6 with sysfs
-		sysopen(HANDLE, "$dimm_i/eeprom", O_RDONLY)
-			or die "Cannot open $dimm_i/eeprom";
-		binmode HANDLE;
-		sysseek(HANDLE, $offset, SEEK_SET)
-			or die "Cannot seek $dimm_i/eeprom";
-		sysread(HANDLE, my $eeprom, $size)
-			or die "Cannot read $dimm_i/eeprom";
-		close HANDLE;
-		@bytes = unpack("C*", $eeprom);
 	} else {
-		# Kernel 2.4 with procfs
-		for my $i (0 .. ($size-1)/16) {
-			my $hexoff = sprintf('%02x', $offset + $i * 16);
-			push @bytes, split(" ", `cat $dimm_i/$hexoff`);
+#		for my $i (0 .. ($size - 1)) {
+#			push (@bytes, freebsd_readbyte($offset + $i, $dimm_i));
+#		}
+		for my $i (0 .. (($size - 1) / 2)) {
+			my $word = freebsd_readword($offset + 2 * $i, $dimm_i);
+			push (@bytes, $word & 0xff);
+			push (@bytes, $word >> 8);
 		}
 	}
 	return @bytes;
@@ -1702,7 +1720,7 @@
 # Parse command-line
 foreach (@ARGV) {
 	if ($_ eq '-h' || $_ eq '--help') {
-		print "Usage: $0 [-c] [-f [-b]] [-x|-X file [files..]]\n",
+		print "Usage: $0 [-c] [-f [-b]] [-d|-x|-X file [files..]]\n",
 			"       $0 -h\n\n",
 			"  -f, --format            Print nice html output\n",
 			"  -b, --bodyonly          Don't print html header\n",
@@ -1711,6 +1729,7 @@
 			"      --merge-cells       Merge neighbour cells with identical values\n",
 			"                          (side-by-side output only)\n",
 			"  -c, --checksum          Decode completely even if checksum fails\n",
+			"  -d,                     Read data from the device\n",
 			"  -x,                     Read data from hexdump files\n",
 			"  -X,                     Same as -x except treat multibyte hex\n",
 			"                          data as little endian\n",
@@ -1746,6 +1765,10 @@
 		$opt_igncheck = 1;
 		next;
 	}
+	if ($_ eq '-d') {
+		$opt_smbdev = 1;
+		next;
+	}
 	if ($_ eq '-x') {
 		$use_hexdump = BIGENDIAN;
 		next;
@@ -1760,7 +1783,11 @@
 		exit;
 	}
 
-	push @dimm, { eeprom => basename($_), file => $_ } if $use_hexdump;
+	if ($opt_smbdev) {
+		$use_smbdev = $_;
+	} else {
+		push @dimm, { eeprom => basename($_), file => $_ } if $use_hexdump;
+	}
 }
 
 if ($opt_html && !$opt_bodyonly) {
@@ -1777,61 +1804,20 @@
 Jean Delvare, Trent Piepho and others');
 
 
-# From a sysfs device path and an attribute name, return the attribute
-# value, or undef (stolen from sensors-detect)
-sub sysfs_device_attribute
-{
-	my ($device, $attr) = @_;
-	my $value;
-
-	open(local *FILE, "$device/$attr") or return "";
-	$value = <FILE>;
-	close(FILE);
-	return unless defined $value;
-
-	chomp($value);
-	return $value;
-}
-
 sub get_dimm_list
 {
-	my (@dirs, $dir, $opened, $file, @files);
-
-	if ($use_sysfs) {
-		@dirs = ('/sys/bus/i2c/drivers/eeprom', '/sys/bus/i2c/drivers/at24');
-	} else {
-		@dirs = ('/proc/sys/dev/sensors');
-	}
-
-	foreach $dir (@dirs) {
-		next unless opendir(local *DIR, $dir);
-		$opened++;
-		while (defined($file = readdir(DIR))) {
-			if ($use_sysfs) {
-				# We look for I2C devices like 0-0050 or 2-0051
-				next unless $file =~ /^\d+-[\da-f]+$/i;
-				next unless -d "$dir/$file";
-
-				# Device name must be eeprom (driver eeprom)
-				# or spd (driver at24)
-				my $attr = sysfs_device_attribute("$dir/$file", "name");
-				next unless defined $attr &&
-					    ($attr eq "eeprom" || $attr eq "spd");
-			} else {
-				next unless $file =~ /^eeprom-/;
-			}
-			push @files, { eeprom => "$file",
-				       file => "$dir/$file" };
-		}
-		close(DIR);
-	}
-
-	if (!$opened) {
-		print STDERR "No EEPROM found, try loading the eeprom or at24 module\n";
-		exit;
+	my @dimms;
+	if (! -c $use_smbdev) {
+        	print "SMBus device not found\n";
+	        exit;
+	}
+	for my $spd (0xA0 .. 0xAE) {
+		next if ($spd % 2 != 0);
+		my @test_bytes = readspd(0, 4, $spd);
+		next unless spd_written(@test_bytes);
+		push @dimms, { eeprom => sprintf('0x%02X', $spd), file => $spd };
 	}
-
-	return sort { $a->{file} cmp $b->{file} } @files;
+	return @dimms;
 }
 
 # @dimm is a list of hashes. There's one hash for each EEPROM we found.
@@ -2022,7 +2008,7 @@
 		print "\n\n";
 	} else {
 		print "<b><u>" if $opt_html;
-		printl2("\n\nDecoding EEPROM", $dimm[$current]->{file});
+		printl2("\n\nDecoding EEPROM", $dimm[$current]->{eeprom});
 		print "</u></b>" if $opt_html;
 	}
 	print "<table border=1>\n" if $opt_html;