Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F174316935
D8173.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
D8173.diff
View Options
Index: head/sys/dev/smbus/smbconf.h
===================================================================
--- head/sys/dev/smbus/smbconf.h
+++ head/sys/dev/smbus/smbconf.h
@@ -34,6 +34,10 @@
#define n(flags) (~(flags) & (flags))
+/* Order constants for smbus children. */
+#define SMBUS_ORDER_HINTED 20
+#define SMBUS_ORDER_PNP 40
+
/*
* How tsleep() is called in smb_request_bus().
*/
Index: head/sys/dev/smbus/smbus.c
===================================================================
--- head/sys/dev/smbus/smbus.c
+++ head/sys/dev/smbus/smbus.c
@@ -31,6 +31,7 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/lock.h>
+#include <sys/malloc.h>
#include <sys/module.h>
#include <sys/mutex.h>
#include <sys/bus.h>
@@ -41,54 +42,16 @@
#include "smbus_if.h"
#include "bus_if.h"
+struct smbus_ivar
+{
+ uint8_t addr;
+};
/*
* Autoconfiguration and support routines for System Management bus
*/
+static void smbus_probe_device(device_t dev, u_char addr);
-/*
- * Device methods
- */
-static int smbus_probe(device_t);
-static int smbus_attach(device_t);
-static int smbus_detach(device_t);
-
-static int smbus_child_location_str(device_t parent, device_t child,
- char *buf, size_t buflen);
-static int smbus_print_child(device_t parent, device_t child);
-static void smbus_probe_device(device_t dev, u_char* addr);
-static int smbus_read_ivar(device_t parent, device_t child, int which,
- uintptr_t *result);
-
-static device_method_t smbus_methods[] = {
- /* device interface */
- DEVMETHOD(device_probe, smbus_probe),
- DEVMETHOD(device_attach, smbus_attach),
- DEVMETHOD(device_detach, smbus_detach),
-
- /* bus interface */
- DEVMETHOD(bus_add_child, bus_generic_add_child),
- DEVMETHOD(bus_child_location_str, smbus_child_location_str),
- DEVMETHOD(bus_driver_added, bus_generic_driver_added),
- DEVMETHOD(bus_print_child, smbus_print_child),
- DEVMETHOD(bus_read_ivar, smbus_read_ivar),
-
- DEVMETHOD_END
-};
-
-driver_t smbus_driver = {
- "smbus",
- smbus_methods,
- sizeof(struct smbus_softc),
-};
-
-devclass_t smbus_devclass;
-
-/*
- * At 'probe' time, we add all the devices which we know about to the
- * bus. The generic attach routine will probe and attach them if they
- * are alive.
- */
static int
smbus_probe(device_t dev)
{
@@ -107,9 +70,9 @@
mtx_init(&sc->lock, device_get_nameunit(dev), "smbus", MTX_DEF);
bus_generic_probe(dev);
for (addr = SMBUS_ADDR_MIN; addr < SMBUS_ADDR_MAX; ++addr) {
- sc->addrs[addr] = addr;
- smbus_probe_device(dev, &sc->addrs[addr]);
+ smbus_probe_device(dev, addr);
}
+ bus_enumerate_hinted_children(dev);
bus_generic_attach(dev);
return (0);
@@ -124,6 +87,7 @@
error = bus_generic_detach(dev);
if (error)
return (error);
+ device_delete_children(dev);
mtx_destroy(&sc->lock);
return (0);
@@ -135,34 +99,78 @@
}
static void
-smbus_probe_device(device_t dev, u_char* addr)
+smbus_probe_device(device_t dev, u_char addr)
{
device_t child;
int error;
u_char cmd;
u_char buf[2];
+ struct smbus_ivar *devi;
cmd = 0x01;
- error = smbus_trans(dev, *addr, cmd,
+ error = smbus_trans(dev, addr, cmd,
SMB_TRANS_NOCNT | SMB_TRANS_NOREPORT,
NULL, 0, buf, 1, NULL);
if (error == 0) {
if (bootverbose)
- device_printf(dev, "Probed address 0x%02x\n", *addr);
- child = device_add_child(dev, NULL, -1);
- device_set_ivars(child, addr);
+ device_printf(dev, "Probed address 0x%02x\n", addr);
+ child = BUS_ADD_CHILD(dev, SMBUS_ORDER_PNP, NULL, -1);
+ if (child == NULL)
+ return;
+ devi = device_get_ivars(child);
+ devi->addr = addr;
+ }
+}
+
+static device_t
+smbus_add_child(device_t dev, u_int order, const char *name, int unit)
+{
+ struct smbus_ivar *devi;
+ device_t child;
+
+ child = device_add_child_ordered(dev, order, name, unit);
+ if (child == NULL)
+ return (child);
+ devi = malloc(sizeof(struct smbus_ivar), M_DEVBUF, M_NOWAIT | M_ZERO);
+ if (devi == NULL) {
+ device_delete_child(dev, child);
+ return (NULL);
+ }
+ device_set_ivars(child, devi);
+ return (child);
+}
+
+static void
+smbus_hinted_child(device_t bus, const char *dname, int dunit)
+{
+ struct smbus_ivar *devi;
+ device_t child;
+ int addr;
+
+ addr = 0;
+ resource_int_value(dname, dunit, "addr", &addr);
+ if (addr > UINT8_MAX) {
+ device_printf(bus, "ignored incorrect slave address hint 0x%x"
+ " for %s%d\n", addr, dname, dunit);
+ return;
}
+ child = BUS_ADD_CHILD(bus, SMBUS_ORDER_HINTED, dname, dunit);
+ if (child == NULL)
+ return;
+ devi = device_get_ivars(child);
+ devi->addr = addr;
}
+
static int
smbus_child_location_str(device_t parent, device_t child, char *buf,
size_t buflen)
{
- unsigned char *addr;
+ struct smbus_ivar *devi;
- addr = device_get_ivars(child);
- if (addr)
- snprintf(buf, buflen, "addr=0x%x", *addr);
+ devi = device_get_ivars(child);
+ if (devi->addr != 0)
+ snprintf(buf, buflen, "addr=0x%x", devi->addr);
else if (buflen)
buf[0] = 0;
return (0);
@@ -171,28 +179,49 @@
static int
smbus_print_child(device_t parent, device_t child)
{
- unsigned char *addr;
+ struct smbus_ivar *devi;
int retval;
- addr = device_get_ivars(child);
+ devi = device_get_ivars(child);
retval = bus_print_child_header(parent, child);
- if (addr)
- retval += printf(" at addr 0x%x", *addr);
+ if (devi->addr != 0)
+ retval += printf(" at addr 0x%x", devi->addr);
retval += bus_print_child_footer(parent, child);
return (retval);
}
static int
-smbus_read_ivar(device_t parent, device_t child, int which,
- uintptr_t *result)
+smbus_read_ivar(device_t parent, device_t child, int which, uintptr_t *result)
+{
+ struct smbus_ivar *devi;
+
+ devi = device_get_ivars(child);
+ switch (which) {
+ case SMBUS_IVAR_ADDR:
+ if (devi->addr != 0)
+ *result = devi->addr;
+ else
+ *result = -1;
+ break;
+ default:
+ return (ENOENT);
+ }
+ return (0);
+}
+
+static int
+smbus_write_ivar(device_t parent, device_t child, int which, uintptr_t value)
{
- unsigned char *addr;
+ struct smbus_ivar *devi;
- addr = device_get_ivars(child);
+ devi = device_get_ivars(child);
switch (which) {
case SMBUS_IVAR_ADDR:
- *result = (addr == NULL) ? -1 : *addr;
+ /* Allow to set but no change the slave address. */
+ if (devi->addr != 0)
+ return (EINVAL);
+ devi->addr = value;
break;
default:
return (ENOENT);
@@ -200,4 +229,47 @@
return (0);
}
+static void
+smbus_probe_nomatch(device_t bus, device_t child)
+{
+ struct smbus_ivar *devi = device_get_ivars(child);
+
+ /*
+ * Ignore (self-identified) devices without a slave address set.
+ * For example, smb(4).
+ */
+ if (devi->addr != 0)
+ device_printf(bus, "<unknown device> at addr %#x\n",
+ devi->addr);
+}
+
+/*
+ * Device methods
+ */
+static device_method_t smbus_methods[] = {
+ /* device interface */
+ DEVMETHOD(device_probe, smbus_probe),
+ DEVMETHOD(device_attach, smbus_attach),
+ DEVMETHOD(device_detach, smbus_detach),
+
+ /* bus interface */
+ DEVMETHOD(bus_add_child, smbus_add_child),
+ DEVMETHOD(bus_hinted_child, smbus_hinted_child),
+ DEVMETHOD(bus_probe_nomatch, smbus_probe_nomatch),
+ DEVMETHOD(bus_child_location_str, smbus_child_location_str),
+ DEVMETHOD(bus_print_child, smbus_print_child),
+ DEVMETHOD(bus_read_ivar, smbus_read_ivar),
+ DEVMETHOD(bus_write_ivar, smbus_write_ivar),
+
+ DEVMETHOD_END
+};
+
+driver_t smbus_driver = {
+ "smbus",
+ smbus_methods,
+ sizeof(struct smbus_softc),
+};
+
+devclass_t smbus_devclass;
+
MODULE_VERSION(smbus, SMBUS_MODVER);
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Oct 3, 8:13 AM (14 h, 4 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40119355
Default Alt Text
D8173.diff (7 KB)
Attached To
Mode
D8173: smbus: allow child devices to be added via hints
Attached
Detach File
Event Timeline
Log In to Comment