diff options
| author | Doug Ambrisko <ambrisko@FreeBSD.org> | 2007-07-16 17:03:48 +0000 |
|---|---|---|
| committer | Doug Ambrisko <ambrisko@FreeBSD.org> | 2007-07-16 17:03:48 +0000 |
| commit | 72d73315396520151f86f8c6cb42b09d5a1073e5 (patch) | |
| tree | a10f5a10a8c230a055225791c248f38e5552e698 /sys/dev/ipmi | |
| parent | 871f1ddd46625c2f485f7f5737b1c237ebb943a4 (diff) | |
Notes
Diffstat (limited to 'sys/dev/ipmi')
| -rw-r--r-- | sys/dev/ipmi/ipmi_isa.c | 81 |
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); /* |
