static int ipmi2_pci_attach(device_t dev) { struct ipmi_softc *sc; int error, iface, type; sc = device_get_softc(dev); sc->ipmi_dev = dev; /* Interface is determined by progif. */ switch (pci_get_progif(dev)) { case PCIP_SERIALBUS_IPMI_SMIC: iface = SMIC_MODE; break; case PCIP_SERIALBUS_IPMI_KCS: iface = KCS_MODE; break; case PCIP_SERIALBUS_IPMI_BT: iface = BT_MODE; device_printf(dev, "BT interface unsupported\n"); return (ENXIO); default: device_printf(dev, "Unsupported interface: %d\n", pci_get_progif(dev)); return (ENXIO); } /* Check the BAR to determine our resource type. */ sc->ipmi_io_rid = PCIR_BAR(0); if (PCI_BAR_IO(pci_read_config(dev, PCIR_BAR(0), 4))) type = SYS_RES_IOPORT; else type = SYS_RES_MEMORY; sc->ipmi_io_type = type; sc->ipmi_io_spacing = 1; sc->ipmi_io_res[0] = bus_alloc_resource_any(dev, type, &sc->ipmi_io_rid, RF_ACTIVE); if (sc->ipmi_io_res[0] == NULL) { device_printf(dev, "couldn't map ports/memory\n"); return (ENXIO); } sc->ipmi_irq_rid = 0; sc->ipmi_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->ipmi_irq_rid, RF_SHAREABLE | RF_ACTIVE); switch (iface) { case KCS_MODE: device_printf(dev, "using KSC interface\n"); /* * We have to examine the resource directly to determine the * alignment. */ if (!ipmi_kcs_probe_align(sc)) { device_printf(dev, "Unable to determine alignment\n"); error = ENXIO; goto bad; } error = ipmi_kcs_attach(sc); if (error) goto bad; break; case SMIC_MODE: device_printf(dev, "using SMIC interface\n"); error = ipmi_smic_attach(sc); if (error) goto bad; break; } error = ipmi_attach(dev); if (error) goto bad; return (0); bad: ipmi_release_resources(dev); return (error); }
static int ipmi_pci_attach(device_t dev) { struct ipmi_softc *sc = device_get_softc(dev); struct ipmi_get_info info; const char *mode; int error, type; /* Look for an IPMI entry in the SMBIOS table. */ if (!ipmi_smbios_identify(&info)) return (ENXIO); sc->ipmi_dev = dev; switch (info.iface_type) { case KCS_MODE: mode = "KCS"; break; case SMIC_MODE: mode = "SMIC"; break; case BT_MODE: device_printf(dev, "BT mode is unsupported\n"); return (ENXIO); default: device_printf(dev, "No IPMI interface found\n"); return (ENXIO); } device_printf(dev, "%s mode found at %s 0x%jx alignment 0x%x on %s\n", mode, info.io_mode ? "io" : "mem", (uintmax_t)info.address, info.offset, device_get_name(device_get_parent(dev))); if (info.io_mode) type = SYS_RES_IOPORT; else type = SYS_RES_MEMORY; sc->ipmi_io_rid = PCIR_BAR(0); sc->ipmi_io_res[0] = bus_alloc_resource_any(dev, type, &sc->ipmi_io_rid, RF_ACTIVE); sc->ipmi_io_type = type; sc->ipmi_io_spacing = info.offset; if (sc->ipmi_io_res[0] == NULL) { device_printf(dev, "couldn't configure pci io res\n"); return (ENXIO); } sc->ipmi_irq_rid = 0; sc->ipmi_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->ipmi_irq_rid, RF_SHAREABLE | RF_ACTIVE); switch (info.iface_type) { case KCS_MODE: error = ipmi_kcs_attach(sc); if (error) goto bad; break; case SMIC_MODE: error = ipmi_smic_attach(sc); if (error) goto bad; break; } error = ipmi_attach(dev); if (error) goto bad; return (0); bad: ipmi_release_resources(dev); return (error); }
static int ipmi_acpi_attach(device_t dev) { ACPI_HANDLE devh; const char *mode; struct ipmi_get_info info; struct ipmi_softc *sc = device_get_softc(dev); int count, error, flags, i, type; int interface_type = 0, interface_version = 0; error = 0; devh = acpi_get_handle(dev); if (ACPI_FAILURE(acpi_GetInteger(devh, "_IFT", &interface_type))) return (ENXIO); if (ACPI_FAILURE(acpi_GetInteger(devh, "_SRV", &interface_version))) return (ENXIO); switch (interface_type) { case KCS_MODE: count = 2; mode = "KCS"; break; case SMIC_MODE: count = 3; mode = "SMIC"; break; case BT_MODE: device_printf(dev, "BT interface not supported\n"); return (ENXIO); case SSIF_MODE: if (ACPI_FAILURE(acpi_GetInteger(devh, "_ADR", &flags))) return (ENXIO); info.address = flags; device_printf(dev, "SSIF interface not supported on ACPI\n"); return (0); default: return (ENXIO); } if (bus_get_resource(dev, SYS_RES_IOPORT, 0, NULL, NULL) == 0) type = SYS_RES_IOPORT; else if (bus_get_resource(dev, SYS_RES_MEMORY, 0, NULL, NULL) == 0) type = SYS_RES_MEMORY; else { device_printf(dev, "unknown resource type\n"); return (ENXIO); } sc->ipmi_io_rid = 0; sc->ipmi_io_res[0] = bus_alloc_resource_any(dev, type, &sc->ipmi_io_rid, RF_ACTIVE); sc->ipmi_io_type = type; sc->ipmi_io_spacing = 1; if (sc->ipmi_io_res[0] == NULL) { device_printf(dev, "couldn't configure I/O resource\n"); return (ENXIO); } /* If we have multiple resources, allocate up to MAX_RES. */ for (i = 1; i < MAX_RES; i++) { sc->ipmi_io_rid = i; sc->ipmi_io_res[i] = bus_alloc_resource_any(dev, type, &sc->ipmi_io_rid, RF_ACTIVE); if (sc->ipmi_io_res[i] == NULL) break; } sc->ipmi_io_rid = 0; /* If we have multiple resources, make sure we have enough of them. */ if (sc->ipmi_io_res[1] != NULL && sc->ipmi_io_res[count - 1] == NULL) { device_printf(dev, "too few I/O resources\n"); error = ENXIO; goto bad; } device_printf(dev, "%s mode found at %s 0x%jx on %s\n", mode, type == SYS_RES_IOPORT ? "io" : "mem", (uintmax_t)rman_get_start(sc->ipmi_io_res[0]), device_get_name(device_get_parent(dev))); sc->ipmi_dev = dev; /* * Setup an interrupt if we have an interrupt resource. We * don't support GPE interrupts via _GPE yet. */ sc->ipmi_irq_rid = 0; sc->ipmi_irq_res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &sc->ipmi_irq_rid, RF_SHAREABLE | RF_ACTIVE); /* Warn if _GPE exists. */ if (ACPI_SUCCESS(AcpiEvaluateObject(devh, "_GPE", NULL, NULL))) device_printf(dev, "_GPE support not implemented\n"); /* * We assume an alignment of 1 byte as currently the IPMI spec * doesn't provide any way to determine the alignment via ACPI. */ switch (interface_type) { case KCS_MODE: error = ipmi_kcs_attach(sc); if (error) goto bad; break; case SMIC_MODE: error = ipmi_smic_attach(sc); if (error) goto bad; break; } error = ipmi_attach(dev); if (error) goto bad; return (0); bad: ipmi_release_resources(dev); return (error); }