Index: /lm-sensors/trunk/kernel/chips/bmcsensors.c
===================================================================
--- /lm-sensors/trunk/kernel/chips/bmcsensors.c	(revision 1615)
+++ /lm-sensors/trunk/kernel/chips/bmcsensors.c	(revision 1626)
@@ -36,5 +36,5 @@
 static unsigned short normal_i2c[] = { SENSORS_I2C_END };
 static unsigned short normal_i2c_range[] = { SENSORS_I2C_END };
-static unsigned int normal_isa[] = { 0, SENSORS_ISA_END };
+static unsigned int normal_isa[] = { SENSORS_ISA_END };
 static unsigned int normal_isa_range[] = { SENSORS_ISA_END };
 
@@ -77,4 +77,5 @@
 static void bmcsensors_init_client(struct i2c_client *client);
 static int bmcsensors_find(int *address);
+static void bmcsensors_reserve_sdr(void);
 
 
@@ -163,6 +164,9 @@
 static long msgid;		/* message ID */
 static u16 resid;
-
-enum states {STATE_INIT, STATE_RESERVE, STATE_SDR, STATE_SDRPARTIAL, STATE_READING, STATE_DONE};
+static u16 nextrecord;
+int errorcount;
+
+enum states {STATE_INIT, STATE_RESERVE, STATE_SDR, STATE_SDRPARTIAL,
+             STATE_READING, STATE_UNCANCEL, STATE_DONE};
 int state;
 static int receive_counter;
@@ -184,9 +188,8 @@
 #define STYPE_FAN	0x04
 
-/* get rid of this ***************/
-#define STYPE_MAX	0x29		/* the last sensor type we are interested in */
-static u8 bmcs_count[STYPE_MAX + 1] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-static const u8 bmcs_max[STYPE_MAX + 1] = {
-0, 10, 10, 10, 10, 0, 0, 0}; /* more zeros*/
+/* do we really need maximums per-type? */
+#define STYPE_MAX	4		/* the last sensor type we are interested in */
+static u8 bmcs_count[STYPE_MAX + 1] = {0,0,0,0,0};
+static const u8 bmcs_max[STYPE_MAX + 1] = {0, 20, 20, 20, 20};
 
 /************************************/
@@ -293,19 +296,19 @@
 		printk(KERN_INFO "bmcsensors.o: sensor %d: using %s for upper limit\n",
 			i, threshold_text[sdrd[i].lim1]);
-/*
+#ifdef DEBUG
 	else
 		printk(KERN_INFO "bmcsensors.o: sensor %d: no readable upper limit\n", i);
-*/
+#endif
 	if(sdrd[i].lim2 >= 0)
 		printk(KERN_INFO "bmcsensors.o: sensor %d: using %s for lower limit\n",
 			i, threshold_text[sdrd[i].lim2]);
-/*
+#ifdef DEBUG
 	else
 		printk(KERN_INFO "bmcsensors.o: sensor %d: no readable lower limit\n", i);
-*/
+#endif
 }
 
 /* After we have received all the SDR entries and picked out the ones
-   we are interested in, build a table of the /proc entries and register.
+   we are interested in, build a table of the /proc entries and register with i2c.
 */
 static void bmcsensors_build_proc_table()
@@ -365,5 +368,5 @@
 			sdrd[i].m, sdrd[i].b,sdrd[i].k & 0xf, sdrd[i].k >> 4,
 			sdrd[i].capab, sdrd[i].thresh_mask);
