summaryrefslogtreecommitdiffstats
path: root/sys/i386/bios
diff options
context:
space:
mode:
authormdodd <mdodd@FreeBSD.org>2003-01-17 08:10:18 +0000
committermdodd <mdodd@FreeBSD.org>2003-01-17 08:10:18 +0000
commitdef7e1bda051583fcc3525070ac5429f314f7fcf (patch)
tree9569a08b4ce3cebe0d49d0bb941a139c6b6d5f61 /sys/i386/bios
parent67dc3cf7fb55dd4317169204e4235cc4b359827c (diff)
downloadFreeBSD-src-def7e1bda051583fcc3525070ac5429f314f7fcf.zip
FreeBSD-src-def7e1bda051583fcc3525070ac5429f314f7fcf.tar.gz
A driver for the System Management Application Program
Interface (SMAPI) BIOS, which is present on some IBM Thinkpad models (560, 600, 770 to name a few.) The SMAPI BIOS provides access to System Information, System Configuration, and Power Management.
Diffstat (limited to 'sys/i386/bios')
-rw-r--r--sys/i386/bios/smapi.c167
-rw-r--r--sys/i386/bios/smapi_bios.S54
-rw-r--r--sys/i386/bios/smapi_isa.c274
-rw-r--r--sys/i386/bios/smapi_var.h51
4 files changed, 546 insertions, 0 deletions
diff --git a/sys/i386/bios/smapi.c b/sys/i386/bios/smapi.c
new file mode 100644
index 0000000..e2e96ad
--- /dev/null
+++ b/sys/i386/bios/smapi.c
@@ -0,0 +1,167 @@
+/*-
+ * Copyright (c) 2003 Matthew N. Dodd <winter@jurai.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+
+#include <sys/module.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <machine/smapi.h>
+#include <i386/smapi/smapi_var.h>
+
+u_long smapi32_offset;
+u_short smapi32_segment;
+#define SMAPI32_SEGMENT 0x18
+
+devclass_t smapi_devclass;
+
+static d_open_t smapi_open;
+static d_close_t smapi_close;
+static d_ioctl_t smapi_ioctl;
+
+#define CDEV_MAJOR 183
+
+static struct cdevsw smapi_cdevsw = {
+ /* open */ smapi_open,
+ /* close */ smapi_close,
+ /* read */ noread,
+ /* write */ nowrite,
+ /* ioctl */ smapi_ioctl,
+ /* poll */ nopoll,
+ /* mmap */ nommap,
+ /* strategy */ nostrategy,
+ /* name */ "smapi",
+ /* maj */ CDEV_MAJOR,
+ /* dump */ nodump,
+ /* psize */ nopsize,
+ /* flags */ D_MEM,
+ /* kqfilter */ NULL,
+};
+
+static int
+smapi_open (dev, oflags, devtype, td)
+ dev_t dev;
+ int oflags;
+ int devtype;
+ d_thread_t * td;
+{
+
+ return (0);
+}
+
+static int
+smapi_close (dev, fflag, devtype, td)
+ dev_t dev;
+ int fflag;
+ int devtype;
+ d_thread_t * td;
+{
+
+ return (0);
+}
+
+static int
+smapi_ioctl (dev, cmd, data, fflag, td)
+ dev_t dev;
+ u_long cmd;
+ caddr_t data;
+ int fflag;
+ d_thread_t * td;
+{
+ struct smapi_softc *sc;
+ int error;
+
+ error = 0;
+ sc = devclass_get_softc(smapi_devclass, minor(dev));
+ if (sc == NULL) {
+ error = ENXIO;
+ goto fail;
+ }
+
+ switch (cmd) {
+ case SMAPIOGHEADER:
+ bcopy((caddr_t)sc->header, data,
+ sizeof(struct smapi_bios_header));
+ error = 0;
+ break;
+ case SMAPIOCGFUNCTION:
+ smapi32_segment = SMAPI32_SEGMENT;
+ smapi32_offset = sc->smapi32_entry;
+ error = smapi32((struct smapi_bios_parameter *)data,
+ (struct smapi_bios_parameter *)data);
+ break;
+ default:
+ error = ENOTTY;
+ }
+
+fail:
+ return (error);
+}
+
+int
+smapi_attach (struct smapi_softc *sc)
+{
+ struct smapi_bios_parameter input_param;
+ struct smapi_bios_parameter output_param;
+ int retval;
+
+ sc->cdev = make_dev(&smapi_cdevsw,
+ device_get_unit(sc->dev),
+ UID_ROOT, GID_WHEEL, 0600,
+ "%s%d",
+ smapi_cdevsw.d_name,
+ device_get_unit(sc->dev));
+
+ bzero(&input_param, sizeof(struct smapi_bios_parameter));
+ bzero(&output_param, sizeof(struct smapi_bios_parameter));
+ smapi32_segment = SMAPI32_SEGMENT;
+ smapi32_offset = sc->smapi32_entry;
+ retval = smapi32(&output_param, &output_param);
+
+#if 0
+ retval = smapi32_new(sc->smapi32_entry, SMAPI32_SEGMENT,
+ &output_param, &output_param);
+#endif
+
+ return (0);
+}
+
+int
+smapi_detach (struct smapi_softc *sc)
+{
+
+ destroy_dev(sc->cdev);
+ return (0);
+}
diff --git a/sys/i386/bios/smapi_bios.S b/sys/i386/bios/smapi_bios.S
new file mode 100644
index 0000000..2ada5c6
--- /dev/null
+++ b/sys/i386/bios/smapi_bios.S
@@ -0,0 +1,54 @@
+/* $FreeBSD$ */
+
+#include <machine/asmacros.h>
+
+ .data
+smapi32_segment_tmp: .word 0
+smapi32_offset_tmp: .long 0
+ .text
+/*
+ * smapi32(input_param, output_param)
+ * struct smapi_bios_parameter *input_parm;
+ * struct smapi_bios_parameter *output_parm;
+ */
+ENTRY(smapi32)
+ pushl %ebp /* Save frame */
+ movl %esp,%ebp
+
+ pushl %ds
+ pushl 0x0c(%ebp) /* Output Param */
+ pushl %ds
+ pushl 0x08(%ebp) /* Input Param */
+
+ movl $0,%eax /* Clear EAX (return 0) */
+ movw %cs,smapi32_segment /* Save CS */
+ lcall *(smapi32_offset)
+
+ leave
+ ret
+
+/*
+ * smapi32(offset, segment, input_param, output_param)
+ * u_int offset;
+ * u_short segment;
+ * struct smapi_bios_parameter *input_parm;
+ * struct smapi_bios_parameter *output_parm;
+ */
+ENTRY(smapi32_new)
+ pushl %ebp /* Save frame */
+ movl 0x08(%esp),%ebp
+ movl %ebp,smapi32_offset_tmp
+ movw 0x0c(%esp),%bp
+ movw %bp,smapi32_segment_tmp
+
+ pushl %ds
+ pushl 0x20(%ebp) /* Output Param */
+ pushl %ds
+ pushl 0x10(%ebp) /* Input Param */
+
+ movl $0,%eax
+ movw %cs,smapi32_segment_tmp
+ lcall *(smapi32_offset_tmp)
+
+ leave
+ ret
diff --git a/sys/i386/bios/smapi_isa.c b/sys/i386/bios/smapi_isa.c
new file mode 100644
index 0000000..bd6bfd3
--- /dev/null
+++ b/sys/i386/bios/smapi_isa.c
@@ -0,0 +1,274 @@
+/*-
+ * Copyright (c) 2003 Matthew N. Dodd <winter@jurai.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/socket.h>
+
+#include <sys/module.h>
+#include <sys/bus.h>
+
+#include <machine/bus.h>
+#include <machine/resource.h>
+#include <sys/rman.h>
+
+#include <isa/isavar.h>
+#include <isa/pnpvar.h>
+
+/* And all this for BIOS_PADDRTOVADDR() */
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <machine/md_var.h>
+#include <machine/pc/bios.h>
+
+#include <machine/smapi.h>
+#include <i386/smapi/smapi_var.h>
+
+static void smapi_isa_identify (driver_t *, device_t);
+static int smapi_isa_probe (device_t);
+static int smapi_isa_attach (device_t);
+static int smapi_isa_detach (device_t);
+static int smapi_modevent (module_t, int, void *);
+
+static int smapi_header_cksum (struct smapi_bios_header *);
+
+#define SMAPI_ID 0x0000a24d
+
+static struct isa_pnp_id smapi_ids[] = {
+ { SMAPI_ID, NULL }, /* SMB0000 */
+ { 0, NULL },
+};
+
+#define SMAPI_START 0xf0000
+#define SMAPI_END 0xffff0
+#define SMAPI_STEP 0x10
+
+#define SMAPI_SIGNATURE(h) ((h->signature[0] == '$') && \
+ (h->signature[1] == 'S') && \
+ (h->signature[2] == 'M') && \
+ (h->signature[3] == 'B'))
+
+static void
+smapi_isa_identify (driver_t *driver, device_t parent)
+{
+ device_t child;
+ struct resource *res;
+ struct smapi_bios_header *header;
+ u_int32_t chunk;
+ int rid;
+
+ rid = 0;
+ chunk = SMAPI_START;
+
+ child = BUS_ADD_CHILD(parent, ISA_ORDER_SENSITIVE, "smapi", -1);
+ device_set_driver(child, driver);
+ isa_set_logicalid(child, SMAPI_ID);
+ isa_set_vendorid(child, SMAPI_ID);
+
+ while (chunk < SMAPI_END) {
+ bus_set_resource(child, SYS_RES_MEMORY, rid, chunk,
+ sizeof(struct smapi_bios_header));
+ res = bus_alloc_resource(child, SYS_RES_MEMORY, &rid,
+ 0ul, ~0ul, 1, RF_ACTIVE);
+ if (res == NULL) {
+ bus_delete_resource(child, SYS_RES_MEMORY, rid);
+ chunk += SMAPI_STEP;
+ continue;
+ }
+ header = (struct smapi_bios_header *)rman_get_virtual(res);
+
+ if (SMAPI_SIGNATURE(header)) {
+ if (smapi_header_cksum(header)) {
+ device_printf(child, "SMAPI header checksum failed.\n");
+ } else {
+ goto found;
+ }
+ } else {
+ bus_release_resource(child, SYS_RES_MEMORY, rid, res);
+ bus_delete_resource(child, SYS_RES_MEMORY, rid);
+ }
+
+ chunk += SMAPI_STEP;
+ }
+
+ device_delete_child(parent, child);
+ return;
+
+found:
+ device_set_desc(child, "SMAPI BIOS");
+ return;
+}
+
+static int
+smapi_isa_probe (device_t dev)
+{
+ return (ISA_PNP_PROBE(device_get_parent(dev), dev, smapi_ids));
+}
+
+static int
+smapi_isa_attach (device_t dev)
+{
+ struct smapi_softc *sc;
+ int error;
+
+ sc = device_get_softc(dev);
+ error = 0;
+
+ sc->dev = dev;
+ sc->rid = 0;
+ sc->res = bus_alloc_resource(dev, SYS_RES_MEMORY, &sc->rid,
+ 0ul, ~0ul, 1, RF_ACTIVE);
+ if (sc->res == NULL) {
+ device_printf(dev, "Unable to allocate memory resource.\n");
+ error = ENOMEM;
+ goto bad;
+ }
+ sc->header = (struct smapi_bios_header *)rman_get_virtual(sc->res);
+ sc->smapi32_entry = (u_int32_t)BIOS_PADDRTOVADDR(
+ sc->header->prot32_segment +
+ sc->header->prot32_offset);
+
+ if (smapi_header_cksum(sc->header)) {
+ device_printf(dev, "SMAPI header checksum failed.\n");
+ error = ENXIO;
+ goto bad;
+ }
+
+ if (smapi_attach(sc)) {
+ device_printf(dev, "SMAPI attach failed.\n");
+ error = ENXIO;
+ goto bad;
+ }
+
+ device_printf(dev, "Version %02d.%02d, Length %d, Checksum 0x%02x\n",
+ sc->header->version_major, sc->header->version_minor,
+ sc->header->length, sc->header->checksum);
+ device_printf(dev, "Information=0x%b\n",
+ sc->header->information,
+ "\020"
+ "\001REAL_VM86"
+ "\002PROTECTED_16"
+ "\003PROTECTED_32");
+
+ if (bootverbose) {
+ if (sc->header->information & SMAPI_REAL_VM86)
+ device_printf(dev, "Real/VM86 mode: Segment 0x%04x, Offset 0x%04x\n",
+ sc->header->real16_segment,
+ sc->header->real16_offset);
+ if (sc->header->information & SMAPI_PROT_16BIT)
+ device_printf(dev, "16-bit Protected mode: Segment 0x%08x, Offset 0x%04x\n",
+ sc->header->prot16_segment,
+ sc->header->prot16_offset);
+ if (sc->header->information & SMAPI_PROT_32BIT)
+ device_printf(dev, "32-bit Protected mode: Segment 0x%08x, Offset 0x%08x\n",
+ sc->header->prot32_segment,
+ sc->header->prot32_offset);
+ }
+
+ return (0);
+bad:
+ if (sc->res)
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->rid, sc->res);
+ return (error);
+}
+
+static int
+smapi_isa_detach (device_t dev)
+{
+ struct smapi_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ (void)smapi_detach(sc);
+
+ if (sc->res)
+ bus_release_resource(dev, SYS_RES_MEMORY, sc->rid, sc->res);
+
+ return (0);
+}
+
+static int
+smapi_modevent (mod, what, arg)
+ module_t mod;
+ int what;
+ void * arg;
+{
+ device_t * devs;
+ int count;
+ int i;
+
+ switch (what) {
+ case MOD_LOAD:
+ break;
+ case MOD_UNLOAD:
+ devclass_get_devices(smapi_devclass, &devs, &count);
+ for (i = 0; i < count; i++) {
+ device_delete_child(device_get_parent(devs[i]), devs[i]);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return (0);
+}
+
+static device_method_t smapi_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_identify, smapi_isa_identify),
+ DEVMETHOD(device_probe, smapi_isa_probe),
+ DEVMETHOD(device_attach, smapi_isa_attach),
+ DEVMETHOD(device_detach, smapi_isa_detach),
+ { 0, 0 }
+};
+
+static driver_t smapi_driver = {
+ "smapi",
+ smapi_methods,
+ sizeof(struct smapi_softc),
+};
+
+DRIVER_MODULE(smapi, isa, smapi_driver, smapi_devclass, smapi_modevent, 0);
+MODULE_VERSION(smapi, 1);
+
+static int
+smapi_header_cksum (struct smapi_bios_header *header)
+{
+ u_int8_t *ptr;
+ u_int8_t cksum;
+ int i;
+
+ ptr = (u_int8_t *)header;
+ cksum = 0;
+ for (i = 0; i < header->length; i++) {
+ cksum += ptr[i];
+ }
+
+ return (cksum);
+}
diff --git a/sys/i386/bios/smapi_var.h b/sys/i386/bios/smapi_var.h
new file mode 100644
index 0000000..c05ae8f
--- /dev/null
+++ b/sys/i386/bios/smapi_var.h
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 2003 Matthew N. Dodd <winter@jurai.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+struct smapi_softc {
+ dev_t cdev;
+ device_t dev;
+ struct resource * res;
+ int rid;
+
+ u_int32_t smapi32_entry;
+
+ struct smapi_bios_header *header;
+};
+
+extern u_long smapi32_offset;
+extern u_short smapi32_segment;
+extern devclass_t smapi_devclass;
+
+int smapi_attach (struct smapi_softc *);
+int smapi_detach (struct smapi_softc *);
+
+extern int smapi32 (struct smapi_bios_parameter *,
+ struct smapi_bios_parameter *);
+extern int smapi32_new (u_long, u_short,
+ struct smapi_bios_parameter *,
+ struct smapi_bios_parameter *);
OpenPOWER on IntegriCloud