Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 14 Sep 2009 11:46:43 +0000 (UTC)
From:      Rui Paulo <rpaulo@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r197190 - head/sys/dev/asmc
Message-ID:  <200909141146.n8EBkhIb050942@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: rpaulo
Date: Mon Sep 14 11:46:43 2009
New Revision: 197190
URL: http://svn.freebsd.org/changeset/base/197190

Log:
  Make the sudden motion sensor work on older models and add a bit of
  debugging.
  
  Submitted by:	Christoph Langguth <christoph at rosenkeller.org>
  MFC after:	1 week

Modified:
  head/sys/dev/asmc/asmc.c
  head/sys/dev/asmc/asmcvar.h

Modified: head/sys/dev/asmc/asmc.c
==============================================================================
--- head/sys/dev/asmc/asmc.c	Mon Sep 14 11:20:45 2009	(r197189)
+++ head/sys/dev/asmc/asmc.c	Mon Sep 14 11:46:43 2009	(r197190)
@@ -86,6 +86,10 @@ static void 	asmc_sms_handler(void *arg)
 #endif
 static void 	asmc_sms_printintr(device_t dev, uint8_t);
 static void 	asmc_sms_task(void *arg, int pending);
+#ifdef DEBUG
+void		asmc_dumpall(device_t);
+static int	asmc_key_dump(device_t, int);
+#endif
 
 /*
  * Model functions.
@@ -532,6 +536,17 @@ asmc_detach(device_t dev)
 	return (0);
 }
 
+#ifdef DEBUG
+void asmc_dumpall(device_t dev)
+{
+	int i;
+
+	/* XXX magic number */
+	for (i=0; i < 0x100; i++)
+		asmc_key_dump(dev, i);
+}
+#endif
+
 static int
 asmc_init(device_t dev)
 {
@@ -584,13 +599,17 @@ asmc_init(device_t dev)
 	asmc_key_write(dev, ASMC_KEY_SMS_FLAG, buf, 1);
 	DELAY(100);
 
+	sc->sc_sms_intr_works = 0;
+	
 	/*
-	 * Wait up to 5 seconds for SMS initialization.
+	 * Retry SMS initialization 1000 times
+	 * (takes approx. 2 seconds in worst case)
 	 */
-	for (i = 0; i < 10000; i++) {
+	for (i = 0; i < 1000; i++) {
 		if (asmc_key_read(dev, ASMC_KEY_SMS, buf, 2) == 0 && 
-		    (buf[0] != 0x00 || buf[1] != 0x00)) {
+		    (buf[0] == ASMC_SMS_INIT1 && buf[1] == ASMC_SMS_INIT2)) {
 			error = 0;
+			sc->sc_sms_intr_works = 1;
 			goto out;
 		}
 		buf[0] = ASMC_SMS_INIT1;
@@ -620,6 +639,10 @@ nosms:
 		device_printf(dev, "number of keys: %d\n", buf[3]);
 	}	      
 
+#ifdef DEBUG
+	asmc_dumpall(dev);
+#endif
+
 	return (error);
 }
 
@@ -729,6 +752,99 @@ out:
 	return (error);
 }
 
+#ifdef DEBUG
+static int
+asmc_key_dump(device_t dev, int number)
+{
+	struct asmc_softc *sc = device_get_softc(dev);
+	char key[5] = { 0 };
+	char type[7] = { 0 };
+	uint8_t index[4];
+	uint8_t v[32];
+	uint8_t maxlen;
+	int i, error = 1, try = 0;
+
+	mtx_lock_spin(&sc->sc_mtx);
+
+	index[0] = (number >> 24) & 0xff;
+	index[1] = (number >> 16) & 0xff;
+	index[2] = (number >> 8) & 0xff;
+	index[3] = (number) & 0xff;
+
+begin:
+	if (asmc_command(dev, 0x12))
+		goto out;
+
+	for (i = 0; i < 4; i++) {
+		ASMC_DATAPORT_WRITE(sc, index[i]);
+		if (asmc_wait(dev, 0x04))
+			goto out;
+	}
+
+	ASMC_DATAPORT_WRITE(sc, 4);
+
+	for (i = 0; i < 4; i++) {
+		if (asmc_wait(dev, 0x05))
+			goto out;
+		key[i] = ASMC_DATAPORT_READ(sc);
+	}
+
+	/* get type */
+	if (asmc_command(dev, 0x13))
+		goto out;
+
+	for (i = 0; i < 4; i++) {
+		ASMC_DATAPORT_WRITE(sc, key[i]);
+		if (asmc_wait(dev, 0x04))
+			goto out;
+	}
+
+	ASMC_DATAPORT_WRITE(sc, 6);
+
+	for (i = 0; i < 6; i++) {
+		if (asmc_wait(dev, 0x05))
+			goto out;
+		type[i] = ASMC_DATAPORT_READ(sc);
+	}
+
+	error = 0;
+out:
+	if (error) {
+		if (++try < 10) goto begin;
+		device_printf(dev,"%s for key %s failed %d times, giving up\n",
+			__func__, key, try);
+		mtx_unlock_spin(&sc->sc_mtx);
+	}
+	else {
+		char buf[1024];
+		char buf2[8];
+		mtx_unlock_spin(&sc->sc_mtx);
+		maxlen = type[0];
+		type[0] = ' ';
+		type[5] = 0;
+		if (maxlen > sizeof(v)) {	
+			device_printf(dev, "WARNING: cropping maxlen "
+			    "from %d to %lud\n", maxlen, sizeof(v));
+			maxlen = sizeof(v);
+		}
+		for (i = 0; i < sizeof(v); i++) {
+			v[i] = 0;
+		}
+		asmc_key_read(dev, key, v, maxlen);
+		snprintf(buf, sizeof(buf), "key %d is: %s, type %s "
+		    "(len %d), data", number, key, type, maxlen);
+		for (i = 0; i < maxlen; i++) {
+			snprintf(buf2, sizeof(buf), " %02x", v[i]);
+			strlcat(buf, buf2, sizeof(buf));
+		}
+		strlcat(buf, " \n", sizeof(buf));
+		device_printf(dev, buf);
+	}
+
+	return (error);
+}
+#endif
+
 static int
 asmc_key_write(device_t dev, const char *key, uint8_t *buf, uint8_t len)
 {
@@ -945,6 +1061,8 @@ asmc_sms_intrfast(void *arg)
 	uint8_t type;
 	device_t dev = (device_t) arg;
 	struct asmc_softc *sc = device_get_softc(dev);
+	if (!sc->sc_sms_intr_works)
+		return (FILTER_HANDLED);
 
 	mtx_lock_spin(&sc->sc_mtx);
 	type = ASMC_INTPORT_READ(sc);

Modified: head/sys/dev/asmc/asmcvar.h
==============================================================================
--- head/sys/dev/asmc/asmcvar.h	Mon Sep 14 11:20:45 2009	(r197189)
+++ head/sys/dev/asmc/asmcvar.h	Mon Sep 14 11:46:43 2009	(r197190)
@@ -49,6 +49,7 @@ struct asmc_softc {
 	int 			sc_sms_intrtype;
 	struct taskqueue 	*sc_sms_tq;
 	struct task 		sc_sms_task;
+	uint8_t			sc_sms_intr_works;
 };
 
 /*



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200909141146.n8EBkhIb050942>