Module Name:    src
Committed By:   riastradh
Date:           Tue Apr  1 17:49:05 UTC 2014

Modified Files:
        src/sys/dev/ic: apple_smc.c apple_smc_fan.c apple_smc_temp.c
            apple_smcvar.h

Log Message:
Polish the Apple SMC code with commentary and little fixes.


To generate a diff of this commit:
cvs rdiff -u -r1.3 -r1.4 src/sys/dev/ic/apple_smc.c \
    src/sys/dev/ic/apple_smc_fan.c src/sys/dev/ic/apple_smc_temp.c \
    src/sys/dev/ic/apple_smcvar.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/ic/apple_smc.c
diff -u src/sys/dev/ic/apple_smc.c:1.3 src/sys/dev/ic/apple_smc.c:1.4
--- src/sys/dev/ic/apple_smc.c:1.3	Tue Apr  1 17:48:52 2014
+++ src/sys/dev/ic/apple_smc.c	Tue Apr  1 17:49:05 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: apple_smc.c,v 1.3 2014/04/01 17:48:52 riastradh Exp $	*/
+/*	$NetBSD: apple_smc.c,v 1.4 2014/04/01 17:49:05 riastradh Exp $	*/
 
 /*
  * Apple System Management Controller
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: apple_smc.c,v 1.3 2014/04/01 17:48:52 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: apple_smc.c,v 1.4 2014/04/01 17:49:05 riastradh Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -75,12 +75,12 @@ void
 apple_smc_attach(struct apple_smc_tag *smc)
 {
 
-	mutex_init(&smc->smc_lock, MUTEX_DEFAULT, IPL_NONE);
-
+	mutex_init(&smc->smc_io_lock, MUTEX_DEFAULT, IPL_NONE);
 #if 0				/* XXX sysctl */
 	apple_smc_sysctl_setup(smc);
 #endif
 
+	/* Attach any children.  */
         (void)apple_smc_rescan(smc, APPLE_SMC_BUS, NULL);
 }
 
