--- ipmitool-1.8.11/lib/dimm_spd.c	2009-02-25 15:38:52.000000000 -0500
+++ ipmitool-1.8.11-spdfix/lib/dimm_spd.c	2009-03-31 23:34:24.000000000 -0400
@@ -60,6 +60,37 @@
 	{ 0x06, "DDR SGRAM" },
 	{ 0x07, "DDR SDRAM" },
 	{ 0x08, "DDR2 SDRAM" },
+	{ 0x09, "DDR2 SDRAM FB-DIMM" },
+	{ 0x0A, "DDR2 SDRAM FB-DIMM Probe" },
+	{ 0x0B, "DDR3 SDRAM" },
+	{ 0x00, NULL },
+};
+
+const struct valstr ddr3_density_vals[] = 
+{
+	{ 0, "256 Mb" },
+	{ 1, "512 Mb" },
+	{ 2, "1 Gb" },
+	{ 3, "2 Gb" },
+	{ 4, "4 Gb" },
+	{ 5, "8 Gb" },
+	{ 6, "16 Gb" },
+	{ 0x00, NULL },
+};
+
+const struct valstr ddr3_banks_vals[] =
+{
+	{ 0, "3 (8 Banks)" },
+	{ 1, "4 (16 Banks)" },
+	{ 2, "5 (32 Banks)" },
+	{ 3, "6 (64 Banks)" },
+	{ 0x00, NULL },
+};
+
+const struct valstr ddr3_ecc_vals[] =
+{
+	{ 0, "0 bits" },
+	{ 1, "8 bits" },
 	{ 0x00, NULL },
 };
 
@@ -693,51 +724,128 @@
 	if (len < 92)
 		return -1; /* we need first 91 bytes to do our thing */
 
-	size = spd_data[5] * (spd_data[31] << 2);
-	printf(" Memory Size           : %d MB\n", size);
 	printf(" Memory Type           : %s\n",
 	       val2str(spd_data[2], spd_memtype_vals));
