summaryrefslogtreecommitdiff
path: root/sys/dev/ipmi
diff options
context:
space:
mode:
authorDoug Ambrisko <ambrisko@FreeBSD.org>2007-07-16 17:03:48 +0000
committerDoug Ambrisko <ambrisko@FreeBSD.org>2007-07-16 17:03:48 +0000
commit72d73315396520151f86f8c6cb42b09d5a1073e5 (patch)
treea10f5a10a8c230a055225791c248f38e5552e698 /sys/dev/ipmi
parent871f1ddd46625c2f485f7f5737b1c237ebb943a4 (diff)
Notes
Diffstat (limited to 'sys/dev/ipmi')
-rw-r--r--sys/dev/ipmi/ipmi_isa.c81
1 files changed, 79 insertions, 2 deletions
diff --git a/sys/dev/ipmi/ipmi_isa.c b/sys/dev/ipmi/ipmi_isa.c
index a77081ad3908..9d3f9f34c2f2 100644
--- a/sys/dev/ipmi/ipmi_isa.c
+++ b/sys/dev/ipmi/ipmi_isa.c
@@ -87,6 +87,79 @@ ipmi_isa_probe(device_t dev)
}
static int
+ipmi_hint_identify(device_t dev, struct ipmi_get_info *info)
+{
+ const char *mode, *name;
+ int i, unit, val;
+
+ /* We require at least a "mode" hint. */
+ name = device_get_name(dev);
+ unit = device_get_unit(dev);
+ if (resource_string_value(name, unit, "mode", &mode) != 0)
+ return (0);
+
+ /* Set the mode and default I/O resources for each mode. */
+ bzero(info, sizeof(struct ipmi_get_info));
+ if (strcasecmp(mode, "KCS") == 0) {
+ info->iface_type = KCS_MODE;
+ info->address = 0xca2;
+ info->io_mode = 1;
+ info->offset = 1;
+ } else if (strcasecmp(mode, "SMIC") == 0) {
+ info->iface_type = SMIC_MODE;
+ info->address = 0xca9;
+ info->io_mode = 1;
+ info->offset = 1;
+ } else if (strcasecmp(mode, "BT") == 0) {
+ info->iface_type = BT_MODE;
+ info->address = 0xe4;
+ info->io_mode = 1;
+ info->offset = 1;
+ } else {
+ device_printf(dev, "Invalid mode %s\n", mode);
+ return (0);
+ }
+
+ /*
+ * Kill any resources that isahint.c might have setup for us
+ * since it will conflict with how we do resources.
+ */
+ for (i = 0; i < 2; i++) {
+ bus_delete_resource(dev, SYS_RES_MEMORY, i);
+ bus_delete_resource(dev, SYS_RES_IOPORT, i);
+ }
+
+ /* Allow the I/O address to be overriden via hints. */
+ if (resource_int_value(name, unit, "port", &val) == 0 && val != 0) {
+ info->address = val;
+ info->io_mode = 1;
+ } else if (resource_int_value(name, unit, "maddr", &val) == 0 &&
+ val != 0) {
+ info->address = val;
+ info->io_mode = 0;
+ }
+
+ /* Allow the spacing to be overriden. */
+ if (resource_int_value(name, unit, "spacing", &val) == 0) {
+ switch (val) {
+ case 8:
+ info->offset = 1;
+ break;
+ case 16:
+ info->offset = 2;
+ break;
+ case 32:
+ info->offset = 4;
+ break;
+ default:
+ device_printf(dev, "Invalid register spacing\n");
+ return (0);
+ }
+ }
+ return (1);
+}
+
+static int
ipmi_isa_attach(device_t dev)
{
struct ipmi_softc *sc = device_get_softc(dev);
@@ -94,8 +167,12 @@ ipmi_isa_attach(device_t dev)
const char *mode;
int count, error, i, type;
- /* This should never fail. */
- if (!ipmi_smbios_identify(&info))
+ /*
+ * Pull info out of the SMBIOS table. If that doesn't work, use
+ * hints to enumerate a device.
+ */
+ if (!ipmi_smbios_identify(&info) &&
+ !ipmi_hint_identify(dev, &info))
return (ENXIO);
/*