@@ -89,6 +89,7 @@ apple_smc_detach(struct apple_smc_tag *s
 {
 	int error;
 
+	/* Fail if we can't detach all our children.  */
 	error = config_detach_children(smc->smc_dev, flags);
 	if (error)
 		return error;
@@ -96,6 +97,7 @@ apple_smc_detach(struct apple_smc_tag *s
 #if 0				/* XXX sysctl */
 	sysctl_teardown(&smc->smc_log);
 #endif
+	mutex_destroy(&smc->smc_io_lock);
 
 	return 0;
 }
@@ -105,6 +107,7 @@ apple_smc_rescan(struct apple_smc_tag *s
     const int *locators)
 {
 
+	/* Let autoconf(9) do the work of finding new children.  */
 	(void)config_search_loc(&apple_smc_search, smc->smc_dev, APPLE_SMC_BUS,
 	    locators, smc);
 	return 0;
@@ -154,6 +157,7 @@ void
 apple_smc_child_detached(struct apple_smc_tag *smc __unused,
     device_t child __unused)
 {
+	/* We keep no books about our children.  */
 }
 
 static uint8_t
@@ -181,8 +185,12 @@ apple_smc_read_data(struct apple_smc_tag
 	uint8_t status;
 	unsigned int i;
 
-	KASSERT(mutex_owned(&smc->smc_lock));
+	KASSERT(mutex_owned(&smc->smc_io_lock));
 
+	/*
+	 * Wait until the status register says there's data to read and
+	 * read it.
+	 */
 	for (i = 0; i < 100; i++) {
 		status = apple_smc_bus_read_1(smc, APPLE_SMC_CSR);
 		if (status & APPLE_SMC_STATUS_READ_READY) {
@@ -201,14 +209,20 @@ apple_smc_write(struct apple_smc_tag *sm
 	uint8_t status;
 	unsigned int i;
 
-	KASSERT(mutex_owned(&smc->smc_lock));
+	KASSERT(mutex_owned(&smc->smc_io_lock));
 
+	/*
+	 * Write the byte and then wait until the status register says
+	 * it has been accepted.
+	 */
 	apple_smc_bus_write_1(smc, reg, byte);
 	for (i = 0; i < 100; i++) {
 		status = apple_smc_bus_read_1(smc, APPLE_SMC_CSR);
 		if (status & APPLE_SMC_STATUS_WRITE_ACCEPTED)
 			return 0;
 		DELAY(100);
+
+		/* Write again if it hasn't been acknowledged at all.  */
 		if (!(status & APPLE_SMC_STATUS_WRITE_PENDING))
 			apple_smc_bus_write_1(smc, reg, byte);
 	}
@@ -237,18 +251,21 @@ apple_smc_begin(struct apple_smc_tag *sm
 	unsigned int i;
 	int error;
 
-	KASSERT(mutex_owned(&smc->smc_lock));
+	KASSERT(mutex_owned(&smc->smc_io_lock));
 
+	/* Write the command first.  */
 	error = apple_smc_write_cmd(smc, cmd);
 	if (error)
 		return error;
 
+	/* Write the key next.  */
 	for (i = 0; i < 4; i++) {
 		error = apple_smc_write_data(smc, key[i]);
 		if (error)
 			return error;
 	}
 
+	/* Finally, report how many bytes of data we want to send/receive.  */
 	error = apple_smc_write_data(smc, size);
 	if (error)
 		return error;
@@ -264,11 +281,15 @@ apple_smc_input(struct apple_smc_tag *sm
 	uint8_t i;
 	int error;
 
-	mutex_enter(&smc->smc_lock);
+	/* Grab the SMC I/O lock.  */
+	mutex_enter(&smc->smc_io_lock);
+
+	/* Initiate the command with this key.  */
 	error = apple_smc_begin(smc, cmd, key, size);
 	if (error)
 		goto out;
 
+	/* Read each byte of data in sequence.  */
 	for (i = 0; i < size; i++) {
 		error = apple_smc_read_data(smc, &bytes[i]);
 		if (error)
@@ -278,8 +299,7 @@ apple_smc_input(struct apple_smc_tag *sm
 	/* Success!  */
 	error = 0;
 
-out:
-	mutex_exit(&smc->smc_lock);
+out:	mutex_exit(&smc->smc_io_lock);
 	return error;
 }
 
@@ -291,19 +311,25 @@ apple_smc_output(struct apple_smc_tag *s
 	uint8_t i;
 	int error;
 
-	mutex_enter(&smc->smc_lock);
+	/* Grab the SMC I/O lock.  */
+	mutex_enter(&smc->smc_io_lock);
+
+	/* Initiate the command with this key.  */
 	error = apple_smc_begin(smc, cmd, key, size);
 	if (error)
 		goto out;
 
+	/* Write each byte of data in sequence.  */
 	for (i = 0; i < size; i++) {
 		error = apple_smc_write_data(smc, bytes[i]);
 		if (error)
 			goto out;
 	}
 
-out:
-	mutex_exit(&smc->smc_lock);
+	/* Success!  */
+	error = 0;
+
+out:	mutex_exit(&smc->smc_io_lock);
 	return error;
 }
 
@@ -344,27 +370,34 @@ apple_smc_nth_key(struct apple_smc_tag *
 	struct apple_smc_key *key;
 	int error;
 
+	/* Paranoia: type must be NULL or 4 non-null characters long.  */
 	if ((type != NULL) && (strlen(type) != 4))
 		return EINVAL;
 
+	/* Create a new key.  XXX Consider caching these.  */
 	key = kmem_alloc(sizeof(*key), KM_SLEEP);
 #ifdef DIAGNOSTIC
 	key->ask_smc = smc;
 #endif
 
+	/* Ask the SMC what the name of the key by this number is.  */
 	index_be.u32 = htobe32(index);
 	error = apple_smc_input(smc, APPLE_SMC_CMD_NTH_KEY, index_be.name,
 	    key->ask_name, 4);
 	if (error)
 		goto fail;
+
+	/* Null-terminate the name. */
 	key->ask_name[4] = '\0';
 
+	/* Ask the SMC for a description of this key by name.  */
 	CTASSERT(sizeof(key->ask_desc) == 6);
 	error = apple_smc_input(smc, APPLE_SMC_CMD_KEY_DESC, key->ask_name,
 	    &key->ask_desc, 6);
 	if (error)
 		goto fail;
 
+	/* Fail with EINVAL if the types don't match.  */
 	if ((type != NULL) && (0 != memcmp(key->ask_desc.asd_type, type, 4))) {
 		error = EINVAL;
 		goto fail;
@@ -374,8 +407,7 @@ apple_smc_nth_key(struct apple_smc_tag *
 	*keyp = key;
 	return 0;
 
-fail:
-	kmem_free(key, sizeof(*key));
+fail:	kmem_free(key, sizeof(*key));
 	return error;
 }
 
@@ -386,36 +418,43 @@ apple_smc_named_key(struct apple_smc_tag
 	struct apple_smc_key *key;
 	int error;
 
+	/* Paranoia: name must be 4 non-null characters long.  */
 	KASSERT(name != NULL);
 	if (strlen(name) != 4)
 		return EINVAL;
 
+	/* Paranoia: type must be NULL or 4 non-null characters long.  */
 	if ((type != NULL) && (strlen(type) != 4))
 		return EINVAL;
 
+	/* Create a new key.  XXX Consider caching these.  */
 	key = kmem_alloc(sizeof(*key), KM_SLEEP);
 #ifdef DIAGNOSTIC
 	key->ask_smc = smc;
 #endif
+
+	/* Use the specified name, and make sure it's null-terminated.  */
 	(void)memcpy(key->ask_name, name, 4);
 	key->ask_name[4] = '\0';
 
+	/* Ask the SMC for a description of this key by name.  */
 	CTASSERT(sizeof(key->ask_desc) == 6);
 	error = apple_smc_input(smc, APPLE_SMC_CMD_KEY_DESC, key->ask_name,
 	    &key->ask_desc, 6);
 	if (error)
 		goto fail;
 
+	/* Fail with EINVAL if the types don't match.  */
 	if ((type != NULL) && (0 != memcmp(key->ask_desc.asd_type, type, 4))) {
 		error = EINVAL;
 		goto fail;
 	}
 
+	/* Success!  */
 	*keyp = key;
 	return 0;
 
-fail:
-	kmem_free(key, sizeof(*key));
+fail:	kmem_free(key, sizeof(*key));
 	return error;
 }
 
@@ -424,11 +463,14 @@ apple_smc_release_key(struct apple_smc_t
 {
 
 #ifdef DIAGNOSTIC
+	/* Make sure the caller didn't mix up SMC tags.  */
 	if (key->ask_smc != smc)
 		aprint_error_dev(smc->smc_dev,
 		    "releasing key with wrong tag: %p != %p",
 		    smc, key->ask_smc);
 #endif
+
+	/* Nothing to do but free the key's memory.  */
 	kmem_free(key, sizeof(*key));
 }
 
@@ -440,6 +482,7 @@ apple_smc_key_search(struct apple_smc_ta
 	uint32_t start = 0, end = apple_smc_nkeys(smc), median;
 	int error;
 
+	/* Do a binary search on the SMC's key space.  */
 	while (start < end) {
 		median = (start + ((end - start) / 2));
 		error = apple_smc_nth_key(smc, median, NULL, &key);
@@ -453,6 +496,7 @@ apple_smc_key_search(struct apple_smc_ta
 		apple_smc_release_key(smc, key);
 	}
 
+	/* Success!  */
 	*result = start;
 	return 0;
 }
@@ -462,11 +506,15 @@ apple_smc_read_key(struct apple_smc_tag 
     void *buffer, uint8_t size)
 {
 
+	/* Refuse if software and hardware disagree on the key's size.  */
 	if (key->ask_desc.asd_size != size)
 		return EINVAL;
+
+	/* Refuse if the hardware doesn't want us to read it.  */
 	if (!(key->ask_desc.asd_flags & APPLE_SMC_FLAG_READ))
 		return EACCES;
 
+	/* Looks good.  Try reading it from the hardware.  */
 	return apple_smc_input(smc, APPLE_SMC_CMD_READ_KEY, key->ask_name,
 	    buffer, size);
 }
@@ -486,11 +534,15 @@ apple_smc_read_key_2(struct apple_smc_ta
 	uint16_t be;
 	int error;
 
+	/* Read a big-endian quantity from the hardware.  */
 	error = apple_smc_read_key(smc, key, &be, 2);
 	if (error)
 		return error;
 
+	/* Convert it to host order.  */
 	*p = be16toh(be);
+
+	/* Success!  */
 	return 0;
 }
 
@@ -501,11 +553,15 @@ apple_smc_read_key_4(struct apple_smc_ta
 	uint32_t be;
 	int error;
 
+	/* Read a big-endian quantity from the hardware.  */
 	error = apple_smc_read_key(smc, key, &be, 4);
 	if (error)
 		return error;
 
+	/* Convert it to host order.  */
 	*p = be32toh(be);
+
+	/* Success!  */
 	return 0;
 }
 
@@ -514,11 +570,15 @@ apple_smc_write_key(struct apple_smc_tag
     const void *buffer, uint8_t size)
 {
 
+	/* Refuse if software and hardware disagree on the key's size.  */
 	if (key->ask_desc.asd_size != size)
 		return EINVAL;
+
+	/* Refuse if the hardware doesn't want us to write it.  */
 	if (!(key->ask_desc.asd_flags & APPLE_SMC_FLAG_WRITE))
 		return EACCES;
 
+	/* Looks good.  Try writing it to the hardware.  */
 	return apple_smc_output(smc, APPLE_SMC_CMD_WRITE_KEY, key->ask_name,
 	    buffer, size);
 }
@@ -535,8 +595,10 @@ int
 apple_smc_write_key_2(struct apple_smc_tag *smc,
     const struct apple_smc_key *key, uint16_t v)
 {
+	/* Convert the quantity from host to big-endian byte order.  */
 	const uint16_t v_be = htobe16(v);
 
+	/* Write the big-endian quantity to the hardware.  */
 	return apple_smc_write_key(smc, key, &v_be, 2);
 }
 
@@ -544,8 +606,10 @@ int
 apple_smc_write_key_4(struct apple_smc_tag *smc,
     const struct apple_smc_key *key, uint32_t v)
 {
+	/* Convert the quantity from host to big-endian byte order.  */
 	const uint16_t v_be = htobe32(v);
 
+	/* Write the big-endian quantity to the hardware.  */
 	return apple_smc_write_key(smc, key, &v_be, 4);
 }
 
@@ -555,6 +619,7 @@ static int
 apple_smc_modcmd(modcmd_t cmd, void *data __unused)
 {
 
+	/* Nothing to do for now to set up or tear down the module.  */
 	switch (cmd) {
 	case MODULE_CMD_INIT:
 		return 0;
Index: src/sys/dev/ic/apple_smc_fan.c
diff -u src/sys/dev/ic/apple_smc_fan.c:1.3 src/sys/dev/ic/apple_smc_fan.c:1.4
--- src/sys/dev/ic/apple_smc_fan.c:1.3	Tue Apr  1 17:48:52 2014
+++ src/sys/dev/ic/apple_smc_fan.c	Tue Apr  1 17:49:05 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: apple_smc_fan.c,v 1.3 2014/04/01 17:48:52 riastradh Exp $	*/
+/*	$NetBSD: apple_smc_fan.c,v 1.4 2014/04/01 17:49:05 riastradh Exp $	*/
 
 /*
  * Apple System Management Controller: Fans
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: apple_smc_fan.c,v 1.3 2014/04/01 17:48:52 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: apple_smc_fan.c,v 1.4 2014/04/01 17:49:05 riastradh Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -116,15 +116,18 @@ apple_smc_fan_match(device_t parent, cfd
 	int rv = 0;
 	int error;
 
+	/* Find how to find how many fans there are.  */
 	error = apple_smc_named_key(asa->asa_smc, APPLE_SMC_NFANS_KEY,
 	    APPLE_SMC_TYPE_UINT8, &nfans_key);
 	if (error)
 		goto out0;
 
+	/* Find how many fans there are.  */
 	error = apple_smc_read_key_1(asa->asa_smc, nfans_key, &nfans);
 	if (error)
 		goto out1;
 
+	/* Attach only if there's at least one fan.  */
 	if (nfans > 0)
 		rv = 1;
 
@@ -140,26 +143,37 @@ apple_smc_fan_attach(device_t parent, de
 	struct apple_smc_key *nfans_key;
 	int error;
 
+	/* Identify ourselves.  */
 	aprint_normal(": Apple SMC fan sensors\n");
 
+	/* Initialize the softc.  */
 	sc->sc_dev = self;
 	sc->sc_smc = asa->asa_smc;
 
+	/* Find how to find how many fans there are.  */
 	error = apple_smc_named_key(sc->sc_smc, APPLE_SMC_NFANS_KEY,
 	    APPLE_SMC_TYPE_UINT8, &nfans_key);
 	if (error)
 		goto out0;
 
+	/* Find how many fans there are.  */
 	error = apple_smc_read_key_1(sc->sc_smc, nfans_key, &sc->sc_nfans);
 	if (error)
 		goto out1;
 
-	if (sc->sc_nfans == 0) {	/* XXX */
+	/*
+	 * There should be at least one, but just in case the hardware
+	 * changed its mind in the interim...
+	 */
+	if (sc->sc_nfans == 0) {
 		aprint_error_dev(self, "no fans\n");
 		goto out1;
 	}
 
-	/* Must fit in a single decimal digit.  */
+	/*
+	 * The number of fans must fit in a single decimal digit for
+	 * the names of the fan keys; see the fan_sensor table above.
+	 */
 	if (sc->sc_nfans >= 10) {
 		aprint_error_dev(self, "too many fans: %"PRIu8"\n",
 		    sc->sc_nfans);
@@ -167,15 +181,18 @@ apple_smc_fan_attach(device_t parent, de
 	}
 
 #if 0				/* XXX sysctl */
+	/* Set up the sysctl tree for controlling the fans.  */
 	error = apple_smc_fan_sysctl_setup(sc);
 	if (error)
 		goto fail0;
 #endif
 
+	/* Attach the sensors to sysmon_envsys.  */
 	error = apple_smc_fan_attach_sensors(sc);
 	if (error)
 		goto fail1;
 
+	/* Success!  */
 	goto out1;
 
 #if 0
@@ -198,6 +215,7 @@ apple_smc_fan_detach(device_t self, int 
 {
 	struct apple_smc_fan_softc *sc = device_private(self);
 
+	/* If we registered with sysmon_envsys, unregister.  */
 	if (sc->sc_sme != NULL) {
 		sysmon_envsys_unregister(sc->sc_sme);
 		sc->sc_sme = NULL;
@@ -206,6 +224,7 @@ apple_smc_fan_detach(device_t self, int 
 		KASSERT(sc->sc_nfans > 0);
 		KASSERT(sc->sc_nfans < 10);
 
+		/* Release the keys and free the memory for fan records. */
 		apple_smc_fan_release_keys(sc);
 		kmem_free(sc->sc_fans,
 		    (sizeof(sc->sc_fans[0]) * sc->sc_nfans));
@@ -214,6 +233,7 @@ apple_smc_fan_detach(device_t self, int 
 	}
 
 #if 0				/* XXX sysctl */
+	/* Tear down all the sysctl knobs we set up.  */
 	sysctl_teardown(&sc->sc_sysctl_log);
 #endif
 
@@ -230,20 +250,26 @@ apple_smc_fan_attach_sensors(struct appl
 	char name[sizeof(fan_desc.fd_name) + 1];
 	int error;
 
+	/* Create a sysmon_envsys record, but don't register it yet.  */
 	sc->sc_sme = sysmon_envsys_create();
 	sc->sc_sme->sme_name = device_xname(sc->sc_dev);
 	sc->sc_sme->sme_cookie = sc;
 	sc->sc_sme->sme_refresh = apple_smc_fan_refresh;
 
+	/* Create an array of fan sensor records.  */
 	CTASSERT(10 <= (SIZE_MAX / sizeof(sc->sc_fans[0])));
 	sc->sc_fans = kmem_zalloc((sizeof(sc->sc_fans[0]) * sc->sc_nfans),
 	    KM_SLEEP);
 
+	/* Find all the fans.  */
 	for (fan = 0; fan < sc->sc_nfans; fan++) {
-		(void)snprintf(fan_desc_key_name, sizeof fan_desc_key_name,
+
+		/* Format the name of the key for the fan's description.  */
+		(void)snprintf(fan_desc_key_name, sizeof(fan_desc_key_name),
 		    "F%"PRIu8"ID", fan);
 		KASSERT(4 == strlen(fan_desc_key_name));
 
+		/* Look up the key for this fan's description.  */
 		error = apple_smc_named_key(sc->sc_smc, fan_desc_key_name,
 		    APPLE_SMC_TYPE_FANDESC, &fan_desc_key);
 		if (error) {
@@ -253,8 +279,9 @@ apple_smc_fan_attach_sensors(struct appl
 			continue;
 		}
 
+		/* Read the description of this fan.  */
 		error = apple_smc_read_key(sc->sc_smc, fan_desc_key, &fan_desc,
-		    sizeof fan_desc);
+		    sizeof(fan_desc));
 		if (error) {
 			aprint_error_dev(sc->sc_dev,
 			    "error identifying fan %"PRIu8": %d\n",
@@ -266,21 +293,26 @@ apple_smc_fan_attach_sensors(struct appl
 		 * XXX Do more with the fan description...
 		 */
 
+		/* Make a null-terminated copy of this fan's description.  */
 		(void)memcpy(name, fan_desc.fd_name, sizeof(fan_desc.fd_name));
-		name[sizeof(fan_desc.fd_name)] = 0;
+		name[sizeof(fan_desc.fd_name)] = '\0';
 
+		/* Attach all the sensors for this fan.  */
 		for (sensor = 0; sensor < __arraycount(fan_sensors); sensor++)
 			apple_smc_fan_attach_sensor(sc, fan, name, sensor);
 
 #if 0				/* XXX sysctl */
+		/* Attach sysctl knobs to control this fan.  */
 		apple_smc_fan_sysctl_setup_1(sc, fan);
 #endif
 	}
 
+	/* Fan sensors are all attached.  Register with sysmon_envsys now.  */
 	error = sysmon_envsys_register(sc->sc_sme);
 	if (error)
 		goto fail;
 
+	/* Success!  */
 	error = 0;
 	goto out;
 
@@ -301,15 +333,19 @@ apple_smc_fan_attach_sensor(struct apple
 	KASSERT(fan < sc->sc_nfans);
 	KASSERT(sensor < __arraycount(fan_sensors));
 
-	keyp = &sc->sc_fans[fan].sensors[sensor].sensor_key;
-	(void)snprintf(key_name, sizeof key_name, "F%d%s",
+	/* Format the name of the key for this fan sensor.   */
+	(void)snprintf(key_name, sizeof(key_name), "F%d%s",
 	    (int)sensor, fan_sensors[sensor].fs_key_suffix);
 	KASSERT(strlen(key_name) == 4);
+
+	/* Look up the key for this fan sensor. */
+	keyp = &sc->sc_fans[fan].sensors[sensor].sensor_key;
 	error = apple_smc_named_key(sc->sc_smc, key_name, APPLE_SMC_TYPE_FPE2,
 	    keyp);
 	if (error)
 		goto fail0;
 
+	/* Initialize the envsys_data record for this fan sensor.  */
 	edata = &sc->sc_fans[fan].sensors[sensor].sensor_data;
 	edata->units = ENVSYS_SFANRPM;
 	edata->state = ENVSYS_SINVALID;
@@ -317,10 +353,12 @@ apple_smc_fan_attach_sensor(struct apple
 	(void)snprintf(edata->desc, sizeof(edata->desc), "fan %s %s speed",
 	    name, fan_sensors[sensor].fs_name);
 
+	/* Attach this fan sensor to sysmon_envsys.  */
 	error = sysmon_envsys_sensor_attach(sc->sc_sme, edata);
 	if (error)
 		goto fail1;
 
+	/* Success!  */
 	return;
 
 fail1:	apple_smc_release_key(sc->sc_smc, *keyp);
@@ -339,6 +377,7 @@ apple_smc_fan_refresh(struct sysmon_envs
 	uint16_t rpm;
 	int error;
 
+	/* Sanity-check the sensor number out of paranoia.  */
 	CTASSERT(10 <= (SIZE_MAX / __arraycount(fan_sensors)));
 	KASSERT(sc->sc_nfans < 10);
 	if (edata->sensor >= (sc->sc_nfans * __arraycount(fan_sensors))) {
@@ -347,6 +386,7 @@ apple_smc_fan_refresh(struct sysmon_envs
 		return;
 	}
 
+	/* Pick apart the fan number and its sensor number.  */
 	fan = (edata->sensor / __arraycount(fan_sensors));
 	sensor = (edata->sensor % __arraycount(fan_sensors));
 
@@ -356,11 +396,12 @@ apple_smc_fan_refresh(struct sysmon_envs
 
 	/*
 	 * If we're refreshing, this sensor got attached, so we ought
-	 * to have a sensor key.
+	 * to have a sensor key.  Grab it.
 	 */
 	key = sc->sc_fans[fan].sensors[sensor].sensor_key;
 	KASSERT(key != NULL);
 
+	/* Read the fan sensor value, in rpm.  */
 	error = apple_smc_read_key_2(sc->sc_smc, key, &rpm);
 	if (error) {
 		aprint_error_dev(sc->sc_dev,
@@ -370,6 +411,7 @@ apple_smc_fan_refresh(struct sysmon_envs
 		return;
 	}
 
+	/* Success!  */
 	edata->value_cur = rpm;
 	edata->state = ENVSYS_SVALID;
 }
@@ -415,7 +457,9 @@ MODULE(MODULE_CLASS_DRIVER, apple_smc_fa
 static int
 apple_smc_fan_modcmd(modcmd_t cmd, void *arg __unused)
 {
+#ifdef _MODULE
 	int error;
+#endif
 
 	switch (cmd) {
 	case MODULE_CMD_INIT:
Index: src/sys/dev/ic/apple_smc_temp.c
diff -u src/sys/dev/ic/apple_smc_temp.c:1.3 src/sys/dev/ic/apple_smc_temp.c:1.4
--- src/sys/dev/ic/apple_smc_temp.c:1.3	Tue Apr  1 17:48:52 2014
+++ src/sys/dev/ic/apple_smc_temp.c	Tue Apr  1 17:49:05 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: apple_smc_temp.c,v 1.3 2014/04/01 17:48:52 riastradh Exp $	*/
+/*	$NetBSD: apple_smc_temp.c,v 1.4 2014/04/01 17:49:05 riastradh Exp $	*/
 
 /*
  * Apple System Management Controller: Temperature Sensors
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: apple_smc_temp.c,v 1.3 2014/04/01 17:48:52 riastradh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: apple_smc_temp.c,v 1.4 2014/04/01 17:49:05 riastradh Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -87,14 +87,16 @@ CFATTACH_DECL_NEW(apple_smc_temp, sizeof
 static int
 apple_smc_temp_match(device_t parent, cfdata_t match, void *aux)
 {
-	const struct apple_smc_attach_args *asa = aux;
+	const struct apple_smc_attach_args *const asa = aux;
 	uint32_t nsensors;
 	int error;
 
+	/* Find how many temperature sensors we have. */
 	error = apple_smc_temp_count_sensors(asa->asa_smc, &nsensors);
 	if (error)
 		return 0;
 
+	/* If there aren't any, don't bother attaching.  */
 	if (nsensors == 0)
 		return 0;
 
@@ -104,30 +106,59 @@ apple_smc_temp_match(device_t parent, cf
 static void
 apple_smc_temp_attach(device_t parent, device_t self, void *aux)
 {
-	struct apple_smc_temp_softc *sc = device_private(self);
-	const struct apple_smc_attach_args *asa = aux;
+	struct apple_smc_temp_softc *const sc = device_private(self);
+	const struct apple_smc_attach_args *const asa = aux;
+	int error;
+
+	/* Identify ourselves.  */
+	aprint_normal(": Apple SMC temperature sensors\n");
 
+	/* Initialize the softc. */
 	sc->sc_dev = self;
 	sc->sc_smc = asa->asa_smc;
+
+	/* Create a sysmon_envsys record, but don't register it yet.  */
 	sc->sc_sme = sysmon_envsys_create();
 	sc->sc_sme->sme_name = device_xname(self);
 	sc->sc_sme->sme_cookie = sc;
 	sc->sc_sme->sme_refresh = apple_smc_temp_refresh;
 
-	(void)apple_smc_temp_find_sensors(sc);
+	/* Find and attach all the sensors.  */
+	error = apple_smc_temp_find_sensors(sc);
+	if (error) {
+		aprint_error_dev(self, "failed to find sensors: %d\n", error);
+		goto fail;
+	}
+
+	/* Sensors are all attached.  Register with sysmon_envsys now.  */
+	error = sysmon_envsys_register(sc->sc_sme);
+	if (error) {
+		aprint_error_dev(self, "failed to register with sysmon_envsys:"
+		    " %d\n", error);
+		goto fail;
+	}
+
+	/* Success!  */
+	return;
+
+fail:	sysmon_envsys_destroy(sc->sc_sme);
+	sc->sc_sme = NULL;
 }
 
 static int
 apple_smc_temp_detach(device_t self, int flags)
 {
-	struct apple_smc_temp_softc *sc = device_private(self);
+	struct apple_smc_temp_softc *const sc = device_private(self);
 
-	KASSERT(sc->sc_sme != NULL);
-	sysmon_envsys_unregister(sc->sc_sme);
-	sc->sc_sme = NULL;
+	/* If we registered with sysmon_envsys, unregister.  */
+	if (sc->sc_sme != NULL) {
+		sysmon_envsys_unregister(sc->sc_sme);
+		sc->sc_sme = NULL;
 
-	if (sc->sc_sensors != NULL) {
+		KASSERT(sc->sc_sensors != NULL);
 		KASSERT(sc->sc_nsensors > 0);
+
+		/* Release the keys and free the memory for sensor records.  */
 		apple_smc_temp_release_keys(sc);
 		kmem_free(sc->sc_sensors,
 		    (sizeof(sc->sc_sensors[0]) * sc->sc_nsensors));
@@ -135,25 +166,29 @@ apple_smc_temp_detach(device_t self, int
 		sc->sc_nsensors = 0;
 	}
 
+	/* Success!  */
 	return 0;
 }
 
 static void
 apple_smc_temp_refresh(struct sysmon_envsys *sme, struct envsys_data *edata)
 {
-	struct apple_smc_temp_softc *sc = sme->sme_cookie;
+	struct apple_smc_temp_softc *const sc = sme->sme_cookie;
 	const struct apple_smc_key *key;
 	uint16_t utemp16;
 	int32_t temp;
 	int error;
 
+	/* Sanity-check the sensor number out of paranoia.  */
 	if (edata->sensor >= sc->sc_nsensors) {
 		aprint_error_dev(sc->sc_dev, "unknown sensor %"PRIu32"\n",
 		    edata->sensor);
 		return;
 	}
 
+	/* Read the raw temperature sensor value.  */
 	key = sc->sc_sensors[edata->sensor].sensor_key;
+	KASSERT(key != NULL);
 	error = apple_smc_read_key_2(sc->sc_smc, key, &utemp16);
 	if (error) {
 		aprint_error_dev(sc->sc_dev,
@@ -176,6 +211,7 @@ apple_smc_temp_refresh(struct sysmon_env
 	/* Finally, convert to microkelvins as sysmon_envsys wants.  */
 	temp *= 1000;
 
+	/* Success!  */
 	edata->value_cur = temp;
 	edata->state = ENVSYS_SVALID;
 }
@@ -184,8 +220,10 @@ static int
 apple_smc_temp_count_sensors(struct apple_smc_tag *smc, uint32_t *nsensors)
 {
 
+	/* Start with zero sensors.  */
 	*nsensors = 0;
 
+	/* Count 'em.  */
 	return apple_smc_scan_temp_sensors(smc, nsensors,
 	    NULL,
 	    &apple_smc_temp_count_sensors_scanner);
@@ -195,15 +233,15 @@ static void
 apple_smc_temp_count_sensors_scanner(struct apple_smc_tag *smc, void *arg,
     struct apple_smc_key *key)
 {
-	uint32_t *nsensors = arg;
+	uint32_t *const nsensors = arg;
 
 	(*nsensors)++;
 	apple_smc_release_key(smc, key);
 }
 
 struct fss {			/* Find Sensors State */
-	struct apple_smc_temp_softc *fss_sc;
-	size_t fss_sensor;
+	struct apple_smc_temp_softc	*fss_sc;
+	unsigned int			fss_sensor;
 };
 
 static int
@@ -212,26 +250,45 @@ apple_smc_temp_find_sensors(struct apple
 	struct fss fss;
 	int error;
 
+	/* Start with zero sensors.  */
 	fss.fss_sc = sc;
 	fss.fss_sensor = 0;
 
+	/* Find 'em.  */
 	error = apple_smc_scan_temp_sensors(sc->sc_smc, &fss,
 	    &apple_smc_temp_find_sensors_init,
 	    &apple_smc_temp_find_sensors_scanner);
 	if (error)
 		return error;
 
+	/*
+	 * Success guarantees that sc->sc_nsensors will be nonzero and
+	 * sc->sc_sensors will be allocated.
+	 */
+	KASSERT(sc->sc_sensors != NULL);
+	KASSERT(sc->sc_nsensors > 0);
+
+	/* If we didn't find any sensors, bail.  */
+	if (fss.fss_sensor == 0) {
+		kmem_free(sc->sc_sensors, sc->sc_nsensors);
+		sc->sc_sensors = NULL;
+		sc->sc_nsensors = 0;
+		return EIO;
+	}
+
 	/* Shrink the array if we overshot.  */
 	if (fss.fss_sensor < sc->sc_nsensors) {
-		void *sensors = kmem_alloc((fss.fss_sensor *
+		void *const sensors = kmem_alloc((fss.fss_sensor *
 			sizeof(sc->sc_sensors[0])), KM_SLEEP);
+
 		(void)memcpy(sensors, sc->sc_sensors,
 		    (fss.fss_sensor * sizeof(sc->sc_sensors[0])));
 		kmem_free(sc->sc_sensors, sc->sc_nsensors);
-		sc->sc_nsensors = fss.fss_sensor;
 		sc->sc_sensors = sensors;
+		sc->sc_nsensors = fss.fss_sensor;
 	}
 
+	/* Success!  */
 	return 0;
 }
 
@@ -239,15 +296,25 @@ static int
 apple_smc_temp_find_sensors_init(struct apple_smc_tag *smc, void *arg,
     uint32_t nsensors)
 {
-	struct fss *fss = arg;
+	struct fss *const fss = arg;
 
+	/* Record the maximum number of sensors we may have.  */
 	fss->fss_sc->sc_nsensors = nsensors;
-	if (nsensors == 0)
+
+	/* If we found a maximum of zero sensors, bail.  */
+	if (nsensors == 0) {
 		fss->fss_sc->sc_sensors = NULL;
-	else
-		fss->fss_sc->sc_sensors = kmem_alloc((nsensors *
-			sizeof(fss->fss_sc->sc_sensors[0])), KM_SLEEP);
+		return EIO;
+	}
+
+	/*
+	 * If there may be any sensors, optimistically allocate as many
+	 * records for them as we may possibly need.
+	 */
+	fss->fss_sc->sc_sensors = kmem_alloc((nsensors *
+		sizeof(fss->fss_sc->sc_sensors[0])), KM_SLEEP);
 
+	/* Success!  */
 	return 0;
 }
 
@@ -255,23 +322,27 @@ static void
 apple_smc_temp_find_sensors_scanner(struct apple_smc_tag *smc, void *arg,
     struct apple_smc_key *key)
 {
-	struct fss *fss = arg;
+	struct fss *const fss = arg;
 	const uint32_t sensor = fss->fss_sensor;
-	struct envsys_data *edata =
+	struct envsys_data *const edata =
 	    &fss->fss_sc->sc_sensors[sensor].sensor_data;
 	int error;
 
+	/* Initialize the envsys_data record for this temperature sensor.  */
 	edata->units = ENVSYS_STEMP;
 	edata->state = ENVSYS_SINVALID;
 	edata->flags = ENVSYS_FHAS_ENTROPY;
 
 	/*
-	 * XXX Use a more meaningful name based on a table of known
-	 * temperature sensors.
+	 * Use the SMC key name as the temperature sensor's name.
+	 *
+	 * XXX We ought to use a more meaningful name based on a table
+	 * of known temperature sensors.
 	 */
 	CTASSERT(sizeof(edata->desc) >= 4);
 	(void)strlcpy(edata->desc, apple_smc_key_name(key), 4);
 
+	/* Attach this temperature sensor to sysmon_envsys.  */
 	error = sysmon_envsys_sensor_attach(fss->fss_sc->sc_sme, edata);
 	if (error) {
 		aprint_error_dev(fss->fss_sc->sc_dev,
@@ -280,8 +351,8 @@ apple_smc_temp_find_sensors_scanner(stru
 		return;
 	}
 
+	/* Success!  */
 	fss->fss_sc->sc_sensors[sensor].sensor_key = key;
-
 	fss->fss_sensor++;
 }
 
@@ -306,30 +377,36 @@ apple_smc_scan_temp_sensors(struct apple
 	struct apple_smc_key *key;
 	int error;
 
+	/* Find [start, end) bounds on the temperature sensor key indices.  */
 	error = apple_smc_bound_temp_sensors(smc, &tstart, &ustart);
 	if (error)
 		return error;
 	KASSERT(tstart <= ustart);
 
+	/* Inform the caller of the number of candidates.  */
 	if (init != NULL) {
 		error = (*init)(smc, arg, (ustart - tstart));
 		if (error)
 			return error;
 	}
 
+	/* Take a closer look at all the candidates.  */
 	for (i = tstart; i < ustart; i++) {
 		error = apple_smc_nth_key(smc, i, NULL, &key);
 		if (error)
 			continue;
 
+		/* Skip it if it's not a temperature sensor.  */
 		if (!apple_smc_temp_sensor_p(key)) {
 			apple_smc_release_key(smc, key);
 			continue;
 		}
 
+		/* Scan it if it is one.  */
 		(*scanner)(smc, arg, key);
 	}
 
+	/* Success!  */
 	return 0;
 }
 
@@ -337,6 +414,7 @@ static bool
 apple_smc_temp_sensor_p(const struct apple_smc_key *key)
 {
 
+	/* It's a temperature sensor iff its type is sp78.  */
 	return (0 == memcmp(apple_smc_key_desc(key)->asd_type,
 		APPLE_SMC_TYPE_SP78, 4));
 }
@@ -347,17 +425,21 @@ apple_smc_bound_temp_sensors(struct appl
 {
 	int error;
 
+	/* Find the first `T...' key.  */
 	error = apple_smc_key_search(smc, "T", tstart);
 	if (error)
 		return error;
 
+	/* Find the first `U...' key.  */
 	error = apple_smc_key_search(smc, "U", ustart);
 	if (error)
 		return error;
 
+	/* Sanity check: `T...' keys had better precede `U...' keys.  */
 	if (!(*tstart <= *ustart))
 		return EIO;
 
+	/* Success!  */
 	return 0;
 }
 
@@ -370,7 +452,9 @@ MODULE(MODULE_CLASS_DRIVER, apple_smc_te
 static int
 apple_smc_temp_modcmd(modcmd_t cmd, void *arg __unused)
 {
+#ifdef _MODULE
 	int error;
+#endif
 
 	switch (cmd) {
 	case MODULE_CMD_INIT:
Index: src/sys/dev/ic/apple_smcvar.h
diff -u src/sys/dev/ic/apple_smcvar.h:1.3 src/sys/dev/ic/apple_smcvar.h:1.4
--- src/sys/dev/ic/apple_smcvar.h:1.3	Tue Apr  1 17:48:52 2014
+++ src/sys/dev/ic/apple_smcvar.h	Tue Apr  1 17:49:05 2014
@@ -1,4 +1,4 @@
-/*	$NetBSD: apple_smcvar.h,v 1.3 2014/04/01 17:48:52 riastradh Exp $	*/
+/*	$NetBSD: apple_smcvar.h,v 1.4 2014/04/01 17:49:05 riastradh Exp $	*/
 
 /*
  * Apple System Management Controller State
@@ -47,8 +47,8 @@ struct apple_smc_tag {
 	bus_space_tag_t		smc_bst;
 	bus_space_handle_t	smc_bsh;
 	bus_size_t		smc_size;
-	uint32_t		smc_nkeys;
-	kmutex_t		smc_lock;
+	uint32_t		smc_nkeys;	/* number of keys in the SMC */
+	kmutex_t		smc_io_lock;	/* excludes I/O with the SMC */
 
 #if 0				/* XXX sysctl */
 	struct sysctllog	*smc_sysctllog;

Reply via email to