-	printf(" Voltage Intf          : %s\n",
-	       val2str(spd_data[8], spd_voltage_vals));
-	printf(" Error Detect/Cor      : %s\n",
-	       val2str(spd_data[11], spd_config_vals));
-
-	/* handle jedec table bank continuation values */
-	printf(" Manufacturer          : ");
-	if (spd_data[64] != 0x7f)
-		printf("%s\n",
-		       val2str(spd_data[64], jedec_id1_vals));
-	else {
-		if (spd_data[65] != 0x7f)
+	
+	if (spd_data[2] == 0x0B)	/* DDR3 SDRAM */
+	{
+		int iPN;
+		char *pchPN = spd_data+128;
+		int sdram_cap = 0;
+		int pri_bus_width = 0;
+		int sdram_width = 0;
+		int ranks = 0;
+		int mem_size = 0;
+
+		if (len < 148)
+			return -1; /* we need first 91 bytes to do our thing */
+	
+
+		sdram_cap = ldexp(256,(spd_data[4]&15));
+		pri_bus_width = ldexp(8,(spd_data[8]&7));
+		sdram_width = ldexp(4,(spd_data[7]&7));
+		ranks = ldexp(1,((spd_data[7]&0x3F)>>3));
+		mem_size = (sdram_cap/8) * (pri_bus_width/sdram_width) * ranks;
+		printf(" SDRAM Capacity        : %d MB\n", sdram_cap );
+		printf(" Memory Banks          : %s\n", val2str(spd_data[4]>>4, ddr3_banks_vals));
+		printf(" Primary Bus Width     : %d bits\n", pri_bus_width );
+		printf(" SDRAM Device Width    : %d bits\n", sdram_width );
+		printf(" Number of Ranks       : %d\n", ranks );
+		printf(" Memory size           : %d MB\n", mem_size );
+		
+		/* printf(" Memory Density        : %s\n", val2str(spd_data[4]&15, ddr3_density_vals)); */
+		printf(" 1.5 V Nominal Op      : %s\n", (((spd_data[6]&1) != 0) ? "No":"Yes" ) );
+		printf(" 1.35 V Nominal Op     : %s\n", (((spd_data[6]&2) != 0) ? "No":"Yes" ) );
+		printf(" 1.2X V Nominal Op     : %s\n", (((spd_data[6]&4) != 0) ? "No":"Yes" ) );
+		printf(" Error Detect/Cor      : %s\n", val2str(spd_data[8]>>3, ddr3_ecc_vals));
+
+		printf(" Manufacturer          : ");
+		switch (spd_data[117]&127)
+		{
+		case	0:
+			printf("%s\n", val2str(spd_data[118], jedec_id1_vals));
+			break;
+
+		case	1:
+			printf("%s\n", val2str(spd_data[118], jedec_id2_vals));
+			break;
+
+		case	2:
+			printf("%s\n", val2str(spd_data[118], jedec_id3_vals));
+			break;
+
+		case	3:
+			printf("%s\n", val2str(spd_data[118], jedec_id4_vals));
+			break;
+
+		case	4:
+			printf("%s\n", val2str(spd_data[118], jedec_id5_vals));
+			break;
+
+		default:
+			printf("%s\n", "JEDEC JEP106 update required" );
+
+		}
+
+		printf(" Manufacture Date      : year %c%c week %c%c\n", 
+		'0'+(spd_data[120]>>4), '0'+(spd_data[120]&15), '0'+(spd_data[121]>>4), '0'+(spd_data[121]&15) );
+	
+		printf(" Serial Number         : %02x%02x%02x%02x\n",
+		spd_data[122], spd_data[123], spd_data[124], spd_data[125]);
+	
+		printf(" Part Number           : ");
+		for (iPN=0; iPN < 19; iPN++)
+		{	
+			printf( "%c", *pchPN++ );
+		}
+		printf("\n");
+	}
+	else
+	{
+		size = spd_data[5] * (spd_data[31] << 2);
+		printf(" Memory Size           : %d MB\n", size);
+		printf(" Voltage Intf          : %s\n",
+		val2str(spd_data[8], spd_voltage_vals));
+		printf(" Error Detect/Cor      : %s\n",
+		val2str(spd_data[11], spd_config_vals));
+	
+		/* handle jedec table bank continuation values */
+		printf(" Manufacturer          : ");
+		if (spd_data[64] != 0x7f)
 			printf("%s\n",
-			       val2str(spd_data[65], jedec_id2_vals));
+			val2str(spd_data[64], jedec_id1_vals));
 		else {
-			if (spd_data[66] != 0x7f)
+			if (spd_data[65] != 0x7f)
 				printf("%s\n",
-				       val2str(spd_data[66], jedec_id3_vals));
+				val2str(spd_data[65], jedec_id2_vals));
 			else {
-				if (spd_data[67] != 0x7f)
-					printf("%s\n",
-					       val2str(spd_data[67],
-						       jedec_id4_vals));
-				else
+				if (spd_data[66] != 0x7f)
 					printf("%s\n",
-					       val2str(spd_data[68],
-						       jedec_id5_vals));
+					val2str(spd_data[66], jedec_id3_vals));
+				else {
+					if (spd_data[67] != 0x7f)
+						printf("%s\n",
+						val2str(spd_data[67],
+							jedec_id4_vals));
+					else
+						printf("%s\n",
+						val2str(spd_data[68],
+							jedec_id5_vals));
+				}
 			}
 		}
-	}
 
-	if (spd_data[73]) {
-		char part[19];
-		memcpy(part, spd_data+73, 18);
-		part[18] = 0;
-		printf(" Part Number           : %s\n", part);
+		if (spd_data[73]) {
+			char part[19];
+			memcpy(part, spd_data+73, 18);
+			part[18] = 0;
+			printf(" Part Number           : %s\n", part);
+		}
+	
+		printf(" Serial Number         : %02x%02x%02x%02x\n",
+		spd_data[95], spd_data[96], spd_data[97], spd_data[98]);
 	}
 
-	printf(" Serial Number         : %02x%02x%02x%02x\n",
-	       spd_data[95], spd_data[96], spd_data[97], spd_data[98]);
-
 	if (verbose) {
 		printf("\n");
 		printbuf(spd_data, len, "SPD DATA");