-		if(sdrd[i].id_length) {
+		if(sdrd[i].id_length > 0) {
 			ipmi_sprintf(id, sdrd[i].id, sdrd[i].string_type, sdrd[i].id_length);
 			printk(KERN_INFO "bmcsensors.o: sensors.conf: label %s \"%s\"\n",
@@ -372,12 +375,15 @@
 		bmcsensors_select_thresholds(i);
 		if(sdrd[i].linear != 0) {
-			printk(KERN_INFO "bmcsensors.o: sensor %d: nonlinear function 0x%.2x unsupported\n",
-				i, sdrd[i].linear);
+			printk(KERN_INFO
+			       "bmcsensors.o: sensor %d: nonlinear function 0x%.2x unsupported, expect bad results\n",
+			       i, sdrd[i].linear);
 		}
 		if((sdrd[i].format & 0x03) == 0x02) {
-			printk(KERN_INFO "bmcsensors.o: sensor %d: 1's complement format unsupported\n",
+			printk(KERN_INFO
+			       "bmcsensors.o: sensor %d: 1's complement format unsupported, expect bad results\n",
 				i);
 		} else if((sdrd[i].format & 0x03) == 0x03) {
-			printk(KERN_INFO "bmcsensors.o: sensor %d: threshold sensor only, no readings available",
+			printk(KERN_INFO
+			       "bmcsensors.o: sensor %d: threshold sensor only, no readings available",
 				i);
 		}
@@ -390,6 +396,6 @@
 
 	if ((i = i2c_register_entry(&bmc_client, "bmc",
-					bmcsensors_dir_table,
-					THIS_MODULE)) < 0) {
+				    bmcsensors_dir_table,
+				    THIS_MODULE)) < 0) {
 		printk(KERN_INFO "bmcsensors.o: i2c registration failed.\n");
 		kfree(bmcsensors_dir_table);
@@ -426,13 +432,14 @@
 		return STATE_DONE;
 	}
-	bmcsensors_get_reading(&bmc_client, receive_counter); /* don't really need to pass client */
+	/* don't really need to pass client */
+	bmcsensors_get_reading(&bmc_client, receive_counter);
 	return STATE_READING; 
 }
 
-/* Process a SDR response */
+/* Process an SDR response, save the SDR's we like in the sdrd table */
 static int bmcsensors_rcv_sdr_msg(struct ipmi_msg *msg, int state)
 {
-	u16 record, nextrecord;
-	int version, type, length, owner, lun, number, entity, instance, init;
+	u16 record;
+	int type, length, owner, lun, number, entity, instance, init;
 	int stype, code;
 	int id_length;
@@ -441,4 +448,5 @@
 	struct ipmi_msg txmsg;
 	unsigned char * data;
+	u8 id[SDR_MAX_UNPACKED_ID_LENGTH];
 
 
@@ -450,5 +458,7 @@
 			return STATE_DONE;
 		}
+#ifdef DEBUG
 		printk(KERN_INFO "bmcsensors.o: Reducing SDR request size to %d\n", ipmi_sdr_partial_size);
+#endif
 		bmcsensors_get_sdr(resid, 0, 0);
 		return STATE_SDR;
@@ -477,8 +487,8 @@
 
 	nextrecord = (data[2] << 8) | data[1];
-	version = data[5];
 	type = data[6];
 	if(type == 1 || type == 2) {		/* known SDR type */
 /*
+		version = data[5];
 		owner = data[8];
 		lun = data[9];
@@ -487,69 +497,102 @@
 */
 		stype = data[15];
-
 		if(stype <= STYPE_MAX) {	/* known sensor type */
 			if(bmcs_count[stype] >= bmcs_max[stype]) {
-				if(bmcs_max[stype] > 0) {
-					printk(KERN_INFO "bmcsensors.o: Limit of %d exceeded for sensor type 0x%x\n", bmcs_max[stype], stype);
+				if(bmcs_max[stype] > 0)
+					printk(KERN_INFO
+					       "bmcsensors.o: Limit of %d exceeded for sensor type 0x%x\n",
+					       bmcs_max[stype], stype);
 #ifdef DEBUG
+				else
+					printk(KERN_INFO
+					       "bmcsensors.o: Ignoring unsupported sensor type 0x%x\n",
+					       stype);
+#endif
+			} else if(sdrd_count >= MAX_SDR_ENTRIES) {
+				printk(KERN_INFO
+				       "bmcsensors.o: Limit of %d exceeded for total sensors\n",
+				       MAX_SDR_ENTRIES);
+				nextrecord = 0xffff;
+			} else if(data[16] != 0x01) {
+				if(type == 1)
+					ipmi_sprintf(id, &data[51], data[50] >> 6, data[50] & 0x1f);
+				else
+					ipmi_sprintf(id, &data[35], data[34] >> 6, data[34] & 0x1f);
+				printk(KERN_INFO
+				       "bmcsensors.o: skipping non-threshold sensor \"%s\"\n",
+				       id);
+			} else {
+				/* add entry to sdrd table */
+				sdrd[sdrd_count].stype = stype;
+				sdrd[sdrd_count].number = data[10];
+				sdrd[sdrd_count].capab = data[14];
+				sdrd[sdrd_count].thresh_mask = (((u16) data[22]) << 8) | data[21];
+				if(type == 1) {
+					sdrd[sdrd_count].format = data[24] >> 6;
+					sdrd[sdrd_count].linear = data[26] & 0x7f;
+					sdrd[sdrd_count].m = data[27];
+					sdrd[sdrd_count].m |= ((u16) (data[28] & 0xc0)) << 2;
+					if(sdrd[sdrd_count].m & 0x0200)
+						sdrd[sdrd_count].m |= 0xfc00;	/* sign extend */
+					sdrd[sdrd_count].b = data[29];
+					sdrd[sdrd_count].b |= ((u16) (data[30] & 0xc0)) << 2;
+					if(sdrd[sdrd_count].b & 0x0200)
+						sdrd[sdrd_count].b |= 0xfc00;	/* sign extend */
+					sdrd[sdrd_count].k = data[32];
+					sdrd[sdrd_count].nominal = data[34];
+					for(i = 0; i < SDR_LIMITS; i++)		/* assume readable */
+						sdrd[sdrd_count].limits[i] = data[39 + i];
+					sdrd[sdrd_count].string_type = data[50] >> 6;
+					id_length = data[50] & 0x1f;
+					memcpy(sdrd[sdrd_count].id, &data[51], id_length);
+					sdrd[sdrd_count].id_length = id_length;
 				} else {
-					printk(KERN_INFO "bmcsensors.o: Ignoring unsupported sensor type 0x%x\n", stype);
-#endif
+					sdrd[sdrd_count].m = 1;
+					sdrd[sdrd_count].b = 0;
+					sdrd[sdrd_count].k = 0;
+					sdrd[sdrd_count].string_type = data[34] >> 6;
+					id_length = data[34] & 0x1f;
+					if(id_length > 0)
+						memcpy(sdrd[sdrd_count].id, &data[35], id_length);
+					sdrd[sdrd_count].id_length = id_length;
+					/* limits?? */
 				}
-			} else {
-				if(sdrd_count >= MAX_SDR_ENTRIES) {
-					printk(KERN_INFO "bmcsensors.o: Limit of %d exceeded for total sensors\n", MAX_SDR_ENTRIES);
-				} else {
-					/* add SDR database entry */
-					sdrd[sdrd_count].stype = stype;
-					sdrd[sdrd_count].number = data[10];
-					sdrd[sdrd_count].capab = data[14];
-					sdrd[sdrd_count].thresh_mask = (data[22] << 8) | data[21];
-					if(type == 1) {
-						sdrd[sdrd_count].format = data[24] >> 6;
-						sdrd[sdrd_count].linear = data[26] & 0x7f;
-						sdrd[sdrd_count].m = data[27];
-						sdrd[sdrd_count].m |= ((u16) (data[28] & 0xc0)) << 2;
-						if(sdrd[sdrd_count].m & 0x0200)
-							sdrd[sdrd_count].m |= 0xfc00;	/* sign extend */
-						sdrd[sdrd_count].b = data[29];
-						sdrd[sdrd_count].b |= ((u16) (data[30] & 0xc0)) << 2;
-						if(sdrd[sdrd_count].b & 0x0200)
-							sdrd[sdrd_count].b |= 0xfc00;	/* sign extend */
-						sdrd[sdrd_count].k = data[32];
-						sdrd[sdrd_count].nominal = data[34];
-						for(i = 0; i < SDR_LIMITS; i++)		/* assume readable */
-							sdrd[sdrd_count].limits[i] = data[39 + i];
-						sdrd[sdrd_count].string_type = data[50] >> 6;
-						id_length = data[50] & 0x1f;
-						if(id_length > 0)
-							memcpy(sdrd[sdrd_count].id, &data[51], id_length);
-						sdrd[sdrd_count].id_length = id_length;
-					} else {
-						sdrd[sdrd_count].m = 1;
-						sdrd[sdrd_count].b = 0;
-						sdrd[sdrd_count].k = 0;
-						sdrd[sdrd_count].string_type = data[34] >> 6;
-						id_length = data[34] & 0x1f;
-						if(id_length > 0)
-							memcpy(sdrd[sdrd_count].id, &data[35], id_length);
-						sdrd[sdrd_count].id_length = id_length;
-						/* limits?? */
-					}
-					bmcs_count[stype]++;
-					sdrd_count++;
-				}
+				bmcs_count[stype]++;
+				sdrd_count++;
 			}
 		}
+#ifdef DEBUG
+	/* peek at the other SDR types */
+	} else if(type == 0x10 || type == 0x11 || type == 0x12) {
+		ipmi_sprintf(id, data + 19, data[18]>>6, data[18] & 0x1f);
+		if(type == 0x10) {
+			printk(KERN_INFO "bmcsensors.o: Generic Device acc=0x%x; slv=0x%x; lun=0x%x; type=0x%x; \"%s\"\n",
+				data[8], data[9], data[10], data[13], id);
+		else if(type == 0x11) {
+			printk(KERN_INFO "bmcsensors.o: FRU Device acc=0x%x; slv=0x%x; log=0x%x; ch=0x%x; type=0x%x; \"%s\"\n",
+				data[8], data[9], data[10], data[11], data[13], id);
+		} else {
+			printk(KERN_INFO "bmcsensors.o: Mgmt Ctllr Device slv=0x%x; \"%s\"\n",
+				data[8], id);
+		}
+	} else if(type == 0x14) {
+		printk(KERN_INFO "bmcsensors.o: Message Channel Info Records:\n");
+		for(i = 0; i < 8; i++) {
+			printk(KERN_INFO "bmcsensors.o: Channel %d info 0x%x\n",
+				i, data[9 + i]);
+		}
+	} else {
+		printk(KERN_INFO "bmcsensors.o: Skipping SDR type 0x%x\n", type);
+#endif
 	}
 			
 	if(nextrecord == 0xFFFF) {
-		rstate = STATE_READING;
 		if(sdrd_count == 0) {
 			printk(KERN_INFO "bmcsensors.o: No recognized sensors found.\n");
+			rstate = STATE_DONE;
+			/* unregister?? */
 		} else {
-			printk(KERN_INFO "bmcsensors.o: found %d temp, %d volt, %d current, %d fan sensors\n",
-bmcs_count[1], bmcs_count[2], bmcs_count[3], bmcs_count[4]);
 			bmcsensors_build_proc_table();
+			rstate = STATE_READING;
 		}
 	} else {
@@ -566,5 +609,8 @@
 		case STATE_INIT:
 		case STATE_RESERVE:
-			resid = (msg->data[2] << 8) || msg->data[1];
+			resid = (((u16)msg->data[2]) << 8) || msg->data[1];
+#ifdef DEBUG
+			printk(KERN_INFO "bmcsensors.o: Got first resid 0x%.4x\n", resid);
+#endif
 			bmcsensors_get_sdr(resid, 0, 0);
 			state = STATE_SDR;
@@ -580,4 +626,14 @@
 			break;
 
+		case STATE_UNCANCEL:
+			resid = (((u16)msg->data[2]) << 8) || msg->data[1];
+#ifdef DEBUG
+			printk(KERN_INFO "bmcsensors.o: Got new resid 0x%.4x\n", resid);
+#endif
+			rx_msg_data_offset = 0;
+			bmcsensors_get_sdr(resid, nextrecord, 0);
+			state = STATE_SDR;
+			break;
+
 		case STATE_DONE:
 			break;
@@ -593,7 +649,18 @@
 				   void * handler_data)
 {
-	if (msg->msg.data[0] != 0 && msg->msg.data[0] != 0xca) {
-		printk(KERN_ERR "BMCsensors response: Error %x on cmd %x; state = %d; probably fatal.\n",
-		       msg->msg.data[0], msg->msg.cmd, state);
+	if(state == STATE_SDR && msg->msg.data[0] == 0xc5) {
+		/* )(*&@(*&#@$ reservation cancelled, get new resid */
+		if(errorcount++ > 200) {
+			printk(KERN_ERR
+			       "bmcsensors.o: Too many reservations cancelled, giving up\n");
+			state = STATE_DONE;
+		} else {
+			bmcsensors_reserve_sdr();
+			state = STATE_UNCANCEL;
+		}
+	} else if (msg->msg.data[0] != 0 && msg->msg.data[0] != 0xca) {
+		printk(KERN_ERR
+		       "bmcsensors.o: Error 0x%x on cmd 0x%x/0x%x; state = %d; probably fatal.\n",
+		       msg->msg.data[0], msg->msg.netfn & 0xfe, msg->msg.cmd, state);
 	} else {
 		bmcsensors_rcv_msg(&(msg->msg));
@@ -611,7 +678,4 @@
 		       msg->cmd);
 #endif
-/*
-	bmcclient_i2c_send_message(&bmc_client, msgid++, msg);
-*/
 	bmc_client.adapter->algo->slave_send((struct i2c_adapter *) &bmc_client,
 	                                     (char *) msg, msgid++);
