]> Devoid-pointer.net GitWeb - omnibook.git/commitdiff
Merge branche/new-backend 129:HEAD to trunk
authorMathieu Bérard <mathieu.berard@crans.org>
Sat, 9 Sep 2006 00:06:15 +0000 (00:06 +0000)
committerMathieu Bérard <mathieu.berard@crans.org>
Sat, 9 Sep 2006 00:06:15 +0000 (00:06 +0000)
33 files changed:
Makefile
ac.c
acpi.c [new file with mode: 0644]
apmemu.c
battery.c
blank.c
bluetooth.c [new file with mode: 0644]
compal.c
compat.h
debian/control
display.c
doc/ChangeLog
doc/README
doc/README-1st
doc/TODO
dock.c
dump.c
ec.c
ec.h
fan.c
fan_policy.c
hotkeys.c
info.c
init.c
lcd.c
misc/omnibook-integration.patch
muteled.c
nbsmi.c [new file with mode: 0644]
omnibook.h
sections.lds
temperature.c
touchpad.c
wireless.c [new file with mode: 0644]

index e684e6de03b4bf305f3457f27869e7a5f4f55451..0bbb25521dcba9a60c01236ec22bf69320f34eb7 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -27,7 +27,6 @@ INSTDIR       = extra
 #KSRC  = /usr/src/linux
 KSRC   = $(VMODDIR)/build
 KMODDIR        = $(KSRC)/drivers/misc/omnibook
-KINCDIR        = $(KSRC)/include/linux
 KDOCDIR        = $(KSRC)/Documentation/omnibook
 PWD    = $(shell pwd)
 TODAY  = $(shell date +%Y%m%d)
@@ -42,19 +41,16 @@ RM  = rm -f
 FIND   = find
 endif
 
-DEBUG  = # -D OMNIBOOK_DEBUG  -g -O0
+DEBUG  =  -D OMNIBOOK_DEBUG -g -O0
 
 EXTRA_CFLAGS += -D OMNIBOOK_STANDALONE $(DEBUG)
-EXTRA_LDFLAGS += $(src)/sections.lds
+EXTRA_LDFLAGS +=  $(src)/sections.lds
 
 
-OBJS   = ac.o battery.o blank.o display.o dock.o \
-         ec.o fan.o fan_policy.o init.o lcd.o hotkeys.o \
-         temperature.o touchpad.o dump.o info.o \
-         apmemu.o muteled.o compal.o
-
-
-# All extra flags delt with automagically
+OBJS   = init.o ec.o compal.o acpi.o nbsmi.o \
+          ac.o apmemu.o battery.o blank.o bluetooth.o display.o dock.o dump.o \
+         fan.o fan_policy.o hotkeys.o info.o lcd.o muteled.o temperature.o \
+          touchpad.o wireless.o
 
 obj-m         += $(MODULE_NAME).o
 omnibook-objs := $(OBJS)
@@ -63,11 +59,10 @@ all:                 $(MODULE_NAME).ko
 
 clean:
                make -C $(KSRC) M=$(PWD) clean
-               $(RM) *~ "#*#" .swp
+               $(RM) -r *~ "#*#" .swp
                $(RM) -r debian/omnibook-source *-stamp
                $(RM) -r Module.symvers Modules.symvers
-               (cd misc/obtest; $(RM) obtest *.o)
-
+               (cd misc/obtest; $(RM) obtest *.o;)
 
 install:       all
                # Removing module from locations used by previous versions
@@ -95,13 +90,10 @@ $(MODULE_NAME).ko:
 
 kinstall:
                $(RM) -r $(KMODDIR)
-               $(RM) $(KINCDIR)/omnibook.h
                $(MKDIR) $(KMODDIR)
-               $(INSTALL) *.c sections.lds $(KMODDIR)
-               $(INSTALL) apmemu.h compat.h ec.h laptop.h $(KMODDIR)
-               $(INSTALL) omnibook.h $(KINCDIR)
+               $(INSTALL) *.h *.c sections.lds $(KMODDIR)
                $(MKDIR) $(KDOCDIR)
-               $(INSTALL) doc/README doc/README-OneTouch $(KDOCDIR)
+               $(INSTALL) doc/README doc/README-Hotkeys $(KDOCDIR)
                
 kpatch:                kinstall
                (cd $(KSRC); patch -p1 < $(PWD)/misc/omnibook-integration.patch)
diff --git a/ac.c b/ac.c
index 2307eb1964a547dadbdac4a80292822fb0c3dcfe..cc3d0aec89f0c0f65155673cf3c2cbfdf6b5affa 100644 (file)
--- a/ac.c
+++ b/ac.c
  * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
  */
 
-#ifdef OMNIBOOK_STANDALONE
 #include "omnibook.h"
-#else
-#include <linux/omnibook.h>
-#endif
-
 #include "ec.h"
 
-static const struct omnibook_io_operation ac_io_table[] = {
-       { XE3GF|TSP10|TSM30X,               EC, XE3GF_ADP,  0, XE3GF_ADP_MASK},
-       { XE3GC|AMILOD,                     EC, XE3GC_STA1, 0, XE3GC_ADP_MASK},
-       { OB500|OB510|OB6000|OB6100|XE4500, EC, OB500_STA2, 0, OB500_ADP_MASK},
-       { OB4150,                           EC, OB4150_ADP, 0, OB4150_ADP_MASK},
-       { XE2,                              EC, XE2_STA1,   0, XE2_ADP_MASK},
-       { 0,}
-};
-
-static struct omnibook_io_operation *ac_io;
-       
-int omnibook_get_ac(void)
+int omnibook_get_ac(struct omnibook_operation *io_op)
 {
        u8 ac;
        int retval;
 
-       retval = omnibook_io_read( ac_io, &ac);
-       if (!retval)
-               retval = ac ? 1 : 0;
+       retval = io_op->backend->byte_read(io_op, &ac);
+       if(!retval)
+               retval = !!ac;
        return retval;
 }
 
-static int omnibook_ac_read(char *buffer)
+static int omnibook_ac_read(char *buffer,struct omnibook_operation *io_op)
 {
        int len = 0;
        int ac;
 
-       ac = omnibook_get_ac();
+       ac = omnibook_get_ac(io_op);
        if (ac < 0)
                return ac;
 
@@ -59,21 +43,28 @@ static int omnibook_ac_read(char *buffer)
        return len;
 }
 
-static int omnibook_ac_init(void)
-{
-       ac_io = omnibook_io_match(ac_io_table);
-       return ac_io ? 0 : -ENODEV;
-}
+static struct omnibook_tbl ac_table[] __initdata = {
+       { XE3GF|TSP10|TSM30X,                   SIMPLE_BYTE(EC,XE3GF_ADP,XE3GF_ADP_MASK)},
+       { XE3GC|AMILOD,                         SIMPLE_BYTE(EC,XE3GC_STA1,XE3GC_ADP_MASK)},
+       { OB500|OB510|OB6000|OB6100|XE4500,     SIMPLE_BYTE(EC,OB500_STA2,OB500_ADP_MASK)},
+       { OB4150,                               SIMPLE_BYTE(EC,OB4150_ADP,OB4150_ADP_MASK)},
+       { XE2,                                  SIMPLE_BYTE(EC,XE2_STA1,XE2_ADP_MASK)},
+       { 0,}
+};
 
-static struct omnibook_feature __declared_feature ac_feature = {
-        .name = "ac",
-        .enabled = 1,
-        .read = omnibook_ac_read,
-        .init = omnibook_ac_init,
-        .ectypes = XE3GF|XE3GC|OB500|OB510|OB6000|OB6100|XE4500|OB4150|XE2|AMILOD|TSP10|TSM30X,
+struct omnibook_feature __declared_feature ac_driver = {
+       .name = "ac",
+#ifdef CONFIG_OMNIBOOK_LEGACY
+       .enabled = 1,
+#else
+       .enabled = 0,
+#endif
+       .read = omnibook_ac_read,
+       .ectypes = XE3GF|XE3GC|OB500|OB510|OB6000|OB6100|XE4500|OB4150|XE2|AMILOD|TSP10|TSM30X,
+       .tbl = ac_table,
 };
 
-module_param_named(ac, ac_feature.enabled, int, S_IRUGO);
+module_param_named(ac, ac_driver.enabled, int, S_IRUGO);
 MODULE_PARM_DESC(ac, "Use 0 to disable, 1 to enable AC adapter status monitoring");
 
 /* End of file */
diff --git a/acpi.c b/acpi.c
new file mode 100644 (file)
index 0000000..9878536
--- /dev/null
+++ b/acpi.c
@@ -0,0 +1,232 @@
+/*
+ * acpi.c -- ACPI methods low-level access code for TSM30X class laptops
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * Written by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ *
+ */
+
+
+#include "omnibook.h"
+#include "ec.h"
+
+#ifdef CONFIG_ACPI
+
+#include <acpi/acpi_drivers.h>
+
+/*
+ * ACPI backend masks and strings
+ */
+
+#define EC_ACPI_DEVICE "\\_SB.PCI0.LPCB.EC0"
+
+#define GET_WIRELESS_METHOD "ANTR"
+#define SET_WIRELESS_METHOD "ANTW"
+#define WLEX_MASK      0x4
+#define WLAT_MASK      0x1
+#define BTEX_MASK      0x8
+#define BTAT_MASK      0x2
+#define KLSW_MASK      0x10
+
+#define GET_DISPLAY_METHOD "DOSS"
+#define SET_DISPLAY_METHOD "DOSW"
+/* Display reading masks CADL = detected, CSTE = enabled */
+#define        LCD_CADL        0x10
+#define        CRT_CADL        0x20
+#define        TVO_CADL        0x40
+#define        LCD_CSTE        0x1
+#define        CRT_CSTE        0x2
+#define        TVO_CSTE        0x4
+
+/*
+ * Probe for expected ACPI device
+ * FIXME we check only the ACPI device and not the associated methods
+ */
+static int omnibook_acpi_probe(const struct omnibook_operation *io_op)
+{
+       acpi_handle dev_handle; 
+       int retval = 0;
+       
+       if(acpi_disabled) {
+               printk(O_ERR "ACPI is disabled: feature unavailable.\n");
+               return -ENODEV;
+       }
+
+       if(acpi_get_handle(NULL, EC_ACPI_DEVICE, &dev_handle) != AE_OK) {
+               printk(O_ERR "Can't get handle on ACPI EC device");     
+               return -ENODEV;
+       }
+
+       acpi_backend.data = dev_handle;
+
+       dprintk("ACPI probing was successfull\n");
+       return retval;
+}
+
+/*
+ * Execute an ACPI method which return either integer or nothing
+ * (acpi_evaluate_object wrapper)
+ */
+static int omnibook_acpi_execute(char *method, const int *param, int *result)
+{
+
+       struct acpi_object_list args_list;
+       struct acpi_buffer buff;
+       union acpi_object arg, out_objs[1];
+
+       if(!(acpi_backend.data)) {
+               dprintk("no handle on EC ACPI device"); 
+               return -ENODEV;
+       }
+       
+       if(param) {
+               args_list.count = 1;
+               args_list.pointer = &arg;
+               arg.type = ACPI_TYPE_INTEGER;
+               arg.integer.value = *param;
+       } else
+               args_list.count = 0;
+       
+       buff.length = sizeof(out_objs);
+        buff.pointer = out_objs;
+       
+       if(acpi_evaluate_object(acpi_backend.data, method, &args_list, &buff) != AE_OK) {
+               printk(O_ERR "ACPI method execution failed\n");
+               return -EIO;
+       }
+       
+       if(!result) /* We don't care what the method returned here */
+               return 0;
+       
+       if(out_objs[0].type != ACPI_TYPE_INTEGER) {
+               printk(O_ERR "ACPI method result is not a number\n");
+               return -EINVAL;
+       }
+
+       *result = out_objs[0].integer.value;
+       return 0;
+}
+
+static int omnibook_acpi_get_wireless(const struct omnibook_operation *io_op, unsigned int *state)
+{
+       int retval = 0;
+       int raw_state;
+       
+       if ((retval = omnibook_acpi_execute(GET_WIRELESS_METHOD,0,&raw_state)))
+               return retval;
+
+
+       *state = ( raw_state & WLEX_MASK ) ? WIFI_EX : 0;
+       *state |= ( raw_state & WLAT_MASK ) ? WIFI_STA : 0;
+       *state |= ( raw_state & KLSW_MASK ) ? KILLSWITCH : 0;
+       *state |= ( raw_state & BTEX_MASK ) ? BT_EX : 0;
+       *state |= ( raw_state & BTAT_MASK ) ? BT_STA : 0;
+       
+       return retval;
+}
+
+static int omnibook_acpi_set_wireless(const struct omnibook_operation *io_op, unsigned int state)
+{
+       int retval = 0;
+       int raw_state;
+       
+       raw_state = state & WIFI_STA; /* bit 0 */
+       raw_state |= (state & BT_STA) << 0x1; /* bit 1 */
+
+       dprintk("set_wireless raw_state: %x\n", raw_state);
+
+       if ((retval = omnibook_acpi_execute(SET_WIRELESS_METHOD,&raw_state,NULL)))
+               return retval;
+       
+       return retval;
+}
+
+static int omnibook_acpi_get_display(const struct omnibook_operation *io_op, unsigned int *state)
+{
+       int retval = 0;
+       int raw_state = 0;
+
+       retval = omnibook_acpi_execute(GET_DISPLAY_METHOD, 0 , &raw_state);
+       if(retval < 0)
+               return retval;
+
+       /* Backend specific to backend-neutral conversion */
+       *state =  ( raw_state & LCD_CSTE) ? DISPLAY_LCD_ON : 0; 
+       *state |= ( raw_state & CRT_CSTE) ? DISPLAY_CRT_ON : 0;
+       *state |= ( raw_state & TVO_CSTE) ? DISPLAY_TVO_ON : 0; 
+
+       *state |= ( raw_state & LCD_CADL) ? DISPLAY_LCD_DET : 0;
+       *state |= ( raw_state & CRT_CADL) ? DISPLAY_CRT_DET : 0;
+       *state |= ( raw_state & TVO_CADL) ? DISPLAY_TVO_DET : 0;
+       
+
+       return DISPLAY_LCD_ON|DISPLAY_CRT_ON|DISPLAY_TVO_ON|
+               DISPLAY_LCD_DET|DISPLAY_CRT_DET|DISPLAY_TVO_DET;
+}
+
+static const unsigned int acpi_display_mode_list[] = {
+       DISPLAY_LCD_ON,
+       DISPLAY_CRT_ON,
+       DISPLAY_LCD_ON|DISPLAY_CRT_ON,
+       DISPLAY_TVO_ON,
+       DISPLAY_LCD_ON|DISPLAY_TVO_ON,
+       DISPLAY_CRT_ON|DISPLAY_TVO_ON,
+       DISPLAY_LCD_ON|DISPLAY_CRT_ON|DISPLAY_TVO_ON,
+};
+
+static int omnibook_acpi_set_display(const struct omnibook_operation *io_op, unsigned int state)
+{
+       int retval = 0;
+       int i, matched;
+
+       for(i = 0; i < ARRAY_SIZE(acpi_display_mode_list); i++) {
+               if(acpi_display_mode_list[i] == state) {
+                       matched = i + 1; /* raw state is array row number + 1 */
+                       break;
+               }       
+       }
+       if(!matched) {
+               printk("Display mode %x is unsupported.\n", state);
+               return -EINVAL;
+       }
+       
+       retval = omnibook_acpi_execute(SET_DISPLAY_METHOD, &matched, NULL );
+       if(retval < 0)
+               return retval;
+
+       return DISPLAY_LCD_ON|DISPLAY_CRT_ON|DISPLAY_TVO_ON;
+}
+
+struct omnibook_backend acpi_backend = {
+       .name = "acpi",
+       .init = omnibook_acpi_probe,
+       .aerial_get = omnibook_acpi_get_wireless,
+       .aerial_set = omnibook_acpi_set_wireless,
+       .display_get = omnibook_acpi_get_display,
+       .display_set = omnibook_acpi_set_display,
+};
+
+#else /* CONFIG_ACPI */
+
+/* dummy backend for non-ACPI systems */
+static int _fail_probe(const struct omnibook_operation *io_op)
+{
+       return -ENODEV;
+}
+
+struct omnibook_backend acpi_backend = {
+        .name = "acpi",
+        .init = _fail_probe,
+};
+
+#endif /* CONFIG_ACPI */
index 192fca51fe530a0a24137c2b1d69c939b05c5403..832959bb5b9221429296bbbe2f75d79addda389e 100644 (file)
--- a/apmemu.c
+++ b/apmemu.c
  * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
  */
 
-#ifdef OMNIBOOK_STANDALONE
 #include "omnibook.h"
-#else
-#include <linux/omnibook.h>
-#endif
 
+#ifdef CONFIG_OMNIBOOK_LEGACY
 
 #ifdef CONFIG_APM
 #include <linux/apm_bios.h>
@@ -68,7 +65,9 @@
       -1: Unknown
    8) min = minutes; sec = seconds */
 
-static int omnibook_apmemu_read(char *buffer)
+extern struct omnibook_feature ac_driver;
+
+static int omnibook_apmemu_read(char *buffer, struct omnibook_operation *io_op)
 {
        int retval;
        int len = 0;
@@ -100,7 +99,10 @@ static int omnibook_apmemu_read(char *buffer)
                "?"
        };
 
-       ac = omnibook_get_ac();
+/*
+ * FIXME: Broken, how do we know ac and battery are in a usable state ?
+ */
+       ac = omnibook_get_ac(ac_driver.io_op);
        apm.ac = (ac) ? APMEMU_AC_ONLINE : APMEMU_AC_OFFLINE;
        /* Asking for Battery 0 as APM does */
        retval = omnibook_get_battery_status(0, &battstat);
@@ -137,7 +139,7 @@ static int omnibook_apmemu_read(char *buffer)
        return len;
 }
 
-static int omnibook_apmemu_init(void)
+static int __init omnibook_apmemu_init(struct omnibook_operation *io_op)
 {
 #ifdef CONFIG_APM
        if (!apm_info.disabled) {
@@ -148,21 +150,18 @@ static int omnibook_apmemu_init(void)
        return 0;
 }
 
-static struct omnibook_feature __declared_feature apmemu_feature = {
+static struct omnibook_feature __declared_feature apmemu_driver = {
         .name = "apmemu",
         .proc_entry = "apm", /* create /proc/apm */
-#ifdef CONFIG_OMNIBOOK_APMEMU
          .enabled = 1,
-#else
-        .enabled = 0,
-#endif
         .read = omnibook_apmemu_read,
         .init = omnibook_apmemu_init,
         .ectypes = XE3GF|XE3GC|TSP10,
 };
 
 
-module_param_named(apmemu, apmemu_feature.enabled, int, S_IRUGO);
+module_param_named(apmemu, apmemu_driver.enabled, int, S_IRUGO);
 MODULE_PARM_DESC(apmemu, "Use 0 to disable, 1 to enable /proc/apm emulation");
 
+#endif /* CONFIG_OMNIBOOK_LEGACY */
 /* End of file */
index 3c352fb1b0a934e5256e3c875e274a93f64ad641..f9eb553969c6d03b142364f047f92af3d1f14f56 100644 (file)
--- a/battery.c
+++ b/battery.c
  * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
  */
 
-#ifdef OMNIBOOK_STANDALONE
 #include "omnibook.h"
-#else
-#include <linux/omnibook.h>
-#endif
 
 #include "ec.h"
 
-static int omnibook_ec_read16(u8 addr, u16 * data)
+static int ec_read16(u8 addr, u16 * data)
 {
        int retval;
        u8 high;
        u8 low;
        u16 result;
 
-       retval = omnibook_ec_read(addr, &low);
+       retval = legacy_ec_read(addr, &low);
        if (retval)
                return retval;
-       retval = omnibook_ec_read(addr + 0x01, &high);
+       retval = legacy_ec_read(addr + 0x01, &high);
        result = ((high << 8) + low);
        *data = result;
        return retval;
@@ -55,7 +51,7 @@ static int omnibook_battery_present(int num)
 
                if (num >= 2)
                        return -EINVAL;
-               if ((retval = omnibook_ec_read(XE3GF_BAL, &bat)))
+               if ((retval = legacy_ec_read(XE3GF_BAL, &bat)))
                        return retval;
                mask = XE3GF_BAL0_MASK;
                for (i = 0; i < num; i++)
@@ -67,7 +63,7 @@ static int omnibook_battery_present(int num)
        } else if (omnibook_ectype & (XE3GC|AMILOD) ) {
                if (num >= 2)
                        return -EINVAL;
-               if ((retval = omnibook_ec_read(XE3GC_BAT, &bat)))
+               if ((retval = legacy_ec_read(XE3GC_BAT, &bat)))
                        return retval;
                mask = XE3GC_BAT0_MASK;
                for (i = 0; i < num; i++)
@@ -104,19 +100,19 @@ static int omnibook_get_battery_info(int num,
                        return retval;
                if (retval) {
                        if ((retval =
-                            omnibook_ec_read(XE3GF_BTY0 + (offset * num),
+                            legacy_ec_read(XE3GF_BTY0 + (offset * num),
                                     &(*battinfo).type)))
                                return retval;
                        if ((retval =
-                            omnibook_ec_read16(XE3GF_BSN0 + (offset * num),
+                            ec_read16(XE3GF_BSN0 + (offset * num),
                                       &(*battinfo).sn)))
                                return retval;
                        if ((retval =
-                            omnibook_ec_read16(XE3GF_BDV0 + (offset * num),
+                            ec_read16(XE3GF_BDV0 + (offset * num),
                                       &(*battinfo).dv)))
                                return retval;
                        if ((retval =
-                            omnibook_ec_read16(XE3GF_BDC0 + (offset * num),
+                            ec_read16(XE3GF_BDC0 + (offset * num),
                                       &(*battinfo).dc)))
                                return retval;
 
@@ -134,15 +130,15 @@ static int omnibook_get_battery_info(int num,
                        return retval;
                if (retval) {
                        if ((retval =
-                            omnibook_ec_read16(XE3GC_BDV0 + (offset * num),
+                            ec_read16(XE3GC_BDV0 + (offset * num),
                                       &(*battinfo).dv)))
                                return retval;
                        if ((retval =
-                            omnibook_ec_read16(XE3GC_BDC0 + (offset * num),
+                            ec_read16(XE3GC_BDC0 + (offset * num),
                                       &(*battinfo).dc)))
                                return retval;
                        if ((retval =
-                            omnibook_ec_read(XE3GC_BTY0 + (offset * num),
+                            legacy_ec_read(XE3GC_BTY0 + (offset * num),
                                     &(*battinfo).type)))
                                return retval;
 
@@ -161,15 +157,15 @@ static int omnibook_get_battery_info(int num,
                        return retval;
                if (retval) {
                        if ((retval =
-                            omnibook_ec_read16(AMILOD_BDV0 + (offset * num),
+                            ec_read16(AMILOD_BDV0 + (offset * num),
                                       &(*battinfo).dv)))
                                return retval;
                        if ((retval =
-                            omnibook_ec_read16(AMILOD_BDC0 + (offset * num),
+                            ec_read16(AMILOD_BDC0 + (offset * num),
                                       &(*battinfo).dc)))
                                return retval;
                        if ((retval =
-                            omnibook_ec_read(AMILOD_BTY0 + (offset * num),
+                            legacy_ec_read(AMILOD_BTY0 + (offset * num),
                                     &(*battinfo).type)))
                                return retval;
 
@@ -243,22 +239,22 @@ int omnibook_get_battery_status(int num,
                        return retval;
                if (retval) {
                        if ((retval =
-                            omnibook_ec_read(XE3GF_BST0 + (offset * num), &status)))
+                            legacy_ec_read(XE3GF_BST0 + (offset * num), &status)))
                                return retval;
                        if ((retval =
-                            omnibook_ec_read16(XE3GF_BRC0 + (offset * num),
+                            ec_read16(XE3GF_BRC0 + (offset * num),
                                       &(*battstat).rc)))
                                return retval;
                        if ((retval =
-                            omnibook_ec_read16(XE3GF_BPV0 + (offset * num),
+                            ec_read16(XE3GF_BPV0 + (offset * num),
                                       &(*battstat).pv)))
                                return retval;
                        if ((retval =
-                            omnibook_ec_read16(XE3GF_BFC0 + (offset * num),
+                            ec_read16(XE3GF_BFC0 + (offset * num),
                                       &(*battstat).lc)))
                                return retval;
                        if ((retval =
-                            omnibook_ec_read(XE3GF_GAU0 + (offset * num),
+                            legacy_ec_read(XE3GF_GAU0 + (offset * num),
                                     &(*battstat).gauge)))
                                return retval;
 
@@ -287,18 +283,18 @@ int omnibook_get_battery_status(int num,
                        return retval;
                if (retval) {
                        if ((retval =
-                            omnibook_ec_read(XE3GC_BST0 + (offset * num), &status)))
+                            legacy_ec_read(XE3GC_BST0 + (offset * num), &status)))
                                return retval;
                        if ((retval =
-                            omnibook_ec_read16(XE3GC_BRC0 + (offset * num),
+                            ec_read16(XE3GC_BRC0 + (offset * num),
                                       &(*battstat).rc)))
                                return retval;
                        if ((retval =
-                            omnibook_ec_read16(XE3GC_BPV0 + (offset * num),
+                            ec_read16(XE3GC_BPV0 + (offset * num),
                                       &(*battstat).pv)))
                                return retval;
                        if ((retval =
-                            omnibook_ec_read16(XE3GC_BDC0 + (offset * num), &dc)))
+                            ec_read16(XE3GC_BDC0 + (offset * num), &dc)))
                                return retval;
 
                        if (status & XE3GC_BST_MASK_CRT)
@@ -329,18 +325,18 @@ int omnibook_get_battery_status(int num,
                        return retval;
                if (retval) {
                        if ((retval =
-                            omnibook_ec_read(AMILOD_BST0 + (offset * num), &status)))
+                            legacy_ec_read(AMILOD_BST0 + (offset * num), &status)))
                                return retval;
                        if ((retval =
-                            omnibook_ec_read16(AMILOD_BRC0 + (offset * num),
+                            ec_read16(AMILOD_BRC0 + (offset * num),
                                       &(*battstat).rc)))
                                return retval;
                        if ((retval =
-                            omnibook_ec_read16(AMILOD_BPV0 + (offset * num),
+                            ec_read16(AMILOD_BPV0 + (offset * num),
                                       &(*battstat).pv)))
                                return retval;
                        if ((retval =
-                            omnibook_ec_read16(AMILOD_BDC0 + (offset * num), &dc)))
+                            ec_read16(AMILOD_BDC0 + (offset * num), &dc)))
                                return retval;
 
                        if (status & AMILOD_BST_MASK_CRT)
@@ -368,27 +364,27 @@ int omnibook_get_battery_status(int num,
        } else if (omnibook_ectype & (OB500|OB510) ) {
                switch (num) {
                case 0:
-                       if ((retval = omnibook_ec_read(OB500_BT1S, &status)))
+                       if ((retval = legacy_ec_read(OB500_BT1S, &status)))
                                return retval;
-                       if ((retval = omnibook_ec_read16(OB500_BT1C, &(*battstat).rc)))
+                       if ((retval = ec_read16(OB500_BT1C, &(*battstat).rc)))
                                return retval;
-                       if ((retval = omnibook_ec_read16(OB500_BT1V, &(*battstat).pv)))
+                       if ((retval = ec_read16(OB500_BT1V, &(*battstat).pv)))
                                return retval;
                        break;
                case 1:
-                       if ((retval = omnibook_ec_read(OB500_BT2S, &status)))
+                       if ((retval = legacy_ec_read(OB500_BT2S, &status)))
                                return retval;
-                       if ((retval = omnibook_ec_read16(OB500_BT2C, &(*battstat).rc)))
+                       if ((retval = ec_read16(OB500_BT2C, &(*battstat).rc)))
                                return retval;
-                       if ((retval = omnibook_ec_read16(OB500_BT2V, &(*battstat).pv)))
+                       if ((retval = ec_read16(OB500_BT2V, &(*battstat).pv)))
                                return retval;
                        break;
                case 2:
-                       if ((retval = omnibook_ec_read(OB500_BT3S, &status)))
+                       if ((retval = legacy_ec_read(OB500_BT3S, &status)))
                                return retval;
-                       if ((retval = omnibook_ec_read16(OB500_BT3C, &(*battstat).rc)))
+                       if ((retval = ec_read16(OB500_BT3C, &(*battstat).rc)))
                                return retval;
-                       if ((retval = omnibook_ec_read16(OB500_BT3V, &(*battstat).pv)))
+                       if ((retval = ec_read16(OB500_BT3V, &(*battstat).pv)))
                                return retval;
                        break;
                default:
@@ -413,19 +409,19 @@ int omnibook_get_battery_status(int num,
        } else if (omnibook_ectype & (OB6000|OB6100|XE4500) ) {
                switch (num) {
                case 0:
-                       if ((retval = omnibook_ec_read(OB500_BT1S, &status)))
+                       if ((retval = legacy_ec_read(OB500_BT1S, &status)))
                                return retval;
-                       if ((retval = omnibook_ec_read16(OB500_BT1C, &(*battstat).rc)))
+                       if ((retval = ec_read16(OB500_BT1C, &(*battstat).rc)))
                                return retval;
-                       if ((retval = omnibook_ec_read16(OB500_BT1V, &(*battstat).pv)))
+                       if ((retval = ec_read16(OB500_BT1V, &(*battstat).pv)))
                                return retval;
                        break;
                case 1:
-                       if ((retval = omnibook_ec_read(OB500_BT3S, &status)))
+                       if ((retval = legacy_ec_read(OB500_BT3S, &status)))
                                return retval;
-                       if ((retval = omnibook_ec_read16(OB500_BT3C, &(*battstat).rc)))
+                       if ((retval = ec_read16(OB500_BT3C, &(*battstat).rc)))
                                return retval;
-                       if ((retval = omnibook_ec_read16(OB500_BT3V, &(*battstat).pv)))
+                       if ((retval = ec_read16(OB500_BT3V, &(*battstat).pv)))
                                return retval;
                        break;
                default:
@@ -448,7 +444,7 @@ int omnibook_get_battery_status(int num,
        return 0;
 }
 
-static int omnibook_battery_read(char *buffer)
+static int omnibook_battery_read(char *buffer,struct omnibook_operation *io_op)
 {
        char *statustr;
        char *typestr;
@@ -553,14 +549,18 @@ static int omnibook_battery_read(char *buffer)
        return len;
 }
 
-static struct omnibook_feature __declared_feature battery_feature  = {
+static struct omnibook_feature __declared_feature battery_driver = {
         .name = "battery",
+#ifdef CONFIG_OMNIBOOK_LEGACY
         .enabled = 1,
+#else
+        .enabled = 0,
+#endif
         .read = omnibook_battery_read,
-        .ectypes = XE3GF|XE3GC|AMILOD|TSP10, /* FIXME: OB500|OB6000|OB6100|XE4500 */
+        .ectypes = XE3GF|XE3GC|AMILOD|TSP10|TSM30X, /* FIXME: OB500|OB6000|OB6100|XE4500 */
 };
 
 
-module_param_named(battery, battery_feature.enabled, int, S_IRUGO);
+module_param_named(battery, battery_driver.enabled, int, S_IRUGO);
 MODULE_PARM_DESC(battery, "Use 0 to disable, 1 to enable battery status monitoring");
 /* End of file */
diff --git a/blank.c b/blank.c
index b4d31f53238ea7751bc7f7bcbdfda67ac40cca9a..cf8150190cdffb6adc7887b9cd69890d074a5016 100644 (file)
--- a/blank.c
+++ b/blank.c
  * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
  */
 
-#ifdef OMNIBOOK_STANDALONE
 #include "omnibook.h"
-#else
-#include <linux/omnibook.h>
-#endif
 
 #include <asm/io.h>
 #include "ec.h"
 
+static struct omnibook_feature blank_driver;
+
 static int omnibook_console_blank_enabled = 0;
 
 extern int (*console_blank_hook) (int);
 
+/*
+ * We would need an io_op parameter,but we are bound to the crapy
+ * console_blank_hook here
+ */
+
 int omnibook_lcd_blank(int blank)
 {
        int retval = 0;
-       u8 cmd;
-       /*
-        * XE3GF
-        * XE3GC
-        * AMILOD
-        * TSP10
-        * TSM30X
-        * TSM40
-        */
-       if (omnibook_ectype & (XE3GF|XE3GC|AMILOD|TSP10|TSM30X|TSM40) ) {
-               cmd = blank ? OMNIBOOK_KBC_CMD_LCD_OFF : OMNIBOOK_KBC_CMD_LCD_ON;
-               if ((retval =
-                    omnibook_kbc_command(OMNIBOOK_KBC_CONTROL_CMD, cmd)))
-                       return retval;
-       /*
-        * OB500
-        * OB6000
-        * XE2
-        */
-       } else if (omnibook_ectype & (OB500|OB6000|XE2) ) {
-               cmd = inb(OB500_GPO1);
-               cmd = blank ? cmd & ~OB500_BKLT_MASK : cmd | OB500_BKLT_MASK;
-               outb(cmd, OB500_GPO1);
-       /*
-        * OB510
-        * OB61000
-        */
-       } else if (omnibook_ectype & (OB510|OB6100) ) {
-               cmd = inb(OB510_GPO2);
-               cmd = blank ? cmd & ~OB510_BKLT_MASK : cmd | OB510_BKLT_MASK;
-               outb(cmd, OB510_GPO2);
-       /*
-        * UNKNOWN
-        */
-       } else {
-               printk(O_INFO
+       
+       if ( blank_driver.io_op->backend == PIO )
+               omnibook_apply_write_mask(blank_driver.io_op, blank);
+       else if ( blank_driver.io_op->backend == KBC )
+               omnibook_toggle(blank_driver.io_op, blank);
+       else {
+               printk(O_WARN
                       "LCD console blanking is unsupported on this machine.\n");
                retval = -ENODEV;
        }
+       
        return retval;
 }
 
-static int omnibook_console_blank_enable(void)
+static int console_blank_register_hook(void)
 {
        if (omnibook_console_blank_enabled == 0) {
                if (console_blank_hook == NULL) {
@@ -90,7 +65,7 @@ static int omnibook_console_blank_enable(void)
        return 0;
 }
 
-static int omnibook_console_blank_disable(void)
+static int console_blank_unregister_hook(void)
 {
        if (console_blank_hook == omnibook_lcd_blank) {
                console_blank_hook = NULL;
@@ -106,7 +81,7 @@ static int omnibook_console_blank_disable(void)
        return 0;
 }
 
-static int omnibook_console_blank_read(char *buffer)
+static int omnibook_console_blank_read(char *buffer,struct omnibook_operation *io_op)
 {
        int len = 0;
 
@@ -117,17 +92,17 @@ static int omnibook_console_blank_read(char *buffer)
        return len;
 }
 
-static int omnibook_console_blank_write(char *buffer)
+static int omnibook_console_blank_write(char *buffer,struct omnibook_operation *io_op)
 {
        int retval;
 
        switch (*buffer) {
        case '0':
-               if ((retval = omnibook_console_blank_disable()))
+               if ((retval = console_blank_unregister_hook()))
                        return retval;
                break;
        case '1':
-               if ((retval = omnibook_console_blank_enable()))
+               if ((retval = console_blank_register_hook()))
                        return retval;
                break;
        default:
@@ -136,23 +111,25 @@ static int omnibook_console_blank_write(char *buffer)
        return 0;
 }
 
-static int omnibook_console_blank_init(void)
+static int __init omnibook_console_blank_init(struct omnibook_operation *io_op)
 {
-
-       int retval;
-
-       if ((retval = omnibook_console_blank_enable()))
-               return retval;
-
-       return 0;
+       return console_blank_register_hook();
 }
 
-static void omnibook_console_blank_cleanup(void)
+static void __exit omnibook_console_blank_cleanup(struct omnibook_operation *io_op)
 {
-       omnibook_console_blank_disable();
+       console_blank_unregister_hook();
 }
 
-static struct omnibook_feature __declared_feature blank_feature = {
+static struct omnibook_tbl blank_table[] __initdata = {
+       { XE3GF|XE3GC|AMILOD|TSP10|TSM30X|TSM40, COMMAND(KBC,OMNIBOOK_KBC_CMD_LCD_OFF,OMNIBOOK_KBC_CMD_LCD_ON)},
+       { OB500|OB6000|XE2, { PIO, OB500_GPO1, OB500_GPO1, 0, -OB500_BKLT_MASK, OB500_BKLT_MASK}},
+       { OB510|OB6100,     { PIO, OB510_GPO2, OB510_GPO2, 0, -OB510_BKLT_MASK, OB510_BKLT_MASK}},
+       { 0,}
+};
+
+
+static struct omnibook_feature __declared_feature blank_driver = {
         .name = "blank",
         .enabled = 1,
         .read = omnibook_console_blank_read,
@@ -160,8 +137,9 @@ static struct omnibook_feature __declared_feature blank_feature = {
         .init = omnibook_console_blank_init,
         .exit = omnibook_console_blank_cleanup,
         .ectypes = XE3GF|XE3GC|OB500|OB510|OB6000|OB6100|XE2|AMILOD|TSP10|TSM30X|TSM40,
+        .tbl = blank_table,
 };
 
-module_param_named(blank, blank_feature.enabled, int, S_IRUGO);
+module_param_named(blank, blank_driver.enabled, int, S_IRUGO);
 MODULE_PARM_DESC(blank, "Use 0 to disable, 1 to enable lcd console blanking");
 /* End of file */
diff --git a/bluetooth.c b/bluetooth.c
new file mode 100644 (file)
index 0000000..66c8ea1
--- /dev/null
@@ -0,0 +1,95 @@
+/*
+ * wireless.c Bluetooth feature
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * Written by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ *
+ */
+#include "omnibook.h"
+#include "ec.h"
+
+static int omnibook_bt_read(char *buffer,struct omnibook_operation *io_op)
+{
+       int len = 0;
+       int retval;
+       unsigned int state; 
+       
+       if((retval = io_op->backend->aerial_get(io_op, &state)))
+               return retval;
+       
+       len += sprintf(buffer + len,"Bluetooth adapter is %s", (state & BT_EX) ? "present" : "absent");
+       if (state & BT_EX)
+               len += sprintf(buffer + len," and %s", (state & BT_STA) ? "enabled" : "disabled");
+       len += sprintf(buffer + len,".\n");     
+       return len;
+       
+}
+
+static int omnibook_bt_write(char *buffer,struct omnibook_operation *io_op)
+{
+       int retval = 0; 
+       unsigned int state;
+       
+       if((retval = io_op->backend->aerial_get(io_op, &state)))
+               return retval;
+       
+       if(*buffer == '0' )
+               state &= ~BT_STA;
+       else if (*buffer == '1' )
+               state |= BT_STA;
+       else
+               return -EINVAL;
+       
+       if((retval = io_op->backend->aerial_set(io_op, state)))
+               return retval;
+
+       return retval;  
+}
+
+static struct omnibook_feature bt_feature;
+
+static int __init omnibook_bt_init(struct omnibook_operation *io_op)
+{
+       int retval = 0;
+       unsigned int state;
+
+/*
+ *  Refuse enabling/disabling a non-existent device
+ */
+       
+       if((retval = io_op->backend->aerial_get(io_op, &state)))
+               return retval;
+       
+       if(!(state & BT_EX))
+               bt_feature.write = NULL;        
+       
+       return retval;
+}
+
+/*
+ * To avoid duplication the table is in wireless.c
+ */
+extern struct omnibook_tbl wireless_table[];
+
+static struct omnibook_feature __declared_feature bt_driver = {
+       .name = "bluetooth",
+       .enabled = 1,
+       .read = omnibook_bt_read,
+       .write = omnibook_bt_write,
+       .init = omnibook_bt_init,
+       .ectypes = TSM30X|TSM40,
+       .tbl = wireless_table,
+};
+
+module_param_named(bluetooth, bt_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(bluetooth, "Use 0 to disable, 1 to enable bluetooth adapter control");
index 8b6df94c60590b83e47be103e38b769706da530e..985feaf6d4a30eb979ae500e3a8df08234251780 100644 (file)
--- a/compal.c
+++ b/compal.c
  *
  */
 
-#ifdef OMNIBOOK_STANDALONE
+
 #include "omnibook.h"
-#else
-#include <linux/omnibook.h>
-#endif
 
 #include <linux/delay.h>
 #include <linux/ioport.h>
 #include <linux/pci.h>
+#include <linux/kref.h>
 
-#include <asm/io.h>
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16))
 #include <asm/semaphore.h>
+#define DEFINE_MUTEX(lock)             DECLARE_MUTEX(lock)
+#define mutex_lock(lock)               down(lock)
+#define mutex_lock_interruptible(lock) down_interruptible(lock)
+#define mutex_unlock(lock)             up(lock)
+#else
+#include <linux/mutex.h>
+#endif
+
+#include <asm/io.h>
 #include "ec.h"
 
+/*
+ * ATI's IXP PCI-LPC bridge
+ */
+#define PCI_DEVICE_ID_ATI_SB400 0x4377
+
 /* 
  * PCI Config space regiser
  * Laptop with Intel ICH Chipset
@@ -57,8 +69,7 @@
 /* 
  * We protect access to the Command/Data/Index interface by a Mutex
  */
-static DECLARE_MUTEX(compal_sem);
-
+static DEFINE_MUTEX(compal_lock);
 
 /*
  * Private data of this backend
@@ -68,13 +79,15 @@ static struct pci_dev *lpc_bridge;  /* Southbridge chip ISA bridge/LPC interface
 static u32    ioport_base;             /* PIO base adress */
 static union { u16 word; u32 dword;
               } pci_reg_state;         /* Saved state of register in PCI config spave */
+static int already_failed = 0;         /* Backend init already failed at leat once */
 
 /*
  * Possible list of supported southbridges
  * Here mostly to implement a more or less clean PCI probing
  * Works only because of previous DMI probing.
+ * Shared with nbsmi backend
  */
-static const struct pci_device_id lpc_bridge_table[] = {
+const struct pci_device_id lpc_bridge_table[] = {
         { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AA_0,   PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
         { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801AB_0,   PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
         { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_0,   PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
@@ -92,7 +105,8 @@ static const struct pci_device_id lpc_bridge_table[] = {
         { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0,      PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
         { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1,      PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
         { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_31,     PCI_ANY_ID, PCI_ANY_ID, 0, 0, },
-        { 0, },                 /* End of list */
+       { PCI_VENDOR_ID_ATI,   PCI_DEVICE_ID_ATI_SB400,         PCI_ANY_ID, PCI_ANY_ID, 0, 0, },        
+       { 0, },                 /* End of list */
 };
 
 
@@ -103,10 +117,9 @@ static const struct pci_device_id lpc_bridge_table[] = {
  * Write a 2-bytes wide command to the COMMAND ports
  * Read the result in the DATA port
  */
-static unsigned char lowlevel_read(unsigned int command)
+static unsigned char lowlevel_read(u16 command)
 {
        unsigned char data;
-
        outb((command & 0xff00) >> 8 ,ioport_base + PIO_PORT_COMMAND1);
        outb(command & 0x00ff ,ioport_base + PIO_PORT_COMMAND2);
        data = inb(ioport_base + PIO_PORT_DATA);
@@ -118,7 +131,7 @@ static unsigned char lowlevel_read(unsigned int command)
  * Write a 2-bytes wide command to the COMMAND ports
  * Write the result in the DATA port
  */
-static void lowlevel_write(unsigned int command, unsigned int data)
+static void lowlevel_write(u16 command, u8 data)
 {
        outb((command & 0xff00) >> 8 ,ioport_base + PIO_PORT_COMMAND1);
        outb(command & 0x00ff,ioport_base + PIO_PORT_COMMAND2);
@@ -258,15 +271,12 @@ static void clear_cdimode_pci(void)
        }
 }
 
-
-
-
 /*
  * Try to init the backend
  * This function can be called blindly as it use a kref
  * to check if the init sequence was already done.
  */
-int omnibook_cdimode_init(void)
+static int omnibook_cdimode_init(const struct omnibook_operation *io_op)
 {
        int retval = 0;
        int i;
@@ -275,9 +285,14 @@ int omnibook_cdimode_init(void)
        if(!(omnibook_ectype & TSM30X))
                return -ENODEV;
 
+       if(already_failed) {
+               dprintk("CDI backend init already failed, skipping.\n");
+               return -ENODEV;
+       }
+
        if(!refcount) {
                /* Fist use of the backend */
-               down(&compal_sem);      
+               mutex_lock(&compal_lock);
                dprintk("Try to init cdimode\n");       
                refcount = kmalloc(sizeof(struct kref),GFP_KERNEL);
                if(!refcount) {
@@ -313,7 +328,7 @@ int omnibook_cdimode_init(void)
                        BUG();
                }
                
-               if(!request_region(ioport_base ,4 ,"omnibook")) {
+               if(!request_region(ioport_base ,4 ,OMNIBOOK_MODULE_NAME)) {
                        printk(O_ERR "Request I/O region error\n");
                        retval = -ENODEV;
                        goto error2;
@@ -345,20 +360,26 @@ error2:
        lpc_bridge = NULL;
 error1:
        kfree(refcount);
+       refcount = NULL;
+       already_failed = 1;
 out:
-       up(&compal_sem);
+       mutex_unlock(&compal_lock);
        return retval;
 }
 
-void cdimode_free(struct kref *ref)
+static void cdimode_free(struct kref *ref)
 {
+       mutex_lock(&compal_lock);
        dprintk("Cdimode not used anymore: disposing\n");
        pci_dev_put(lpc_bridge);
        release_region(ioport_base,4);
        kfree(refcount);
+       lpc_bridge = NULL;
+       refcount = NULL;
+       mutex_unlock(&compal_lock);
 }
 
-void omnibook_cdimode_exit(void)
+static void omnibook_cdimode_exit(const struct omnibook_operation *io_op)
 {
 /* ectypes other than TSM30X have no business with this backend */
        BUG_ON(!(omnibook_ectype & TSM30X));
@@ -370,31 +391,32 @@ void omnibook_cdimode_exit(void)
  * Read EC index and write result to value 
  * 'EC index' here is unrelated to an index in the EC registers
  */
-int omnibook_cdimode_read(unsigned int index, u8 *value)
+static int omnibook_cdimode_read(const struct omnibook_operation *io_op, u8 *value)
 {
        int retval = 0;
        
-       BUG_ON(!(omnibook_ectype & TSM30X));
-       
        if(!lpc_bridge)
                return -ENODEV;
        
-       if(down_interruptible(&compal_sem))
+       if(mutex_lock_interruptible(&compal_lock))
                return -ERESTARTSYS;
        
        retval = enable_cdimode();
        if(retval)
                goto out;
-       retval = send_ec_cmd(0xfbfd,index);
+       retval = send_ec_cmd(0xfbfd,(unsigned int) io_op->read_addr);
        if(retval)
                goto error;
        retval = read_ec_cmd(0xfbfe,value);
        
+       if(io_op->read_mask)
+               *value &= io_op->read_mask;
+       
 error:
        clear_cdimode();
 out:
        clear_cdimode_pci();
-       up(&compal_sem);
+       mutex_unlock(&compal_lock);
        return retval;
 }
 
@@ -402,35 +424,64 @@ out:
  * Write value 
  * 'EC index' here is unrelated to an index in the EC registers
  */
-int omnibook_cdimode_write(unsigned int index, u8 value)
+static int omnibook_cdimode_write(const struct omnibook_operation *io_op, u8 value)
 {
        int retval = 0;
        
-       BUG_ON(!(omnibook_ectype & TSM30X));
-       
        if(!lpc_bridge)
                return -ENODEV;
        
-       if(down_interruptible(&compal_sem))
+       if(mutex_lock_interruptible(&compal_lock))
                return -ERESTARTSYS;
                
        retval = enable_cdimode();
        if(retval)
                goto out;
-       retval = send_ec_cmd(0xfbfd,index);
+       retval = send_ec_cmd(0xfbfd,(unsigned int) io_op->write_addr);
        if(retval)
                goto error;
        retval = send_ec_cmd(0xfbfe,value);
-       
 error:
        clear_cdimode();
 out:
        clear_cdimode_pci();
-       up(&compal_sem);
+       mutex_unlock(&compal_lock);
        return retval;
 
 }
 
+/*
+ * Fn+foo and multimedia hotkeys handling
+ */
+static int omnibook_cdimode_hotkeys(const struct omnibook_operation *io_op, unsigned int state)
+{
+       int retval;     
+       struct omnibook_operation hotkeys_op;
+       
+       /* Fn+foo handling */
+       hotkeys_op.backend = CDI;
+       hotkeys_op.write_addr = TSM70_FN_INDEX;
+       hotkeys_op.on_mask = TSM70_FN_ENABLE;
+       hotkeys_op.off_mask = TSM70_FN_DISABLE;
+       retval = omnibook_toggle(&hotkeys_op, !!(state & HKEY_FN) );
+       if(retval < 0)
+               return retval;
+       
+       /* Multimedia keys handling */
+       if(state & HKEY_MULTIMEDIA) {
+               hotkeys_op.write_addr = TSM70_HOTKEYS_INDEX;
+               retval = omnibook_cdimode_write(&hotkeys_op, TSM70_HOTKEYS_ENABLE);
+       } else {
+               /* FIXME: quirk use kbc backend */
+               retval = kbc_backend.byte_write(NULL,OMNIBOOK_KBC_CMD_ONETOUCH_DISABLE);
+       }
+
+       if(retval < 0)
+               return retval;
+       else
+               return HKEY_MULTIMEDIA|HKEY_FN;
+}      
+
 /* Scan index space, this hard locks my machine */
 #if 0
 static int compal_scan(char *buffer)
@@ -453,4 +504,13 @@ static int compal_scan(char *buffer)
 }
 #endif
 
+struct omnibook_backend compal_backend = {
+       .name = "compal",
+       .init = omnibook_cdimode_init,
+       .exit = omnibook_cdimode_exit,
+       .byte_read = omnibook_cdimode_read,
+       .byte_write = omnibook_cdimode_write,
+       .hotkeys_set = omnibook_cdimode_hotkeys,
+};
+
 /* End of file */
index fdb18050f7bcdd28353f612eb36043abab735503..29ba6282b3be0bb7f10b5661726c0ebb52265a39 100644 (file)
--- a/compat.h
+++ b/compat.h
@@ -76,4 +76,7 @@ void inline *kzalloc(size_t size, int flags)
 }
 #endif
 
+
+
+
 /* End of file */
index 66023d33e9582141e21ffdc06a4d2ca3d595287b..279bcdd4d11d182949f58d374cbb7e93cbe647d0 100644 (file)
@@ -14,7 +14,7 @@ Description: Source for the omnibook driver
  Pavilions, Toshiba Satellites and some other laptops manufactured by
  Compal Electronics, Inc as ODM.
  .
- This module is only compatible with Linux kernels >= 2.6.8
+ This module is only compatible with Linux kernels >= 2.6.9
  .
  Kernel source is required to compile this module.
  .
index 99281c78696da65c39a97477d290b3c04cc09d7c..8f3b50b92bb7e2ff6c4c31c0862b6d8f8980266e 100644 (file)
--- a/display.c
+++ b/display.c
@@ -1,5 +1,5 @@
 /*
- * display.c -- external display related functions
+ * display.c -- External display (LCD,VGA,TV-OUT) feature
  * 
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
  * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
  */
 
-#ifdef OMNIBOOK_STANDALONE
 #include "omnibook.h"
-#else
-#include <linux/omnibook.h>
-#endif
-
 #include "ec.h"
 
-static const struct omnibook_io_operation display_io_table[] = {
-       { XE3GF|TSP10|TSM30X|TSM40,         EC, XE3GF_STA1, 0, XE3GF_SHDD_MASK},
-       { XE3GC,                            EC, XE3GC_STA1, 0, XE3GC_CRTI_MASK},
-       { OB500|OB510|OB6000|OB6100|XE4500, EC, OB500_STA1, 0, OB500_CRTS_MASK},
-       { OB4150,                           EC, OB4150_STA2, 0, OB4150_CRST_MASK},
-       { 0,}
+static const char display_name[][16] = {
+       "Internal LCD",
+       "External VGA",
+       "External TV-OUT",
+       "External DVI",
 };
 
-static struct omnibook_io_operation *display_io;
-
-static int omnibook_display_read(char *buffer)
+static int omnibook_display_read(char *buffer,struct omnibook_operation *io_op)
 {
        int len = 0;
        int retval;
-       u8 sta;
-       
-       if ((retval = omnibook_io_read(display_io, &sta)))
+       unsigned int sta, en_mask, det_mask;
+
+       retval = io_op->backend->display_get(io_op, &sta);
+       if ( retval < 0)
                return retval;
-       len +=
-           sprintf(buffer + len, "External display is %s\n",
-                   (sta) ? "present" : "not present");
+
+       for( en_mask = DISPLAY_LCD_ON ; en_mask <= DISPLAY_DVI_ON; en_mask = en_mask << 1) {
+               det_mask = en_mask << 4; /* see display masks in omnibook.h */
+               if( !( retval & en_mask ) && !( retval & det_mask ) )
+                       continue; /* not supported */
+               len += sprintf(buffer + len, "%s:", 
+                               display_name[ ffs(en_mask) - 1 ]);
+               if( retval & det_mask )
+                       len += sprintf(buffer + len, " display %s",
+                               ( sta & det_mask ) ? "present" : "absent");
+               if( retval & en_mask )
+                       len += sprintf(buffer + len, " port %s",
+                               ( sta & en_mask ) ? "enabled" : "disabled");
+               len += sprintf(buffer + len, "\n"); 
+       }
+
 
        return len;
 }
 
-static int omnibook_display_init(void)
+static int omnibook_display_write(char *buffer,struct omnibook_operation *io_op)
 {
-       display_io = omnibook_io_match(display_io_table);
-       return display_io ? 0 : -ENODEV;
-}
+       int retval;
+       unsigned int state;     
+       char *endp;
        
+       state = simple_strtoul(buffer, &endp, 16);
+       if (endp == buffer)
+               return -EINVAL;
+       else
+               retval = io_op->backend->display_set(io_op, state);
+
+       return retval;
+}
 
-static struct omnibook_feature __declared_feature display_feature = {
+static struct omnibook_feature display_driver;
+
+static int __init omnibook_display_init(struct omnibook_operation *io_op)
+{
+       /* Disable file writing if unsuported by backend */     
+       if(!io_op->backend->display_set)
+               display_driver.write = NULL;
+       return 0;
+}
+
+
+static struct omnibook_tbl display_table[] __initdata = {
+       { TSM30X,                               {ACPI, }},
+       { XE3GF|TSP10|TSM30X|TSM40,         SIMPLE_BYTE(EC,XE3GF_STA1,XE3GF_SHDD_MASK)},
+       { XE3GC,                            SIMPLE_BYTE(EC,XE3GC_STA1,XE3GC_CRTI_MASK)},
+       { OB500|OB510|OB6000|OB6100|XE4500, SIMPLE_BYTE(EC,OB500_STA1,OB500_CRTS_MASK)},
+       { OB4150,                           SIMPLE_BYTE(EC,OB4150_STA2,OB4150_CRST_MASK)},
+       { 0,}
+};
+
+static struct omnibook_feature __declared_feature display_driver = {
         .name = "display",
         .enabled = 1,
-        .read = omnibook_display_read,
         .init = omnibook_display_init,
+        .read = omnibook_display_read,
+        .write = omnibook_display_write,
         .ectypes = XE3GF|XE3GC|OB500|OB510|OB6000|OB6100|XE4500|OB4150|TSP10|TSM30X|TSM40,
+        .tbl = display_table,
 };
 
-module_param_named(display, display_feature.enabled, int, S_IRUGO);
+module_param_named(display, display_driver.enabled, int, S_IRUGO);
 MODULE_PARM_DESC(display, "Use 0 to disable, 1 to enable display status handling");
 /* End of file */
index 11140e9629c1f888de9290def37deffc85efadb6..a799ee4dc67655c11af30d65f6bbd364096d76b1 100644 (file)
@@ -13,6 +13,58 @@ Changelog file for omnibook package:
   DMI entry. This is restoring pre-20060806 behaviour.
   Invert M40 vs. M40X entry position.
 
+2.20060816 Mathieu Bérard <math_b@users.sourceforge.net>
+* Merge from the new-backend branch: Add new backend code 
+  (in compal.c) used with TSM30X class laptops:
+  Used for lcd access
+  Used for hotkeys support: now most Fn+key generate a scancode,
+  as well as the wifi kill switch.
+  Warning: tested only on TSM40X an TSM70 laptops.
+* Create omnibook_io_operation struct and omnibook_io_{read/write}
+  funtions to simplify implementation of some simple features.
+  Used with ac display dock and led features.
+* Rename onetouch feature to "hotkeys" which is a vendor neutral name.
+* The minimal required kernel version is now 2.6.9 (kref API)
+* Convert semaphore to mutex with fallback for pre 2.6.16 kernel
+* Kill CONFIG_OMNIBOOK_APMEMU and introduce OMNIBOOK_LEGACY:
+  pre-ACPI features now depends on it.
+  Default enabling of ac and battery features also
+  depends on it. It is _disabled_ by default.
+* Introduce ACPI methods execution backend: TSM70 needs it
+  for Display and Wifi/Bluetooth features
+* Expand display and hotkeys features
+* Introduce experimental NbSmi backend for TSM40. It is
+  based on technical documentation provided by Toshiba.
+  Thanks Toshiba !
+* Kill unused omnibook_mem_read/write function for mmio
+  access
+* Cleanup in blank.c fan.c temperature.c
+* Unbreak Pio backend: use request/release_region
+* Introduce bluetooth and wifi frontend features : they allow
+  adapter state querry and control (existence probing, wifi 
+  kill switch probing and adapter enabling/disabling).
+  Supported by TSM30X and TSM40
+* Introduce omnibook_backend struct as a uniform way of 
+  communication between backend and frontend, this
+  kill omnibook_io_{read/write} and friends.
+* Modify ombibook_feature struct to incorporate pointers
+  to an omnibook_table table and to a omnibook_operation
+  struct which is picked-up from the ectype matching
+  omnibook_table entry upon feature initialization
+* Add muteled resume handler
+* Add touchpad handling for TSM30X
+* Add proper display handling for TSM30X
+* Change all features struct name from foo_feature to
+  foo_driver to kept modpost section mismatch detection
+  silent. Put tbl, init and exit entries to their relevant
+  sections.
+
+2.200608017 Mathieu Bérard <math_b@users.sourceforge.net>
+* Fix bug in omnibook_io_match
+* Fix DMI handling behaviour: we stop on the FIRST matched
+  DMI entry. This is restoring pre-20060806 behaviour.
+  Invert M40 vs. M40X entry position.
+
 2.20060816 Mathieu Bérard <math_b@users.sourceforge.net>
 * Merge from the new-backend branch: Add new backend code 
   (in compal.c) used with TSM30X class laptops:
index 265ebbf6dd2934eec31ec38efeb4b20f6847bfc1..1b6b129c52ccdeed0bb186663f63726d7494e22e 100644 (file)
@@ -9,23 +9,20 @@ wants to be a framework to extend the Linux support for HP OmniBook
 and Pavilion, Toshiba Satellite, Acer Aspire and Compal ACL00 laptops
 manufactured by Compal Electronics, Inc as ODM.
 
-There is a similar project for Toshiba Satellite laptops wich supports
-some HP OmniBooks too at ftp://ftp.poupinou.org/tosh_3000/.
-
 How does it work?
 -----------------
-   Some features of HP OmniBooks can be controlled via the keyboard control
+   Some features of sup pored laptops can be controlled via the keyboard control
    and data registers. Commands and parameters were discovered by Pavel
    Mihaylov.
 
    Some other features available via /proc/omnibook/* provided by the
-   Embedded Controller or other I/O registers of your laptop. Informations
-   comes from DSDT ACPI table of HP OmniBook XE3 GF dissassembled by Ducrot
+   Embedded Controller or other I/O registers of your laptop. Information
+   comes from DSDT ACPI table of HP OmniBook XE3 GF disassembled by Ducrot
    Bruno and others or discovered by me.
 
    Note: You do not have to enable APM or ACPI to use this driver.
 
-   All supported models seems to have same keyboard and embedded controller:
+   Most supported models seems to have same keyboard and embedded controller:
    National Semiconductor PC87570 Keyboard and ACPI Embedded Controller or
    compatible, but with different types of firmware.
    See http://www.national.com/pf/PC/PC87570.html for more info.
@@ -85,18 +82,19 @@ How does it work?
        Toshiba Satellite M35X
        Toshiba Satellite M70
    13. Toshiba Satellite M40
+   14. Toshiba Satellite A105
    
    If your model is not listed above you may try to load the module. If it
-   have same DMI identification strigs as a supported machine it may works
+   have same DMI identification strings as a supported machine it may works
    out of the box. Please report it.
    Only the /proc/omnibook/dmi and /proc/omnibook/version are working when
    you load the module on an unsupported machine.
    In this case you may load the module with ectype parameter to force using
    a certain EC firmware type or see how became you machine supported at the
-   end of this documet.
+   end of this document.
 
-What is working?
-----------------
+What are the provided features?
+-------------------------------
  1. Enabling hotkey buttons. See README-Hotkeys for details.
     You may enable or disable it via /proc/omnibook/hotkeys.
     There is a power management handler for reenabling the buttons at resume
@@ -126,39 +124,74 @@ What is working?
 
  8. Display status monitoring /proc/omnibook/display.
 
- 9. LCD brightness setting and monitoring.
+ 9. LCD brightness setting and monitoring via /proc/omnibook/lcd.
+
+10. Docking station/port replicator support via /proc/omnibook/dock.
 
-10. Docking station/port replicator support.
+11. Wifi and Bluetooth adapters monitoring and control via
+    /proc/omnibook/bluetooth and /proc/omnibook/wifi
 
 How to use?
 -----------
  1. The hotkeys are enabled by default by this module.
     To disable it use the command:
 
-       echo 0 > /proc/omnibook/hotkeys
+       $ echo off > /proc/omnibook/hotkeys
 
     The command
 
-       echo 1 > /proc/omnibook/hotkeys
+       $ echo on > /proc/omnibook/hotkeys
 
     enables hotkeys buttons.
+    
+    Reading to that same file allow you to read the state of the hotkeys:
+
+       $ cat /proc/omnibook/hotkeys
+       Multimedia hotkeys are enabled.
+       Fn hotkeys are enabled.
+
+    The items displayed depends on your laptop model.
+    Some Toshiba models support advanced hotkeys control. Alternatively to and
+    on/off command you can fine-tune the behavior of your keyboard's hotkeys
+    writing an hexadecimal number to the hotkeys files.
+    To enable a specific hotkeys feature, add its code to this hexadecimal
+    number. The feature/code table follow:
+
+       Onetouch buttons:               0x1
+       Multimedia hotkeys are:         0x2
+       Fn hotkeys are:                 0x4
+       Stick key is:                   0x8
+       Press Fn twice to lock:         0x10
+       Dock events:                    0x20
+       Fn + F5 hotkey:                 0x40
+
+    That is to enable multimedia hotkeys only do: 
+       $cat 0x2 > /proc/omnibook/hotkeys
+    To enable Fn hotkeys and Dock events only do:
+       $cat 0x24 > /proc/omnibook/hotkeys      (as 0x24 = 0x4 + 0x20)
+
+    Finally 'off' is equivalent to 0x0, and 'on' to 0x67 that is
+    Onetouch, Multimedia, Fn, Dock and Fn+F5.
+
+    Unsupported features won't be displayed in /proc/omnibook/hotkeys and writing
+    their corresponding codes won't have any effect.
 
  2. Console (LCD display) blanking is enabled by this module on machines that
     support it. It only enabled if another blanking solution
     (e.g. CONFIG_APM_DISPLAY_BLANK) is not used.
     To disable this behavior use command:
 
-       echo 0 > /proc/omnibook/blank
+       echo 0 > /proc/omnibook/blank
 
     To enable this behavior use command:
 
-       echo 1 > /proc/omnibook/blank
+       echo 1 > /proc/omnibook/blank
 
  3. To see the battery status use
 
-       cat /proc/omnibook/battery
+       cat /proc/omnibook/battery
 
-    command. It produce similar output to that you can see below.
+    It produce similar output to that you can see below.
 
        Battery:                      0
        Type:                    Li-Ion
@@ -175,10 +208,9 @@ How to use?
     apm is enabled, but via this file you can monitor your battery
     independently from apm code.
 
-    Current ACPI driver reports some bad value about battery at least on my
-    machine:
+    ACPI driver might reports some bad value about battery:
 
-       $cat /proc/acpi/battery/BAT1/info
+       $ cat /proc/acpi/battery/BAT1/info
        present:                 yes
        design capacity:         5400 mAh
        last full capacity:      5400 mAh
@@ -194,10 +226,11 @@ How to use?
        OEM info:                HP
 
        This is because the methods used for batteries in the DSDT do
-       not give correct informations. If you want to fix it you may
+       not give correct information. If you want to fix it you may
        have to change methods in the DSDT.
        See http://www.intel.com/technology/iapc/acpi/bios_override.htm
        for details.
+       ACPI support for battery should be good on recent laptops.
 
  4. The /proc/omnibook/fan file provides information about fan status:
 
@@ -211,11 +244,11 @@ How to use?
 
     On certain machines you may turn on the fan by
 
-       echo 1 > /proc/omnibook/fan
+       echo 1 > /proc/omnibook/fan
 
     command and turn off by issuing
 
-       echo 0 > /proc/omnibook/fan
+       echo 0 > /proc/omnibook/fan
 
     command.
 
@@ -255,11 +288,11 @@ How to use?
 
     To set the fan policy write the proper values into the
     /proc/omnibook/fan_policy file. Each value must be greater than or
-    equal to the prvious one. You do not have to write all values.
+    equal to the previous one. You do not have to write all values.
     For example you may set fan off temperature to 60 C, fan on temperature
     to 70 C and fan level 2 temperature to 80 C by
 
-       echo 60 70 80 > /proc/omnibook/fan_policy
+       echo 60 70 80 > /proc/omnibook/fan_policy
 
     command.
     A zero value (echo 0 > /proc/omnibook/fan_policy) sets the default
@@ -277,22 +310,22 @@ How to use?
  5. The touchpad is enabled by default by the BIOS.
     To disable it use the command:
 
-       echo 0 > /proc/omnibook/touchpad
+       echo 0 > /proc/omnibook/touchpad
 
     The command
 
-       echo 1 > /proc/omnibook/touchpad
+       echo 1 > /proc/omnibook/touchpad
 
     enables the touchpad.
 
  6. The /proc/apm emulation is disabled by default on all machines. You have
-    to enable it explicit way by module parameter apmemu. To enable it use:
+    to enable it explicit using the module parameter apmemu. To enable it use:
 
-       insmod omnibook apmemu=1
+       insmod omnibook apmemu=1
 
     You can enable it by /etc/modules.conf with the following entry:
 
-       options omnibook apmemu=1
+       options omnibook apmemu=1
 
     If your kernel have APM support, but the /proc/apm reports buggy values,
     you may boot your kernel without apm support, and try to load omnibook
@@ -303,7 +336,7 @@ How to use?
 
  7. To see the AC adapter status use
 
-       cat /proc/omnibook/ac
+       cat /proc/omnibook/ac
 
     command. It produce similar output to that you can see below.
 
@@ -317,46 +350,59 @@ How to use?
 
  8. To see the display status use
 
-       cat /proc/omnibook/display
+       cat /proc/omnibook/display
 
-    command. It produce similar output to that you can see below.
+    The displayed output depends on your laptop model, as an example:
 
        $ cat /proc/omnibook/display
-       External display is not present
+       Internal LCD: display present port enabled
+       External VGA: display absent port disabled
+       External TV-OUT: display absent port disabled
 
-    Or if you have external monitor installed:
+    If you are adventuresome, and if your laptop model support it,
+    you can try to enable or disable a specific display port.
+    To do that, write an hexadecimal number to the display file, adding the
+    code of display ports you want to enable, the others will be disabled:
 
-       $ cat /proc/omnibook/display
-       External display is present
+       Internal LCD panel:     0x1
+       External VGA port:      0x2
+       External TV port:       0x4
+
+    For example to enable the LCD panel and the TV-OUT port only, you have to
+    write 0x1 + 0x4 = 0x5:
+
+       $ echo 0x5 > /proc/omnibook/display
+
+    It may or may not work, or even crash your X server. Proceed with caution.
 
  9. To see the LCD brightness use
 
-       cat /proc/omnibook/lcd
+       cat /proc/omnibook/lcd
 
-    command. It produce similar output to that you can see below.
+    It produce similar output to that you can see below.
 
        $ cat /proc/omnibook/lcd
-       LCD brightness: 7
+       LCD brightness:  5 (max value: 7)
 
-    To set it use similar command to that you can see below.
+    To set it use similar command to that you can see below:
 
-       echo 10 > /proc/omnibook/lcd
+       $ echo 1 > /proc/omnibook/lcd
 
-    The value of LCD brightness must be betwenn 0 and 10.
+    The value of LCD brightness must be between 0 and the printed max boundary,
+    here you can see it's 7.
 
-    Note: Setting the LCD brightness on HP OmniBook XE3 GF via
+    Bug:  Setting the LCD brightness on HP OmniBook XE3 GF via
           /proc/omnibook/lcd is working if you press one of the
           brightness control keys once after writing the value
-          into /proc/omnibook/lcd. I'll try to fix it, but I have
-          no idea about reason yet.
+          into /proc/omnibook/lcd.
 
     To turn off the LCD backlight use
 
-       echo off > /proc/omnibook/lcd
+       echo off > /proc/omnibook/lcd
 
     To turn it back on use
 
-       echo on > /proc/omnibook/lcd
+       echo on > /proc/omnibook/lcd
 
     This is useful if you have an X server, such as the ATI Radeon,
     that does not know how to turn off the LCD backlight.  Use a
@@ -378,7 +424,7 @@ How to use?
 10. To check that your laptop is docked in a docking station or port
     replicator use
 
-       cat /proc/omnibook/dock
+       cat /proc/omnibook/dock
 
     command. It produce similar output to that you can see below.
 
@@ -394,16 +440,37 @@ How to use?
     You have to enable it explicit way by module parameter dock. To enable
     it use:
 
-        insmod omnibook dock=1
+        insmod omnibook dock=1
 
     You can enable it by /etc/modules.conf with the following entry:
 
        options omnibook dock=1
 
+11. To read wifi and bluetooth adapters status reading the 
+    /proc/omnibook/wifi and /proc/omnibook/bluetooth files respectively:
+
+       $ cat /proc/omnibook/wifi
+       Wifi adapter is present and enabled.
+       Wifi Kill switch is on.
+
+       $ cat /proc/omnibook/bluetooth
+       Bluetooth adapter is absent.
+    
+    You can enable or disable a dectected adapters writing 1 or 0 respectibely
+    to the corresponding file: 
+
+       $ echo 0 >  /proc/omnibook/wifi
+       [ Wifi led shut down, connectivity is lost ]
+
+       $ cat /proc/omnibook/wifi
+       Wifi adapter is present and disabled.
+       Wifi Kill switch is on.
+
+
 You may enable features above via the proper module parameters. See the 
 output of
 
-       modinfo omnibook
+       modinfo omnibook
 
 command.
 
@@ -413,12 +480,12 @@ networked) users or you are the only user of the laptop you may load the
 module with the parameter user to enable non-root accounts to set omnibook
 paremeters as follows:
 
-       insmod omnibook user=1
+       insmod omnibook user=1
 
 You can enable users to set parameters by /etc/modules.conf with the
 following entry:
 
-       options omnibook user=1
+       options omnibook user=1
 
 Graphical frontends
 -------------------
@@ -441,12 +508,7 @@ How can your laptop be supported?
 If your model is unsupported and you want it to be supported I need four
 things:
 
-1. Test your machine with Pavel's omke.pl and report the result. You
-   should include that a feature works or not and details if any
-   (eg. OneTouch keycodes in hex as appears in syslog after enabling
-    them by omke.pl etc.).
-
-2. Force the module to load with an embedded controller firmware type
+1. Force the module to load with an embedded controller firmware type
    detailed above. For example if you want to test that your machine
    is an XE3GF style model, use the following command:
 
@@ -457,10 +519,10 @@ things:
    Warning!!! Forced load on an unsupported machine may cause
    unpredictable result. You have been warned...
 
-3. Send me DMI strings of your machine (/proc/omnibook/dmi after
+2. Send me DMI strings of your machine (/proc/omnibook/dmi after
    loading omnibook module on any machine).
 
-4. If possible send me the DSDT of your machine. If your kernel is 
+3. If possible send me the DSDT of your machine. If your kernel is 
    configured for ACPI you can found it at /proc/acpi/dsdt. Use the
    following command to get the DSDT AML file.
 
@@ -476,14 +538,14 @@ things:
 
    Please send me the AML file. Note: it is binary file.
 
-5. Developers or advanced users who want to help the developement of this driver
+4. Developers or advanced users who want to help the development of this driver
    can enable an experimental features of the omnibook kernel module:
    /proc/omnibook/dump, which dump the content of the embedded 
    controller memory.
 
    It have to be manually enabled using the dump=1 kernel module parameters 
-   and can be used in conjunction with a carefull examination 
-   of a decompiled DSDT to spot where your laptop stores interesting informations
+   and can be used in conjunction with a careful examination 
+   of a decompiled DSDT to spot where your laptop stores interesting information
    such as FAN speed or CPU temperature.
 
 This code was written without any documentation from HP or Compal so it
@@ -512,11 +574,50 @@ Compal Electronics, Inc. does not response to information requests at all.
 Meanwhile (in 2002) Compaq and HP merged and as I know Compaq will the
 supplier of the new laptop models in the merged company.
 
-Some new models of Toshiba Satellite notebooks (M70 and M40) seems to
+Some new models of Toshiba Satellite notebooks (M70 and M40X) seems to
 be made by Compal.
 
+The NbSmi backend code which implement support for some Toshiba Satellite
+was made using technical documentation provided by Toshiba.
+This code is contained in the nbsmi.c file
+Thanks Toshiba for this Linux-friendly behavior.
+This technical documentation was provided with the following disclaimer:
+
+----- Disclaimer Verbatim copy Begin -----
+ PLEASE READ THIS INTELLECTUAL PROPERTY DISCLAIMER CAREFULLY BEFORE 
+USING THE TOSHIBA TECHNICAL INFORMATION AS ATTACHED.
+    BY USING THE TOSHIBA TECHNICAL INFORMATION, YOU ARE AGREEING TO BE 
+BOUND BY ALL OF THE TERMS OF THIS INTELLECTUAL PROPERTY DISCLAIMER.
+    IF YOU DO NOT AGREE TO THE TERMS OF THIS INTELLECTUAL PROPERTY 
+DISCLAIMER, PROMPTLY RETURN THE ATTACHED TOSHIBA TECHNICAL INFORMATION.
+
+                 Copyright (C) 1999, Toshiba Corp. All rights reserved.
+
+
+                    INTELLECTUAL PROPERTY DISCLAIMER
+
+    NO LICENSE, EXPRESS OR IMPLIED, BY ESTOPPEL OR OTHERWISE, OF ANY 
+INTELLECTUAL PROPERTY RIGHTS OF TOSHIBA IS GRANTED OR INTENDED HEREBY.  
+NOTWITHSTANDING FORGOING, TOSHIBA WILL NOT MAKE ANY CLAIM BASED ON THE 
+INTELLECTUAL PROPERTY RIGHTS AGAINST SOFTWARE FOR LINUX DEVELOPED USING 
+TOSHIBA TECHNICAL INFORMATION, PROVIDED THAT SUCH SOFTWARE IS USED FOR 
+OR DISTRIBUTED WITH LINUX FOR EXECUTION ON TOSHIABA COMPUTER PRODUCTS.
+
+    TOSHIBA DISCLAIMS ALL LIABILITY, INCLUDING LIABILITY FOR INFRINGEMENT 
+OF PROPRIETARY RIGHTS RELATING TO IMPLEMENTATION OF TOSHIBA TECHNICAL 
+INFORMATION.  TOSHIBA DOES NOT WARRANT OR REPRESENT THAT SUCH 
+IMPLEMENTATION(S) WILL NOT INFRINGE SUCH RIGHTS.
+
+    TOSHIBA TECHNICAL INFORMATION IS PROVIDED "AS IS" WITH NO WARRNTIES 
+WHATSOEVER INCLUDING ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR ANY 
+PARTICULAR PURPOSE.
+---- Disclaimer End ----
+
 For more information you can see the OmniBook mailing list at
 http://zurich.ai.mit.edu/mailman/listinfo/omnibook
 
+or the Toshiba linux mailing list at 
+http://linux.toshiba-dme.co.jp/linux/
+
 You can find actual version of this code at
-http://sourceforge.net/projects/omke
+http://sourceforge.net/projects/omnibook
index 71e3450f2e22e124edd7047d66a175d3a4fb7688..cc9823a97cd72aa7c2543022f45f4af39c44755c 100644 (file)
@@ -2,9 +2,11 @@ This package intended to provide Linux kernel support for HP OmniBook,
 HP Pavilion, Toshiba Satellite and some Acer Aspire and Compal laptops.
 The state of this code is experimental.
 
-This code was written without any documentation about HP OmniBooks and
-other machines so it is provided as is without any warranty. Use it on
-your own risk.
+This code was written using technical documentation provided by Toshiba about
+some Toshiba Satellites (M40 ...) and Toshiba Tecra. 
+This code was written without any documentation about other laptop models.
+
+It is provided as is without any warranty. Use it on your own risk.
 
 The code in the files in the omnibook distribution is licensed for use
 under the terms of GNU General Public License, included as the file
@@ -12,5 +14,4 @@ named COPYING.
 
 For installation instructions please read the file named INSTALL.
 For usage informations and/or bug reports you may read file named README.
-For additional informations for using it on kernel 2.6 see README-2.6.
 For current bugs and problems see file named BUGS.
index 6759b9fd61b0cbabef39d04486e9e9f8457c404d..b9fefb8f1e019a16f0fb6acb00b7274b2b332720 100644 (file)
--- a/doc/TODO
+++ b/doc/TODO
@@ -1,22 +1,21 @@
 TODO
 ====
 
+Current issues:
+
 * See if/how key polling can be ported to 2.6
 * LED API support
-* Clarify the TSM40 situation
 * Create a clean access method to the i8042 kbd controller (this will require
   a kernel patch)
-* We use I/O ports without a request_region ( ec.c blank.c fan.c)
-* To be cleaned: blank fan
-* To much global variables sometimes
+* To be cleaned: battery dump fan_policy
 
-Items imported from previous version:
+Old items imported from previous version:
 
 * Fix LCD brighness handling on XE3GF style machines
 * Fully support OB5xx, OB6xxx and XE4500 style machines
 * Battery support for OB5xx, OB6xxx and XE4500 style machines
 
-Will probably always remain here:
+Will probably remain here forever:
 
 * Adding more features of embedded controller
 * Support more machines
diff --git a/dock.c b/dock.c
index 1301e54cee19b7485421e60c7b3ab445f83dc003..d25482fb18d538ac1748c692d3135a4301d70181 100644 (file)
--- a/dock.c
+++ b/dock.c
  * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
  */
 
-#ifdef OMNIBOOK_STANDALONE
 #include "omnibook.h"
-#else
-#include <linux/omnibook.h>
-#endif
 
 #include "ec.h"
 
-static const struct omnibook_io_operation dock_io_table[] = {
-       { XE3GF,                     EC, XE3GF_CSPR, 0, XE3GF_CSPR_MASK},
-       { OB500|OB510|OB6000|OB6100, EC, OB500_STA1, 0, OB500_DCKS_MASK},
-       { OB4150,                    EC, OB4150_DCID, 0, 0},    
-       { 0,}
-};
-
-static struct omnibook_io_operation *dock_io;
-
-static int omnibook_dock_read(char *buffer)
+static int omnibook_dock_read(char *buffer,struct omnibook_operation *io_op)
 {
        int len = 0;
        u8 dock;
        int retval;
        
-       if ((retval = omnibook_io_read(dock_io, &dock)))
+       if ((retval = io_op->backend->byte_read(io_op,&dock)))
                return retval;
        
        len +=
@@ -48,20 +35,22 @@ static int omnibook_dock_read(char *buffer)
        return len;
 }
 
-static int omnibook_dock_init(void)
-{
-       dock_io = omnibook_io_match(dock_io_table);
-       return dock_io ? 0 : -ENODEV;
-}
+static struct omnibook_tbl dock_table[] __initdata = {
+       { XE3GF,                     SIMPLE_BYTE(EC,XE3GF_CSPR,XE3GF_CSPR_MASK)},
+       { OB500|OB510|OB6000|OB6100, SIMPLE_BYTE(EC,OB500_STA1,OB500_DCKS_MASK)},
+       { OB4150,                    SIMPLE_BYTE(EC,OB4150_DCID,0)},    
+       { 0,}
+};
+
 
-static struct omnibook_feature __declared_feature dock_feature = {
+static struct omnibook_feature __declared_feature dock_driver = {
         .name = "dock",
         .enabled = 0,
         .read = omnibook_dock_read,
-        .init = omnibook_dock_init,
         .ectypes = XE3GF|OB500|OB510|OB6000|OB6100|OB4150,
+        .tbl = dock_table,
 };
 
-module_param_named(dock, dock_feature.enabled, int, S_IRUGO);
+module_param_named(dock, dock_driver.enabled, int, S_IRUGO);
 MODULE_PARM_DESC(dock, "Use 0 to disable, 1 to enable docking station support");
 /* End of file */
diff --git a/dump.c b/dump.c
index 142cb44207d78177707b9a818e6f272ff579e142..2c0e47e5247a5821557ebda94798f3ee8a65f62d 100644 (file)
--- a/dump.c
+++ b/dump.c
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#ifdef OMNIBOOK_STANDALONE
 #include "omnibook.h"
-#else
-#include <linux/omnibook.h>
-#endif
-
 #include "ec.h"
 
 static u8 ecdump_regs[256];
 
-static int ecdump_read(char *buffer)
+static int ecdump_read(char *buffer,struct omnibook_operation *io_op)
 {
        int len = 0;
        int i, j;
@@ -41,7 +36,7 @@ static int ecdump_read(char *buffer)
        for (i = 0; i < 255; i += 16) {
                len += sprintf(buffer + len, "EC 0x%02x:", i);
                for (j = 0; j < 16; j++) {
-                       if (omnibook_ec_read(i + j, &v))
+                       if (legacy_ec_read(i + j , &v))
                                break;
                        if (v != ecdump_regs[i + j])
                                len += sprintf(buffer + len, " *%02x", v);
@@ -64,7 +59,7 @@ static int ecdump_read(char *buffer)
        return len;
 }
 
-static int ecdump_write(char *buffer)
+static int ecdump_write(char *buffer,struct omnibook_operation *io_op)
 {
 
        int i, v;
@@ -76,7 +71,7 @@ static int ecdump_write(char *buffer)
        } else
                return -EINVAL;
        if (i >= 0 && i < 256 && v >= 0 && v < 256) {
-               if (omnibook_ec_write(i, v))
+               if (legacy_ec_write(i, v))
                        return -EIO;
        } else
                return -EINVAL;
@@ -84,14 +79,14 @@ static int ecdump_write(char *buffer)
        return 0;
 }
 
-static struct omnibook_feature __declared_feature dump_feature = {
+static struct omnibook_feature __declared_feature dump_driver = {
         .name = "dump",
         .enabled = 0,
         .read = ecdump_read,
         .write = ecdump_write,
 };
 
-module_param_named(dump, dump_feature.enabled, int, S_IRUGO);
+module_param_named(dump, dump_driver.enabled, int, S_IRUGO);
 MODULE_PARM_DESC(dump, "Use 0 to disable, 1 to enable embedded controller register dump support");
 /* End of file */
 
diff --git a/ec.c b/ec.c
index 60cadfc82c4120021914a1496e48760ad6cdcc6b..74023987c2dcaf7db4120d00ce1f639d8fd007a7 100644 (file)
--- a/ec.c
+++ b/ec.c
  * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
  */
 
+#include "omnibook.h"
+
 #include <linux/types.h>
 #include <linux/delay.h>
 #include <linux/sched.h>
-#include <linux/config.h>
 #include <linux/spinlock.h>
-#include <linux/acpi.h>
-#include <linux/version.h>
+#include <linux/ioport.h>
 
 #include <asm/io.h>
 #include "ec.h"
 #define DEFINE_SPINLOCK(s)              spinlock_t s = SPIN_LOCK_UNLOCKED
 #endif
 
-extern int omnibook_ectype;
 
 /*
- *     Interrupt control
+ * Interrupt control
  */
 
-
-
 static DEFINE_SPINLOCK(omnibook_ec_lock);
 
 
@@ -107,16 +104,20 @@ static int omnibook_ec_wait(u8 event)
  * disabled.
  */
 
-int omnibook_ec_read(u8 addr, u8 *data)
+static int omnibook_ec_read(const struct omnibook_operation *io_op, u8 *data)
 {
-       unsigned long flags;
        int retval;
-
+       
 #ifdef CONFIG_ACPI_EC
-       if (likely(!acpi_disabled))
-               return ec_read(addr, data);
+       if (likely(!acpi_disabled)) {
+               retval = ec_read((u8) io_op->read_addr, data);
+               if(io_op->read_mask)
+                       *data &= io_op->read_mask;
+               dprintk("ACPI EC read at %lx success %i.\n",io_op->read_addr,retval);
+               return retval;
+       }
 #endif
-       spin_lock_irqsave(&omnibook_ec_lock, flags);
+       spin_lock_irq(&omnibook_ec_lock);
        retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_IBF);
        if (retval)
                goto end;
@@ -124,35 +125,41 @@ int omnibook_ec_read(u8 addr, u8 *data)
        retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_IBF);
        if (retval)
                goto end;
-       outb(addr, OMNIBOOK_EC_DATA);
+       outb((u8) io_op->read_addr, OMNIBOOK_EC_DATA);
        retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_OBF);
        if (retval)
                goto end;
        *data = inb(OMNIBOOK_EC_DATA);
+       if(io_op->read_mask)
+               *data &= io_op->read_mask;
 end:
-       spin_unlock_irqrestore(&omnibook_ec_lock, flags);
+       spin_unlock_irq(&omnibook_ec_lock);
+       dprintk("Custom EC read at %lx success %i.\n",io_op->read_addr,retval);
        return retval;
 }
-
+       
 /*
- * Write to the embedded controller
- * Decide at run-time if we can use the much cleaner ACPI EC driver instead of
- * this implementation, this is the case if ACPI has been compiled and is not
+ * Write to the embedded controller:
+ * If OMNIBOOK_LEGACY is set, decide at run-time if we can use the much cleaner 
+ * ACPI EC driver instead of this legacy implementation. 
+ * This is the case if ACPI has been compiled and is not
  * disabled.
+ * If OMNIBOOK_LEGACY is unset, we drop our custoim implementation
  */
 
-int omnibook_ec_write(u8 addr, u8 data)
+static int omnibook_ec_write(const struct omnibook_operation *io_op, u8 data)
 {
-
-       unsigned long flags;
        int retval;
        
 #ifdef CONFIG_ACPI_EC
-       if (likely(!acpi_disabled))
-               return ec_write(addr, data);            
+       if (likely(!acpi_disabled)) {
+               retval = ec_write((u8) io_op->write_addr, data);
+               dprintk("ACPI EC write at %lx success %i.\n",io_op->write_addr,retval);
+               return retval;
+       }       
 #endif
        
-       spin_lock_irqsave(&omnibook_ec_lock, flags);
+       spin_lock_irq(&omnibook_ec_lock);
        retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_IBF);
        if (retval)
                goto end;
@@ -160,16 +167,68 @@ int omnibook_ec_write(u8 addr, u8 data)
        retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_IBF);
        if (retval)
                goto end;
-       outb(addr, OMNIBOOK_EC_DATA);
+       outb((u8) io_op->write_addr, OMNIBOOK_EC_DATA);
        retval = omnibook_ec_wait(OMNIBOOK_EC_STAT_IBF);
        if (retval)
                goto end;
        outb(data, OMNIBOOK_EC_DATA);
 end:
-       spin_unlock_irqrestore(&omnibook_ec_lock, flags);
+       spin_unlock_irq(&omnibook_ec_lock);
+       dprintk("Custom EC write at %lx success %i.\n",io_op->write_addr,retval);
        return retval;
 }
 
+/*
+ * legacy access function for unconverted old code who expect old omnibook_ec_read
+ */
+
+int legacy_ec_read(u8 addr, u8 *data)
+{
+       int retval;
+       struct omnibook_operation *io_op;
+
+       io_op = kzalloc(sizeof(struct omnibook_operation), GFP_KERNEL);
+       if(!io_op)
+               return -ENOMEM;
+       io_op->read_addr = addr;
+       retval = omnibook_ec_read(io_op, data);
+       kfree(io_op);
+       return retval;
+}
+
+
+/*
+ * legacy access function for unconverted old code who expect old omnibook_ec_write
+ */
+
+int legacy_ec_write(u8 addr, u8 data)
+{
+       int retval;
+       struct omnibook_operation *io_op;
+
+       io_op = kzalloc(sizeof(struct omnibook_operation), GFP_KERNEL);
+       if(!io_op)
+               return -ENOMEM;
+       io_op->write_addr = addr;
+       retval = omnibook_ec_write(io_op, data);
+       kfree(io_op);
+       return retval;
+}
+
+static int omnibook_ec_display(const struct omnibook_operation *io_op, unsigned int *state)
+{
+       int retval;
+       u8 raw_state;
+
+       retval = io_op->backend->byte_read(io_op, &raw_state);
+       if(retval < 0)
+               return retval;
+
+       *state = !!(raw_state) & DISPLAY_CRT_DET;
+
+       return DISPLAY_CRT_DET;
+}      
+
 /*
  * Registers of the keyboard controller
  */
@@ -216,17 +275,16 @@ static int omnibook_kbc_wait(u8 event)
 
 static int omnibook_kbc_write_command(u8 cmd)
 {
-       unsigned long flags;
        int retval;
 
-       spin_lock_irqsave(&omnibook_ec_lock, flags);
+       spin_lock_irq(&omnibook_ec_lock);
        retval = omnibook_kbc_wait(OMNIBOOK_KBC_STAT_IBF);
        if (retval)
                goto end;
        outb(cmd, OMNIBOOK_KBC_SC);
        retval = omnibook_kbc_wait(OMNIBOOK_KBC_STAT_IBF);
-      end:
-       spin_unlock_irqrestore(&omnibook_ec_lock, flags);
+end:
+       spin_unlock_irq(&omnibook_ec_lock);
        return retval;
 }
 
@@ -236,17 +294,16 @@ static int omnibook_kbc_write_command(u8 cmd)
 
 static int omnibook_kbc_write_data(u8 data)
 {
-       unsigned long flags;
        int retval;
 
-       spin_lock_irqsave(&omnibook_ec_lock, flags);
+       spin_lock_irq(&omnibook_ec_lock);
        retval = omnibook_kbc_wait(OMNIBOOK_KBC_STAT_IBF);
        if (retval)
                goto end;;
        outb(data, OMNIBOOK_KBC_DATA);
        retval = omnibook_kbc_wait(OMNIBOOK_KBC_STAT_IBF);
-      end:
-       spin_unlock_irqrestore(&omnibook_ec_lock, flags);
+end:
+       spin_unlock_irq(&omnibook_ec_lock);
        return retval;
 }
 
@@ -254,84 +311,240 @@ static int omnibook_kbc_write_data(u8 data)
  * Send a command to keyboard controller
  */
 
-int omnibook_kbc_command(u8 cmd, u8 data)
+static int omnibook_kbc_command(const struct omnibook_operation *io_op, u8 data)
 {
        int retval;
-
-       retval = omnibook_kbc_write_command(cmd);
-       if (retval)
+       
+       if ((retval = omnibook_kbc_write_command(OMNIBOOK_KBC_CONTROL_CMD)))
                return retval;
+
        retval = omnibook_kbc_write_data(data);
        return retval;
 }
 
 /*
- * Common pattern selector:
- * Match an ectype and return pointer to corresponding io_operation.
- * Also make corresponding backend initialisation if necessary
+ * Onetouch button hotkey handler
  */
-void *omnibook_io_match(const struct omnibook_io_operation *io_op)
+static int omnibook_kbc_hotkeys(const struct omnibook_operation *io_op, unsigned int state)
 {
-       int i;
-       void *matched = NULL;
-       for (i = 0; io_op[i].ectypes ; i++) {
-               if (omnibook_ectype & io_op[i].ectypes) {
-                       if (io_op[i].type == CDI && omnibook_cdimode_init())
-                               continue;
-                       matched = (void *) &io_op[i];
-                       break;
+       int retval;
+       struct omnibook_operation hotkeys_op;
+
+       hotkeys_op.backend = KBC;
+       hotkeys_op.on_mask = OMNIBOOK_KBC_CMD_ONETOUCH_ENABLE;
+       hotkeys_op.off_mask = OMNIBOOK_KBC_CMD_ONETOUCH_DISABLE;
+
+       retval = omnibook_toggle( &hotkeys_op, !!(state & HKEY_ONETOUCH));
+       
+       if(retval < 0)
+               return retval;
+       else
+               return HKEY_ONETOUCH;
+}
+
+/*
+ * IO port backend. Only support single or dual ports operations
+ * private data structure: it's the linked list of requested ports
+ * 
+ * Race condition issue: omnibook_pio_init/exit functions are only called from
+ * omnibook_backend_match and omnibook_remove from init.c, this should happen
+ * only at module init/exit time so there is no need for a lock.
+ */
+
+struct pio_private_data_t {
+       unsigned long addr;
+       struct kref refcount;
+       struct list_head list;
+};
+
+static struct pio_private_data_t pio_private_data = {
+       .addr = 0,
+       .list = LIST_HEAD_INIT(pio_private_data.list),
+};
+
+/*
+ * Match an entry in the linked list helper function: see if we have and entry
+ * whose addr field match maddr
+ */
+static struct pio_private_data_t * 
+ omnibook_match_port(struct pio_private_data_t *data, unsigned long maddr)
+{
+       struct list_head  *p;
+       struct pio_private_data_t *cursor;
+
+       list_for_each(p , &data->list ) {
+               cursor = list_entry(p, struct pio_private_data_t, list);
+               if( cursor->addr == maddr ) {
+                       return cursor;
                }
        }
-       return matched;
+       return NULL;
 }
 
 /*
- * Simple read function for common pattern
- * Given an io_operation they read an address and apply a mask on the result
+ * See if we have to request raddr
  */
-
-int omnibook_io_read(struct omnibook_io_operation *io_op, u8 *value)
+static int omnibook_claim_port(struct pio_private_data_t *data, unsigned long raddr)
 {
-       int retval = 0;
-       
-       switch(io_op->type) {
-       case EC:
-               retval = omnibook_ec_read( io_op->read, value);
-               break;
-       case CDI:
-               retval = omnibook_cdimode_read( io_op->read, value);
-               break;
-       default:
-               BUG();
+       struct pio_private_data_t *match, *new;
+
+       match = omnibook_match_port( data, raddr);
+       if(match) {     
+               /* Already requested by us: increment kref and quit */
+               kref_get(&match->refcount);
+               return 0;
+       }       
+
+       /* there was no match: request the region and add to list */
+       if(!request_region(raddr ,1 , OMNIBOOK_MODULE_NAME)) {
+               printk(O_ERR "Request I/O port error\n");
+               return -ENODEV;
+       }
+
+       new = kmalloc(sizeof(struct pio_private_data_t), GFP_KERNEL);
+       if(!new) {
+               release_region(raddr ,1 );
+               return -ENOMEM;
        }
+
+       kref_init(&new->refcount);
+       new->addr = raddr;
+       list_add(&new->list, &data->list);
        
-       if (io_op->mask)
-               *value = *value & io_op->mask;
+       return 0;
+}
+
+/*
+ * Register read_addr and write_addr
+ */
+static int omnibook_pio_init(const struct omnibook_operation *io_op)
+{
+       int retval = 0;
+
+       if(io_op->read_addr &&
+               (retval = omnibook_claim_port(io_op->backend->data, io_op->read_addr)))
+               goto out;
+
+       if(io_op->write_addr && ( io_op->write_addr != io_op->read_addr ))
+               retval = omnibook_claim_port(io_op->backend->data, io_op->write_addr);
+
+out:
+       return retval;
+}
+
+/*
+ * REALLY release a port
+ */
+static void omnibook_free_port(struct kref *ref)
+{
+       struct pio_private_data_t *data;
        
-       return retval;          
+       data = container_of(ref, struct pio_private_data_t, refcount);
+       release_region(data->addr ,1 );
+       list_del(&data->list);
+       kfree(data);
 }
 
 /*
- * Simple write function for common pattern
- * Given an io_operation they write value at an given address
+ * Unregister read_addr and write_addr
  */
+static void omnibook_pio_exit(const struct omnibook_operation *io_op)
+{
+       struct pio_private_data_t *match;
+
+       match = omnibook_match_port(io_op->backend->data, io_op->read_addr);
+       if(match)
+               kref_put(&match->refcount, omnibook_free_port);
+
+       match = NULL;
+       match = omnibook_match_port(io_op->backend->data, io_op->write_addr);
+       if(match)
+               kref_put(&match->refcount, omnibook_free_port);
 
-int omnibook_io_write(struct omnibook_io_operation *io_op, u8 value)
+}
+
+static int omnibook_io_read(const struct omnibook_operation *io_op, u8 *value)
+{
+       *value = inb(io_op->read_addr);
+       if(io_op->read_mask)
+               *value &= io_op->read_mask;
+       return 0;
+}
+
+static int omnibook_io_write(const struct omnibook_operation *io_op, u8 value)
+{
+       outb(io_op->write_addr, value);
+       return 0;
+}
+
+
+/*
+ * Backend interface declarations
+ */
+
+struct omnibook_backend kbc_backend = {
+       .name = "i8042",
+       .byte_write = omnibook_kbc_command,
+       .hotkeys_set = omnibook_kbc_hotkeys,
+};
+
+struct omnibook_backend pio_backend = {
+       .name = "pio",
+       .data = &pio_private_data,
+       .init = omnibook_pio_init,
+       .exit = omnibook_pio_exit,
+       .byte_read = omnibook_io_read,
+       .byte_write = omnibook_io_write,
+};
+
+struct omnibook_backend ec_backend = {
+       .name = "ec",
+       .byte_read = omnibook_ec_read,
+       .byte_write = omnibook_ec_write,
+       .display_get =  omnibook_ec_display,
+};
+
+int omnibook_apply_write_mask(const struct omnibook_operation *io_op, int toggle)
 {
        int retval = 0;
+       int mask;
+       u8 data;
        
-       switch(io_op->type) {
-       case EC:
-               retval = omnibook_ec_write( io_op->write, value);
-               break;
-       case CDI:
-               retval = omnibook_cdimode_write( io_op->write, value);
-               break;
-       default:
-               BUG();
-       }
+
+       if((retval = io_op->backend->byte_read(io_op,&data)))
+               return retval;
        
-       return retval;          
+       if( toggle == 1)
+               mask = io_op->on_mask;
+       else if( toggle == 0)
+               mask = io_op->off_mask;
+       else
+               return -EINVAL;
+
+       if(mask > 0)
+               data |= (u8) mask;
+       else if (mask < 0)
+               data &= ~((u8) (-mask));
+       else
+               return -EINVAL;
+
+       retval = io_op->backend->byte_write(io_op,data);
+       
+       return retval;
 }
 
+/*
+ * Helper for toggle like operations
+ */
+int omnibook_toggle(const struct omnibook_operation *io_op, int toggle)
+{
+       int retval;
+       u8 data;
+       
+       data = toggle ? io_op->on_mask : io_op->off_mask;
+       retval = io_op->backend->byte_write(io_op, data);
+       return retval;
+}
+
+
 /* End of file */
diff --git a/ec.h b/ec.h
index cd22be524a8a34723a851b8441ee5cfdf60f47f2..c136b7bb89916cb5dea8ede50f41508045907a18 100644 (file)
--- a/ec.h
+++ b/ec.h
@@ -1,6 +1,5 @@
 /*
- * ec.h -- low level definitions to access Embedded Controller
- *         and Keyboard Controller and system I/O ports or memory
+ * ec.h -- low level definitions to access Embedded Controller and co.
  * 
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
  * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
  */
 
-extern int omnibook_ec_read(u8 addr, u8 *data);
-extern int omnibook_ec_write(u8 addr, u8 data);
-extern int omnibook_kbc_command(u8 cmd, u8 data);
+#include <linux/acpi.h>
 
-struct omnibook_io_operation;
+/*
+ * Quite ugly:
+ * on_mask and off_maks are also used to store the i8042 data for kbc backend.
+ * an union seemed overkilled
+ */
 
-extern int omnibook_io_read(struct omnibook_io_operation *io_op, u8 *value);
-extern int omnibook_io_write(struct omnibook_io_operation *io_op, u8 value);
-void *omnibook_io_match(const struct omnibook_io_operation *io_op);
+struct omnibook_backend;
 
-extern int omnibook_cdimode_read(unsigned int index, u8 *value);
-extern int omnibook_cdimode_write(unsigned int index, u8 value);
-extern void omnibook_cdimode_exit(void);
-extern int omnibook_cdimode_init(void);
+struct omnibook_operation {
+               struct omnibook_backend *backend;
+               unsigned long read_addr; /* address for data reading */
+               unsigned long write_addr; /* address for data writing */
+               u8 read_mask; /* read mask */
+               int on_mask; /* mask to set (pos value) or unset (neg value) to put feature to on state */
+               int off_mask; /* mask to set (pos value) or unset (neg value) to put feature to off state */
+};
 
+#define COMMAND(backend,data_on,data_off) .io_op = { backend, 0, 0, 0, data_on, data_off }
+#define SIMPLE_BYTE(backend,addr,mask) .io_op = { backend, addr, addr, mask, 0, 0 }
+
+struct omnibook_tbl {
+       enum omnibook_ectype_t ectypes;
+       struct omnibook_operation io_op;
+};
 
 /*
- *  Storage of generic (EC,PIO,...) addresses, read masks, and corresponding ectypes
- *  This is for use with the omnibook_io_{read/write} and omnibook_io_match 
- *  helper functions
+ * Backend interface definition
+ *
+ * Note:
+ * display_get/set and hotkey_set/get return a positive value on success 
+ * which set bits corresponds to the actual supported states 
+ * (see omnibook.h for the DISPLAY_* masks)  
  */
 
-struct omnibook_io_operation {
-       int ectypes;                            /* ectype */
-       enum { BAD, EC, PIO, MMIO, CDI} type;   /* address space */
-       u8 read;                                /* read address */
-       u8 write;                               /* write address */
-       u8 mask;                                /* read mask */
+struct omnibook_backend {
+       const char *name;       /* backend name */
+       void *data;             /* backend private data pointer */
+       int (*init) (const struct omnibook_operation *); 
+       void (*exit) (const struct omnibook_operation *);
+       int (*byte_read) (const struct omnibook_operation *, u8 *); 
+       int (*byte_write) (const struct omnibook_operation *, u8);
+       int (*aerial_get) (const struct omnibook_operation *, unsigned int *);
+       int (*aerial_set) (const struct omnibook_operation *, unsigned int);
+       int (*hotkeys_get) (const struct omnibook_operation *, unsigned int *);
+       int (*hotkeys_set) (const struct omnibook_operation *, unsigned int); 
+       int (*display_get) (const struct omnibook_operation *, unsigned int *);
+       int (*display_set) (const struct omnibook_operation *, unsigned int);
 };
 
+extern struct omnibook_backend kbc_backend;
+extern struct omnibook_backend pio_backend;
+extern struct omnibook_backend ec_backend;
+extern struct omnibook_backend acpi_backend;
+extern struct omnibook_backend nbsmi_backend;
+extern struct omnibook_backend compal_backend;
+
+#define KBC   &kbc_backend
+#define PIO   &pio_backend
+#define EC    &ec_backend
+#define ACPI  &acpi_backend
+#define SMI   &nbsmi_backend
+#define CDI   &compal_backend
+
+int legacy_ec_read(u8 addr, u8 *data);
+int legacy_ec_write(u8 addr, u8 data);
+int omnibook_apply_write_mask(const struct omnibook_operation *io_op, int toggle);
+int omnibook_toggle(const struct omnibook_operation *io_op, int toggle);
+
 /*
  *     Embedded controller adresses
  */
 
-#define XE3GF_CHGM                             0x90    /* , 16 bit */
-#define XE3GF_CHGS                             0x92    /* , 16 bit */
-#define XE3GF_CHGC                             0x94    /* Current charge of board, 16 bit */
-#define XE3GF_CHGV                             0x96    /* Current voltage, 16 bit */
-#define XE3GF_CHGA                             0x98    /* Current intensity, 16 bit */
-#define XE3GF_BAL                              0x9A    /* Battery present status */
-#define XE3GF_STA1                             0x9C    /* Various status bits */
-#define XE3GF_CSPR                             0xA1    /* Port replicator status, 1 bit */
-#define XE3GF_ADP                              0xA3    /* AC acapter status, 1 bit */
-#define XE3GF_FOT                              0xA5    /* Fan off temperature, 8 bit */
-#define XE3GF_FSD1                             0xA6    /* Fan on temperature, 8 bit */
-#define XE3GF_FSD2                             0xA7    /* Fan level 2 temperature, 8 bit */
-#define XE3GF_FSD3                             0xA8    /* Fan level 3 temperature, 8 bit */
-#define XE3GF_FSD4                             0xA9    /* Fan level 4 temperature, 8 bit */
-#define XE3GF_FSD5                             0xAA    /* Fan level 5 temperature, 8 bit */
-#define XE3GF_FSD6                             0xAB    /* Fan level 6 temperature, 8 bit */
-#define XE3GF_FSD7                             0xAC    /* Fan level 7 temperature, 8 bit */
-#define XE3GF_FSRD                             0xAD    /* Fan status, 8 bit */
-#define XE3GF_CTMP                             0xB0    /* CPU tempetature, 8 bit */
-#define XE3GF_BRTS                             0xB9    /* LCD brightness, 4 bit */
-#define XE3GF_BTY0                             0xC0    /* Battery 0 type, 1 bit */
-#define XE3GF_BST0                             0xC1    /* Battery 0 status, 3 bit */
-#define XE3GF_BRC0                             0xC2    /* Battery 0 remaining capacity, 16 bit */
-#define XE3GF_BSN0                             0xC4    /* Battery 0 serial number 16 bit */
-#define XE3GF_BPV0                             0xC6    /* Battery 0 present voltage, 16 bit */
-#define XE3GF_BDV0                             0xC8    /* Battery 0 design voltage 16 bit */
-#define XE3GF_BDC0                             0xCA    /* Battery 0 design capacity 16 bit */
-#define XE3GF_BFC0                             0xCC    /* Battery 0 last full capacity 16 bit */
-#define XE3GF_GAU0                             0xCE    /* Battery 0 gauge, 8 bit */
-#define XE3GF_BTY1                             0xD0    /* Battery 1 type, 1 bit */
-#define XE3GF_BST1                             0xD1    /* Battery 1 status, 3 bit */
-#define XE3GF_BRC1                             0xD2    /* Battery 1 remaining capacity, 16 bit */
-#define XE3GF_BSN1                             0xD4    /* Battery 1 serial number, 16 bit */
-#define XE3GF_BPV1                             0xD6    /* Battery 1 present voltage, 16 bit */
-#define XE3GF_BDV1                             0xD8    /* Battery 1 design voltage 16 bit */
-#define XE3GF_BDC1                             0xDA    /* Battery 1 design capacity 16 bit */
-#define XE3GF_BFC1                             0xDC    /* Battery 1 last full capacity 16 bit */
-#define XE3GF_GAU1                             0xDE    /* Battery 1 gauge, 8 bit */
+#define XE3GF_CHGM     0x90    /* , 16 bit */
+#define XE3GF_CHGS     0x92    /* , 16 bit */
+#define XE3GF_CHGC     0x94    /* Current charge of board, 16 bit */
+#define XE3GF_CHGV     0x96    /* Current voltage, 16 bit */
+#define XE3GF_CHGA     0x98    /* Current intensity, 16 bit */
+#define XE3GF_BAL      0x9A    /* Battery present status */
+#define XE3GF_STA1     0x9C    /* Various status bits */
+#define XE3GF_CSPR     0xA1    /* Port replicator status, 1 bit */
+#define XE3GF_ADP      0xA3    /* AC acapter status, 1 bit */
+#define XE3GF_FOT      0xA5    /* Fan off temperature, 8 bit */
+#define XE3GF_FSD1     0xA6    /* Fan on temperature, 8 bit */
+#define XE3GF_FSD2     0xA7    /* Fan level 2 temperature, 8 bit */
+#define XE3GF_FSD3     0xA8    /* Fan level 3 temperature, 8 bit */
+#define XE3GF_FSD4     0xA9    /* Fan level 4 temperature, 8 bit */
+#define XE3GF_FSD5     0xAA    /* Fan level 5 temperature, 8 bit */
+#define XE3GF_FSD6     0xAB    /* Fan level 6 temperature, 8 bit */
+#define XE3GF_FSD7     0xAC    /* Fan level 7 temperature, 8 bit */
+#define XE3GF_FSRD     0xAD    /* Fan status, 8 bit */
+#define XE3GF_CTMP     0xB0    /* CPU tempetature, 8 bit */
+#define XE3GF_BRTS     0xB9    /* LCD brightness, 4 bit */
+#define XE3GF_BTY0     0xC0    /* Battery 0 type, 1 bit */
+#define XE3GF_BST0     0xC1    /* Battery 0 status, 3 bit */
+#define XE3GF_BRC0     0xC2    /* Battery 0 remaining capacity, 16 bit */
+#define XE3GF_BSN0     0xC4    /* Battery 0 serial number 16 bit */
+#define XE3GF_BPV0     0xC6    /* Battery 0 present voltage, 16 bit */
+#define XE3GF_BDV0     0xC8    /* Battery 0 design voltage 16 bit */
+#define XE3GF_BDC0     0xCA    /* Battery 0 design capacity 16 bit */
+#define XE3GF_BFC0     0xCC    /* Battery 0 last full capacity 16 bit */
+#define XE3GF_GAU0     0xCE    /* Battery 0 gauge, 8 bit */
+#define XE3GF_BTY1     0xD0    /* Battery 1 type, 1 bit */
+#define XE3GF_BST1     0xD1    /* Battery 1 status, 3 bit */
+#define XE3GF_BRC1     0xD2    /* Battery 1 remaining capacity, 16 bit */
+#define XE3GF_BSN1     0xD4    /* Battery 1 serial number, 16 bit */
+#define XE3GF_BPV1     0xD6    /* Battery 1 present voltage, 16 bit */
+#define XE3GF_BDV1     0xD8    /* Battery 1 design voltage 16 bit */
+#define XE3GF_BDC1     0xDA    /* Battery 1 design capacity 16 bit */
+#define XE3GF_BFC1     0xDC    /* Battery 1 last full capacity 16 bit */
+#define XE3GF_GAU1     0xDE    /* Battery 1 gauge, 8 bit */
 
 /*
  * Bitmasks for sub byte values
  */
 
-#define XE3GF_SHDD_MASK                                0x40    /* External display status */
-#define XE3GF_CSPR_MASK                                0x01    /* Port replicator status */
-#define XE3GF_ADP_MASK                         0x20    /* AC acapter status */
-#define XE3GF_BAL0_MASK                                0x01    /* Battery 0 present */
-#define XE3GF_BAL1_MASK                                0x02    /* Battery 1 present */
-#define XE3GF_BMF_MASK                         0x70    /* Model code */
-#define XE3GF_BTY_MASK                         0x80    /* Type: Ni-MH or Li-Ion */
-#define XE3GF_BST_MASK_DSC                     0x01    /* Discarging */
-#define XE3GF_BST_MASK_CHR                     0x02    /* Charging */
-#define XE3GF_BST_MASK_CRT                     0x04    /* Critical */
-#define XE3GF_FSRD_MASK_S1                     0x01    /* Fan level 1 */
-#define XE3GF_FSRD_MASK_S2                     0x02    /* Fan level 2 */
-#define XE3GF_FSRD_MASK_S3                     0x04    /* Fan level 3 */
-#define XE3GF_FSRD_MASK_S4                     0x08    /* Fan level 4 */
-#define XE3GF_FSRD_MASK_S5                     0x10    /* Fan level 5 */
-#define XE3GF_FSRD_MASK_S6                     0x20    /* Fan level 6 */
-#define XE3GF_FSRD_MASK_S7                     0x40    /* Fan level 7 */
-#define XE3GF_BRTS_MASK                                0x0F    /* LCD brightness */
-
-#define XE3GF_FAN_ON_MASK                      0x02    /* Fan on */
+#define XE3GF_SHDD_MASK                0x40    /* External display status */
+#define XE3GF_CSPR_MASK                0x01    /* Port replicator status */
+#define XE3GF_ADP_MASK         0x20    /* AC acapter status */
+#define XE3GF_BAL0_MASK                0x01    /* Battery 0 present */
+#define XE3GF_BAL1_MASK                0x02    /* Battery 1 present */
+#define XE3GF_BMF_MASK         0x70    /* Model code */
+#define XE3GF_BTY_MASK         0x80    /* Type: Ni-MH or Li-Ion */
+#define XE3GF_BST_MASK_DSC     0x01    /* Discarging */
+#define XE3GF_BST_MASK_CHR     0x02    /* Charging */
+#define XE3GF_BST_MASK_CRT     0x04    /* Critical */
+#define XE3GF_FSRD_MASK_S1     0x01    /* Fan level 1 */
+#define XE3GF_FSRD_MASK_S2     0x02    /* Fan level 2 */
+#define XE3GF_FSRD_MASK_S3     0x04    /* Fan level 3 */
+#define XE3GF_FSRD_MASK_S4     0x08    /* Fan level 4 */
+#define XE3GF_FSRD_MASK_S5     0x10    /* Fan level 5 */
+#define XE3GF_FSRD_MASK_S6     0x20    /* Fan level 6 */
+#define XE3GF_FSRD_MASK_S7     0x40    /* Fan level 7 */
+#define XE3GF_BRTS_MASK                0x0F    /* LCD brightness */
+#define XE3GF_FAN_ON_MASK      0x02    /* Fan on */
 
 /*
  * OmniBook XE3 GC values
  */
 
-#define XE3GC_CTMP                             0x28    /* CPU tempetature, 8 bit */
-#define XE3GC_STA1                             0x30    /* Various status bits */
-#define XE3GC_Q0A                              0x31    /* Various status bits */
-#define XE3GC_CCUR                             0x38    /* Current charge of board, 16 bit ? */
-#define XE3GC_CVOL                             0x3A    /* Current voltage, 16 bit ? */
-#define XE3GC_CARM                             0x3C    /* Current intensity, 16 bit ? */
-#define XE3GC_BAT                              0x3E    /* Battery present status */
-#define XE3GC_BST0                             0x40    /* Battery 0 status, 3 bit */
-#define XE3GC_BPR0                             0x41    /* Battery 0 present rate, 16 bit ? */
-#define XE3GC_BRC0                             0x43    /* Battery 0 remaining capacity, 16 bit */
-#define XE3GC_BPV0                             0x45    /* Battery 0 present voltage, 16 bit */
-#define XE3GC_BDV0                             0x47    /* Battery 0 design voltage 16 bit */
-#define XE3GC_BDC0                             0x49    /* Battery 0 design capacity 16 bit */
-#define XE3GC_BTY0                             0x4A    /* Battery 0 type, 1 bit ? */
-#define XE3GC_BTP0                             0x4B    /* Battery 0 ?, 1 bit */
-#define XE3GC_BSN0                             0x4C    /* Battery 0 serial number, 8 bit ? */
-#define XE3GC_BMF0                             0x4D    /* Battery 0 ?,8 bit */
-#define XE3GC_BST1                             0x50    /* Battery 1 status, 3 bit */
-#define XE3GC_BPR1                             0x51    /* Battery 1 present rate, 16 bit ? */
-#define XE3GC_BRC1                             0x53    /* Battery 1 remaining capacity, 16 bit */
-#define XE3GC_BPV1                             0x55    /* Battery 1 present voltage, 16 bit */
-#define XE3GC_BDV1                             0x57    /* Battery 1 design voltage 16 bit */
-#define XE3GC_BDC1                             0x59    /* Battery 1 design capacity 16 bit */
-#define XE3GC_BTY1                             0x5A    /* Battery 1 type, 1 bit ? */
-#define XE3GC_BTP1                             0x5B    /* Battery 1 ?, 1 bit */
-#define XE3GC_BSN1                             0x5C    /* Battery 1 serial number, 8 bit ? */
-#define XE3GC_BMF1                             0x5D    /* Battery 1 ?,8 bit */
-#define XE3GC_STA2                             0x61    /* Various status bits */
-#define XE3GC_BTVL                             0x6A    /* LCD brightness, 4 bit */
+#define XE3GC_CTMP     0x28    /* CPU tempetature, 8 bit */
+#define XE3GC_STA1     0x30    /* Various status bits */
+#define XE3GC_Q0A      0x31    /* Various status bits */
+#define XE3GC_CCUR     0x38    /* Current charge of board, 16 bit ? */
+#define XE3GC_CVOL     0x3A    /* Current voltage, 16 bit ? */
+#define XE3GC_CARM     0x3C    /* Current intensity, 16 bit ? */
+#define XE3GC_BAT      0x3E    /* Battery present status */
+#define XE3GC_BST0     0x40    /* Battery 0 status, 3 bit */
+#define XE3GC_BPR0     0x41    /* Battery 0 present rate, 16 bit ? */
+#define XE3GC_BRC0     0x43    /* Battery 0 remaining capacity, 16 bit */
+#define XE3GC_BPV0     0x45    /* Battery 0 present voltage, 16 bit */
+#define XE3GC_BDV0     0x47    /* Battery 0 design voltage 16 bit */
+#define XE3GC_BDC0     0x49    /* Battery 0 design capacity 16 bit */
+#define XE3GC_BTY0     0x4A    /* Battery 0 type, 1 bit ? */
+#define XE3GC_BTP0     0x4B    /* Battery 0 ?, 1 bit */
+#define XE3GC_BSN0     0x4C    /* Battery 0 serial number, 8 bit ? */
+#define XE3GC_BMF0     0x4D    /* Battery 0 ?,8 bit */
+#define XE3GC_BST1     0x50    /* Battery 1 status, 3 bit */
+#define XE3GC_BPR1     0x51    /* Battery 1 present rate, 16 bit ? */
+#define XE3GC_BRC1     0x53    /* Battery 1 remaining capacity, 16 bit */
+#define XE3GC_BPV1     0x55    /* Battery 1 present voltage, 16 bit */
+#define XE3GC_BDV1     0x57    /* Battery 1 design voltage 16 bit */
+#define XE3GC_BDC1     0x59    /* Battery 1 design capacity 16 bit */
+#define XE3GC_BTY1     0x5A    /* Battery 1 type, 1 bit ? */
+#define XE3GC_BTP1     0x5B    /* Battery 1 ?, 1 bit */
+#define XE3GC_BSN1     0x5C    /* Battery 1 serial number, 8 bit ? */
+#define XE3GC_BMF1     0x5D    /* Battery 1 ?,8 bit */
+#define XE3GC_STA2     0x61    /* Various status bits */
+#define XE3GC_BTVL     0x6A    /* LCD brightness, 4 bit */
 
 /*
  * Bitmasks for sub byte values
  */
 
-#define XE3GC_ADP_MASK                         0x40    /* AC acapter status */
-#define XE3GC_BAT0_MASK                                0x01    /* Battery 0 present */
-#define XE3GC_BAT1_MASK                                0x02    /* Battery 1 present */
-#define XE3GC_BTY_MASK                         0x01    /* Type: Ni-MH or Li-Ion */
-#define XE3GC_BST_MASK_DSC                     0x01    /* Discarging */
-#define XE3GC_BST_MASK_CHR                     0x02    /* Charging */
-#define XE3GC_BST_MASK_CRT                     0x04    /* Critical */
-#define XE3GC_CRTI_MASK                                0x04    /* External display status */
-#define XE3GC_SLPB_MASK                                0x01    /* Sleep button pressed */
-#define XE3GC_F5_MASK                          0x02    /* Fn-F5 - LCD/CRT switch pressed */
-#define XE3GC_VOLD_MASK                                0x04    /* Fn-down arrow or Volume down pressed */
-#define XE3GC_VOLU_MASK                                0x08    /* Fn-up arrow or Volume up pressed */
-#define XE3GC_MUTE_MASK                                0x10    /* Fn+F7 - Volume mute pressed */
-#define XE3GC_CNTR_MASK                                0x20    /* Fn+F3/Fn+F4 - Contrast up or down pressed */
-#define XE3GC_BRGT_MASK                                0x40    /* Fn+F1/Fn+F2 - Brightness up or down pressed */
-#define XE3GC_BTVL_MASK                                0x0F    /* LCD brightness */
+#define XE3GC_ADP_MASK         0x40    /* AC acapter status */
+#define XE3GC_BAT0_MASK                0x01    /* Battery 0 present */
+#define XE3GC_BAT1_MASK                0x02    /* Battery 1 present */
+#define XE3GC_BTY_MASK         0x01    /* Type: Ni-MH or Li-Ion */
+#define XE3GC_BST_MASK_DSC     0x01    /* Discarging */
+#define XE3GC_BST_MASK_CHR     0x02    /* Charging */
+#define XE3GC_BST_MASK_CRT     0x04    /* Critical */
+#define XE3GC_CRTI_MASK                0x04    /* External display status */
+#define XE3GC_SLPB_MASK                0x01    /* Sleep button pressed */
+#define XE3GC_F5_MASK          0x02    /* Fn-F5 - LCD/CRT switch pressed */
+#define XE3GC_VOLD_MASK                0x04    /* Fn-down arrow or Volume down pressed */
+#define XE3GC_VOLU_MASK                0x08    /* Fn-up arrow or Volume up pressed */
+#define XE3GC_MUTE_MASK                0x10    /* Fn+F7 - Volume mute pressed */
+#define XE3GC_CNTR_MASK                0x20    /* Fn+F3/Fn+F4 - Contrast up or down pressed */
+#define XE3GC_BRGT_MASK                0x40    /* Fn+F1/Fn+F2 - Brightness up or down pressed */
+#define XE3GC_BTVL_MASK                0x0F    /* LCD brightness */
 
 /*
  * Emulated scancodes
  */
 
-#define XE3GC_VOLD_SCAN                                0x2E    /* Volume down button scancode */
-#define XE3GC_VOLU_SCAN                                0x30    /* Volume up button scancode */
-#define XE3GC_MUTE_SCAN                                0x20    /* Volume up button scancode */
+#define XE3GC_VOLD_SCAN                0x2E    /* Volume down button scancode */
+#define XE3GC_VOLU_SCAN                0x30    /* Volume up button scancode */
+#define XE3GC_MUTE_SCAN                0x20    /* Volume up button scancode */
 
 /*
  * Toshiba Satellite A105 values and mask
@@ -188,104 +226,104 @@ struct omnibook_io_operation {
  * Fujitsu Amilo D values
  */
 
-#define AMILOD_TMP                             0x28    /* CPU tempetature, 8 bit */
-#define AMILOD_STA1                            0x30    /* Various status bits */
-#define AMILOD_BAT                             0x3E    /* Battery present status */
-#define AMILOD_BDC0                            0x40    /* Battery 0 design capacity 16 bit */
-#define AMILOD_BDV0                            0x42    /* Battery 0 design voltage 16 bit */
-#define AMILOD_BTY0                            0x44    /* Battery 0 type, 1 bit ? */
-#define AMILOD_BST0                            0x45    /* Battery 0 status, 3 bit */
-#define AMILOD_BPR0                            0x46    /* Battery 0 present rate, 16 bit ? */
-#define AMILOD_BRC0                            0x48    /* Battery 0 remaining capacity, 16 bit */
-#define AMILOD_BPV0                            0x4A    /* Battery 0 present voltage, 16 bit */
-#define AMILOD_BTP0                            0x4C    /* Battery 0 ?, 1 bit */
-#define AMILOD_BDC1                            0x50    /* Battery 1 design capacity 16 bit */
-#define AMILOD_BDV1                            0x52    /* Battery 1 design voltage 16 bit */
-#define AMILOD_BTY1                            0x54    /* Battery 1 type, 1 bit ? */
-#define AMILOD_BST1                            0x55    /* Battery 1 status, 3 bit */
-#define AMILOD_BPR1                            0x56    /* Battery 1 present rate, 16 bit ? */
-#define AMILOD_BRC1                            0x58    /* Battery 1 remaining capacity, 16 bit */
-#define AMILOD_BPV1                            0x5A    /* Battery 1 present voltage, 16 bit */
-#define AMILOD_BTP1                            0x5C    /* Battery 1 ?, 1 bit */
-#define AMILOD_CBRG                            0x6F    /* LCD brightness, 4 bit */
+#define AMILOD_TMP     0x28    /* CPU tempetature, 8 bit */
+#define AMILOD_STA1    0x30    /* Various status bits */
+#define AMILOD_BAT     0x3E    /* Battery present status */
+#define AMILOD_BDC0    0x40    /* Battery 0 design capacity 16 bit */
+#define AMILOD_BDV0    0x42    /* Battery 0 design voltage 16 bit */
+#define AMILOD_BTY0    0x44    /* Battery 0 type, 1 bit ? */
+#define AMILOD_BST0    0x45    /* Battery 0 status, 3 bit */
+#define AMILOD_BPR0    0x46    /* Battery 0 present rate, 16 bit ? */
+#define AMILOD_BRC0    0x48    /* Battery 0 remaining capacity, 16 bit */
+#define AMILOD_BPV0    0x4A    /* Battery 0 present voltage, 16 bit */
+#define AMILOD_BTP0    0x4C    /* Battery 0 ?, 1 bit */
+#define AMILOD_BDC1    0x50    /* Battery 1 design capacity 16 bit */
+#define AMILOD_BDV1    0x52    /* Battery 1 design voltage 16 bit */
+#define AMILOD_BTY1    0x54    /* Battery 1 type, 1 bit ? */
+#define AMILOD_BST1    0x55    /* Battery 1 status, 3 bit */
+#define AMILOD_BPR1    0x56    /* Battery 1 present rate, 16 bit ? */
+#define AMILOD_BRC1    0x58    /* Battery 1 remaining capacity, 16 bit */
+#define AMILOD_BPV1    0x5A    /* Battery 1 present voltage, 16 bit */
+#define AMILOD_BTP1    0x5C    /* Battery 1 ?, 1 bit */
+#define AMILOD_CBRG    0x6F    /* LCD brightness, 4 bit */
 
 /*
  * Bitmasks for sub byte values
  */
 
-#define AMILOD_ADP_MASK                                0x40    /* AC acapter status */
-#define AMILOD_BAT0_MASK                       0x01    /* Battery 0 present */
-#define AMILOD_BAT1_MASK                       0x02    /* Battery 1 present */
-#define AMILOD_BTY_MASK                                0x01    /* Type: Ni-MH or Li-Ion */
-#define AMILOD_BST_MASK_DSC                    0x01    /* Discarging */
-#define AMILOD_BST_MASK_CHR                    0x02    /* Charging */
-#define AMILOD_BST_MASK_CRT                    0x04    /* Critical */
-#define AMILOD_CBRG_MASK                       0x0F    /* LCD brightness */
+#define AMILOD_ADP_MASK                0x40    /* AC acapter status */
+#define AMILOD_BAT0_MASK       0x01    /* Battery 0 present */
+#define AMILOD_BAT1_MASK       0x02    /* Battery 1 present */
+#define AMILOD_BTY_MASK                0x01    /* Type: Ni-MH or Li-Ion */
+#define AMILOD_BST_MASK_DSC    0x01    /* Discarging */
+#define AMILOD_BST_MASK_CHR    0x02    /* Charging */
+#define AMILOD_BST_MASK_CRT    0x04    /* Critical */
+#define AMILOD_CBRG_MASK       0x0F    /* LCD brightness */
 
 /*
  * OmniBook 500, 510, 6000, 6100, XE2 values
  */
 
-#define OB500_STA1                             0x44    /* Various status bits */
-#define OB500_STA2                             0x50    /* Various status bits */
-#define OB500_CTMP                             0x55    /* CPU tempetature, 8 bit */
-#define OB500_BT1I                             0x58    /* Battery 1 ? 16 bit */
-#define OB500_BT1C                             0x5A    /* Battery 1 remaining capacity 16 bit ? */
-#define OB500_BT1V                             0x5C    /* Battery 1 present voltage 16 bit ? */
-#define OB500_BT1S                             0x5E    /* Battery 1 status 3 bit ? */
-#define OB500_BT2I                             0x6A    /* Battery 2 ? 16 bit */
-#define OB500_BT2C                             0x6C    /* Battery 2 remaining capacity 16 bit ? */
-#define OB500_BT2V                             0x6E    /* Battery 2 present voltage 16 bit ? */
-#define OB500_BT2S                             0x70    /* Battery 2 status 3 bit ? */
-#define OB500_BT3I                             0x5F    /* Battery 3 ? 16 bit */
-#define OB500_BT3C                             0x61    /* Battery 3 remaining capacity 16 bit ? */
-#define OB500_BT3V                             0x63    /* Battery 3 present voltage 16 bit ? */
-#define OB500_BT3S                             0x65    /* Battery 3 status 3 bit ? */
-
-#define OB6000_STA1                            0x77    /* Various status bits */
-
-#define XE2_STA1                               0x50    /* Various status bits */
+#define OB500_STA1     0x44    /* Various status bits */
+#define OB500_STA2     0x50    /* Various status bits */
+#define OB500_CTMP     0x55    /* CPU tempetature, 8 bit */
+#define OB500_BT1I     0x58    /* Battery 1 ? 16 bit */
+#define OB500_BT1C     0x5A    /* Battery 1 remaining capacity 16 bit ? */
+#define OB500_BT1V     0x5C    /* Battery 1 present voltage 16 bit ? */
+#define OB500_BT1S     0x5E    /* Battery 1 status 3 bit ? */
+#define OB500_BT2I     0x6A    /* Battery 2 ? 16 bit */
+#define OB500_BT2C     0x6C    /* Battery 2 remaining capacity 16 bit ? */
+#define OB500_BT2V     0x6E    /* Battery 2 present voltage 16 bit ? */
+#define OB500_BT2S     0x70    /* Battery 2 status 3 bit ? */
+#define OB500_BT3I     0x5F    /* Battery 3 ? 16 bit */
+#define OB500_BT3C     0x61    /* Battery 3 remaining capacity 16 bit ? */
+#define OB500_BT3V     0x63    /* Battery 3 present voltage 16 bit ? */
+#define OB500_BT3S     0x65    /* Battery 3 status 3 bit ? */
+
+#define OB6000_STA1    0x77    /* Various status bits */
+
+#define XE2_STA1       0x50    /* Various status bits */
 
 /*
  * Bitmasks for sub byte values
  */
 
-#define OB500_LIDS_MASK                                0x01    /* LID status */
-#define OB500_CRTS_MASK                                0x20    /* External display status */
-#define OB500_SLPS_MASK                                0x40    /* Sleep button status */
-#define OB500_DCKS_MASK                                0x80    /* Docking status */
-#define OB500_ADP_MASK                         0x02    /* AC acapter status */
-#define OB500_BST_MASK_DSC                     0x01    /* Discarging */
-#define OB500_BST_MASK_CHR                     0x02    /* Charging */
-#define OB500_BST_MASK_CRT                     0x04    /* Critical */
+#define OB500_LIDS_MASK                0x01    /* LID status */
+#define OB500_CRTS_MASK                0x20    /* External display status */
+#define OB500_SLPS_MASK                0x40    /* Sleep button status */
+#define OB500_DCKS_MASK                0x80    /* Docking status */
+#define OB500_ADP_MASK         0x02    /* AC acapter status */
+#define OB500_BST_MASK_DSC     0x01    /* Discarging */
+#define OB500_BST_MASK_CHR     0x02    /* Charging */
+#define OB500_BST_MASK_CRT     0x04    /* Critical */
 
-#define OB6000_FAN_MASK                                0x10    /* Fan status */
+#define OB6000_FAN_MASK                0x10    /* Fan status */
 
-#define XE2_ADP_MASK                           0x02    /* AC acapter status */
+#define XE2_ADP_MASK           0x02    /* AC acapter status */
 
 /*
  * OmniBook 4150
  */
 
-#define OB4150_TMP                             0x28    /* CPU tempetature, 8 bit */
-#define OB4150_STA1                            0x2E    /* Various status bits */
-#define OB4150_STA2                            0x2F    /* Various status bits */
-#define OB4150_ADP                             0x30    /* AC acapter status, 1 bit */
-#define OB4150_DCID                            0x2C    /* Port replicator */
+#define OB4150_TMP             0x28    /* CPU tempetature, 8 bit */
+#define OB4150_STA1            0x2E    /* Various status bits */
+#define OB4150_STA2            0x2F    /* Various status bits */
+#define OB4150_ADP             0x30    /* AC acapter status, 1 bit */
+#define OB4150_DCID            0x2C    /* Port replicator */
 
 /*
  * Bitmasks for sub byte values
  */
 
-#define OB4150_FAN_MASK                                0x01    /* Fan status */
-#define OB4150_ADP_MASK                                0x40    /* AC acapter status */
-#define OB4150_CRST_MASK                       0x20    /* External display status */
+#define OB4150_FAN_MASK                0x01    /* Fan status */
+#define OB4150_ADP_MASK                0x40    /* AC acapter status */
+#define OB4150_CRST_MASK       0x20    /* External display status */
 
 /*
  *     Keyboard controller command for some laptop functions
  */
 
-#define OMNIBOOK_KBC_CONTROL_CMD               0x59
+#define OMNIBOOK_KBC_CONTROL_CMD       0x59
 
 /*
  *     Keyboard controller command parameters for functions available via kbc
@@ -306,47 +344,71 @@ struct omnibook_io_operation {
  * Other I/O ports
  */
 
-#define ACL00_AC_STAT                          0x11B9  /* AC adapter status on ACL00 */
-#define ACL00_AC_MASK                          0x04    /* Bitmask for AC adapter status on ACL00 */
-#define TOSH3K_AC_STAT                         0x102D  /* AC adapter status on Toshiba 3000 */
-#define TOSH3K_AC_MASK                         0x08    /* Bitmask for AC adapter status on Toshiba 3000 */
-#define XE3GF_AC_STAT                          0x11B9  /* AC adapter status on XE3 GF */
-#define XE3GF_AC_MASK                          0x04    /* Bitmask for AC adapter status on XE3 GF */
-#define XE3GF_LID_STAT                         0x11AD  /* LID switch status on XE3 GF */
-#define XE3GF_LID_MASK                         0x20    /* Bitmask for LID switch status on XE3 GF */
-#define XE3GC_SMIC                             0xFE00
-
-#define OB500_GPO1                             0x8034  /* Fan control */
-#define OB510_GPO2                             0x11B9  /* LCD backlight */
-#define OB510_GPIO                             0x118F  /* Fan control */
-
-#define OB500_FAN_ON_MASK                      0x0A    /* Turn fan on with zero bits */
-#define OB500_FAN_OFF_MASK                     0x08    /* Fan status/off */
-#define OB500_BKLT_MASK                                0x40    /* LCD backlight */
-#define OB510_FAN_ON_MASK                      0x18    /* Turn fan on with zero bits */
-#define OB510_FAN_OFF_MASK                     0x10    /* Turn fan on */
-#define OB510_BKLT_MASK                                0x01    /* LCD backlight */
-
-#define XE2_FAN_MASK                           0x02    /* Turn fan on with zero bit */
+#define ACL00_AC_STAT          0x11B9  /* AC adapter status on ACL00 */
+#define ACL00_AC_MASK          0x04    /* Bitmask for AC adapter status on ACL00 */
+#define TOSH3K_AC_STAT         0x102D  /* AC adapter status on Toshiba 3000 */
+#define TOSH3K_AC_MASK         0x08    /* Bitmask for AC adapter status on Toshiba 3000 */
+#define XE3GF_AC_STAT          0x11B9  /* AC adapter status on XE3 GF */
+#define XE3GF_AC_MASK          0x04    /* Bitmask for AC adapter status on XE3 GF */
+#define XE3GF_LID_STAT         0x11AD  /* LID switch status on XE3 GF */
+#define XE3GF_LID_MASK         0x20    /* Bitmask for LID switch status on XE3 GF */
+#define XE3GC_SMIC             0xFE00
+
+#define OB500_GPO1             0x8034  /* Fan control */
+#define OB510_GPO2             0x11B9  /* LCD backlight */
+#define OB510_GPIO             0x118F  /* Fan control */
+
+#define OB500_FAN_ON_MASK      0x0A    /* Turn fan on with zero bits */
+#define OB500_FAN_OFF_MASK     0x08    /* Fan status/off */
+#define OB500_BKLT_MASK                0x40    /* LCD backlight */
+#define OB510_FAN_ON_MASK      0x18    /* Turn fan on with zero bits */
+#define OB510_FAN_OFF_MASK     0x10    /* Turn fan on */
+#define OB510_BKLT_MASK                0x01    /* LCD backlight */
+
+#define XE2_FAN_MASK           0x02    /* Turn fan on with zero bit */
 
 /*
  * Memory adresses
  */
 
-#define XE3GC_BCMD                             0xFFFFEBC
+#define XE3GC_BCMD             0xFFFFEBC
 
 /*
  * Toshiba Satellite A105 values and mask
  */
 
-#define A105_BNDT                              0xA3    /* LCD brightness */
-#define A105_BNDT_MASK                         0x0F
+#define A105_BNDT              0xA3    /* LCD brightness */
+#define A105_BNDT_MASK         0x0F
 
 /*
  * Index and values for Command/Data/Index interface
  */
 
-#define TSM70_FN_INDEX                 0x45
-#define TSM70_FN_ENABLE                        0x75
-#define TSM70_LCD_READ                 0x5C
-#define TSM70_LCD_WRITE                        0x5D
+#define TSM70_FN_INDEX         0x45
+#define TSM70_FN_ENABLE                0x75
+#define TSM70_FN_DISABLE       0x74
+#define TSM70_HOTKEYS_INDEX    0x59
+#define TSM70_HOTKEYS_ENABLE   0x90
+#define TSM70_LCD_READ         0x5C
+#define TSM70_LCD_WRITE                0x5D
+#define TSM70_TOUCHPAD_ON      0x80
+#define TSM70_TOUCHPAD_OFF     0x81
+
+/* Toshiba SMI funtion */
+#define SMI_FN_PRESSED         0x00
+#define SMI_SET_LCD_BRIGHTNESS 0xa2
+#define SMI_GET_LCD_BRIGHTNESS 0xa3
+#define SMI_GET_KILL_SWITCH    0xa4
+#define SMI_SET_AERIAL         0xa5
+#define SMI_GET_AERIAL         0xa6
+#define SMI_SET_DISPLAY_STATE  0xa7
+#define SMI_GET_DISPLAY_STATE  0xa8
+#define SMI_SET_FN_INTERFACE   0xa9
+#define SMI_GET_FN_INTERFACE   0xaa
+#define SMI_GET_FN_LAST_SCAN   0xab
+#define SMI_SET_FN_F5_INTERFACE        0xc2
+
+#define SMI_FN_KEYS_MASK       0x01
+#define SMI_STICK_KEYS_MASK    0x02
+#define SMI_FN_TWICE_LOCK_MASK 0x04
+#define SMI_FN_DOCK_MASK       0x08
diff --git a/fan.c b/fan.c
index 31c35d36ebb804b79779bce3f19021c6de4785be..5989eb6e6816918d426b74988696237abad979fb 100644 (file)
--- a/fan.c
+++ b/fan.c
  * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
  */
 
-#ifdef OMNIBOOK_STANDALONE
 #include "omnibook.h"
-#else
-#include <linux/omnibook.h>
-#endif
 
 #include <linux/delay.h>
 #include <asm/io.h>
 #include "ec.h"
 
-static int omnibook_get_fan(void)
+static struct omnibook_operation ctmp_io_op = { EC, XE3GF_CTMP , 0, 0, 0, 0};
+static struct omnibook_operation fot_io_op = { EC, XE3GF_FOT, XE3GF_FOT, 0, 0, 0};
+
+static int omnibook_get_fan(struct omnibook_operation *io_op)
 {
        u8 fan;
        int retval;
 
+       if((retval = io_op->backend->byte_read(io_op, &fan)))
+               return retval;
+
        /*
-        * XE3GF
-        * TSP10 
+        * For most models the reading is a bool
+        * It as to be inverted on all but OB6000|OB6100|OB4150|AMILOD
+        * TSP10|XE3GF return an integer
         */
-       if (omnibook_ectype & (XE3GF|TSP10) ) {
-               if ((retval = omnibook_ec_read(XE3GF_FSRD, &fan)))
-                       return retval;
+
+       if(omnibook_ectype & (TSP10|XE3GF))
                retval = fan;
-       /*
-        * OB500 
-        */
-       } else if (omnibook_ectype & (OB500) ) {
-               fan = inb(OB500_GPO1);
-               retval = (fan & OB500_FAN_OFF_MASK) ? 0 : 1;
-       /*
-        * OB510 
-        */
-       } else if (omnibook_ectype & (OB510) ) {
-               fan = inb(OB510_GPIO);
-               retval = (fan & OB510_FAN_OFF_MASK) ? 0 : 1;
-       /*
-        * OB6000
-        * OB6100 
-        */
-       } else if (omnibook_ectype & (OB6000|OB6100) ) {
-               if ((retval = omnibook_ec_read(OB6000_STA1, &fan)))
-                       return retval;
-               retval = (fan & OB6000_FAN_MASK) ? 1 : 0;
-       /*
-        * OB4150
-        * AMILOD 
-        */
-       } else if (omnibook_ectype & (OB4150|AMILOD) ) {
-               if ((retval = omnibook_ec_read(OB4150_STA1, &fan)))
-                       return retval;
-               retval = (fan & OB4150_FAN_MASK) ? 1 : 0;
-       /*
-        * XE2 
-        */
-       } else if (omnibook_ectype & (XE2) ) {
-               fan = inb(OB500_GPO1);
-               retval = (fan & XE2_FAN_MASK) ? 0 : 1;
-       } else {
-               printk(O_INFO "Fan status monitoring is unsupported on this machie.\n");
-               retval = -ENODEV;
-       }
+       else if(omnibook_ectype & (OB6000|OB6100|OB4150|AMILOD))
+               retval = !!fan;
+       else
+               retval = !fan;
 
        return retval;
 }
 
-static int omnibook_fan_on(void)
+static int omnibook_fan_on(struct omnibook_operation *io_op)
 {
-       u8 fan;
-       int retval = 0;
-
-       /*
-        * XE3GF
-        * TSP10 
-        */
-       if (omnibook_ectype & (XE3GF|TSP10) ) {
-               if ((retval = omnibook_ec_read(XE3GF_FSRD, &fan)))
-                       return retval;
-               if ((retval = omnibook_ec_write(XE3GF_FSRD, fan | XE3GF_FAN_ON_MASK)))
-                       return retval;
-       /*
-        * OB500 
-        */
-       } else if (omnibook_ectype & (OB500) ) {
-               fan = inb(OB500_GPO1);
-               outb(fan & ~OB500_FAN_ON_MASK, OB500_GPO1);
-                       
-       /*
-        * OB510 
-        */
-       } else if (omnibook_ectype & (OB510) ) {
-               fan = inb(OB510_GPIO);
-               outb(fan & ~OB510_FAN_ON_MASK, OB510_GPIO);
-       /*
-        * OB6000
-        * OB6100 
-        */
-       } else if (omnibook_ectype & (OB6000|OB6100) ) {
-       
-               if ((retval = omnibook_ec_read(OB6000_STA1, &fan)))
-                       return retval;
-               if ((retval = omnibook_ec_write(OB6000_STA1, fan | OB6000_FAN_MASK)))
-                       return retval;
-       /*
-        * OB4150
-        * AMILOD 
-        */
-       } else if (omnibook_ectype & (OB4150|AMILOD) ) {
-               if ((retval = omnibook_ec_read(OB4150_STA1, &fan)))
-                       return retval;
-               if ((retval = omnibook_ec_write(OB4150_STA1, fan | OB4150_FAN_MASK)))
-                       return retval;
-       /*
-        * XE2 
-        */
-       } else if (omnibook_ectype & (XE2) ) {
-               fan = inb(OB500_GPO1);
-               outb(fan & ~XE2_FAN_MASK, OB500_GPO1);
-       } else {
-               printk(O_INFO "Direct fan control is unsupported on this machie.\n");
-               retval = -ENODEV;
-       }
-
-       return retval;
+       return omnibook_apply_write_mask(io_op,1);
 }
 
-static int omnibook_fan_off(void)
+static int omnibook_fan_off(struct omnibook_operation *io_op)
 {
-       u8 fan;
        int retval = 0;
 
-       /*
-        * XE3GF
-        * TSP10 
-        */
+/*
+ * Special handling for XE3GF & TSP10
+ */
        if (omnibook_ectype & (XE3GF|TSP10) ) {
                u8 fot, temp;
-               if ((retval = omnibook_ec_read(XE3GF_FSRD, &fan)))
+               retval = omnibook_get_fan(io_op);
+               
+               /* error or fan is already off */
+               if (retval <= 0 )
                        return retval;
 
-               /* fan is already off */
-               if (!fan)
-                       return 0;
-
                /* now we set FOT to current temp, then reset to initial value */
-               if ((retval = omnibook_ec_read(XE3GF_FOT, &fot)))
+               if ((retval = fot_io_op.backend->byte_read(&fot_io_op, &fot)))
                        return retval;
-               if ((retval = omnibook_ec_read(XE3GF_CTMP, &temp)))
+               if ((retval = ctmp_io_op.backend->byte_read(&ctmp_io_op, &temp)))
                        return retval;
-
+               
+/*
+ * FIXME: should add a timeout
+ */
                do {
-                       omnibook_ec_write(XE3GF_FOT, temp);
+                       fot_io_op.backend->byte_write(&fot_io_op, temp);
                        mdelay(1);
-               } while (omnibook_get_fan() != 0);
+               } while (omnibook_get_fan(io_op) != 0);
 
-               omnibook_ec_write(XE3GF_FOT, fot);
-       /*
-        * OB500 
-        */
-       } else if (omnibook_ectype & (OB500) ) {
-               fan = inb(OB500_GPO1);
-               outb(fan | OB500_FAN_OFF_MASK, OB500_GPO1);
-       /*
-        * OB510 
-        */
-       } else if (omnibook_ectype & (OB510) ) {
-               fan = inb(OB510_GPIO);
-               outb(fan | OB510_FAN_OFF_MASK, OB510_GPIO);
-       /*
-        * OB6000
-        * OB6100 
-        */
-       } else if (omnibook_ectype & (OB6000|OB6100) ) {
-               if ((retval = omnibook_ec_read(OB6000_STA1, &fan)))
-                       return retval;
-               if ((retval = omnibook_ec_write(OB6000_STA1, fan & ~OB6000_FAN_MASK)))
-                       return retval;
-       /*
-        * OB4150
-        * AMILOD 
-        */
-       } else if (omnibook_ectype & (OB4150|AMILOD) ) {
-               if ((retval = omnibook_ec_read(OB4150_STA1, &fan)))
-                       return retval;
-               if ((retval = omnibook_ec_write(OB4150_STA1, fan & ~OB4150_FAN_MASK)))
-                       return retval;
-       /*
-        * XE2 
-        */
-       } else if (omnibook_ectype & (XE2) ) {
-               fan = inb(OB500_GPO1);
-               outb(fan | XE2_FAN_MASK, OB500_GPO1);
-       } else {
-               printk(O_INFO "Direct fan control is unsupported on this machie.\n");
-               retval = -ENODEV;
-       }
+               fot_io_op.backend->byte_write(&fot_io_op, fot);
+       
+       } else 
+               retval = omnibook_apply_write_mask(io_op, 0);
 
        return retval;
 }
 
-static int omnibook_fan_read(char *buffer)
+static int omnibook_fan_read(char *buffer,struct omnibook_operation *io_op)
 {
        int fan;
        int len = 0;
        char *str;
 
-       fan = omnibook_get_fan();
+       fan = omnibook_get_fan(io_op);
        if (fan < 0)
                return fan;
        str = (fan) ? "on" : "off";
@@ -233,17 +109,17 @@ static int omnibook_fan_read(char *buffer)
        return len;
 }
 
-static int omnibook_fan_write(char *buffer)
+static int omnibook_fan_write(char *buffer,struct omnibook_operation *io_op)
 {
        int retval;
 
        switch (*buffer) {
        case '0':
-               if ((retval = omnibook_fan_off()))
+               if ((retval = omnibook_fan_off(io_op)))
                        return retval;
                break;
        case '1':
-               if ((retval = omnibook_fan_on()))
+               if ((retval = omnibook_fan_on(io_op)))
                        return retval;
                break;
        default:
@@ -254,7 +130,7 @@ static int omnibook_fan_write(char *buffer)
 
 static struct omnibook_feature fan_feature;
 
-static int omnibook_fan_init(void)
+static int __init omnibook_fan_init(struct omnibook_operation *io_op)
 {
        /*
         * OB4150
@@ -267,13 +143,24 @@ static int omnibook_fan_init(void)
        return 0;
 }
 
-static struct omnibook_feature __declared_feature fan_feature = {
+static struct omnibook_tbl fan_table[] __initdata = {
+       { XE3GF|TSP10,   {EC,XE3GF_FSRD,XE3GF_FSRD,0,XE3GF_FAN_ON_MASK,0}},
+       { OB500,         {PIO,OB500_GPO1,OB500_GPO1,OB500_FAN_OFF_MASK,-OB500_FAN_ON_MASK,OB500_FAN_OFF_MASK}},
+       { OB510,         {PIO,OB510_GPIO,OB510_GPIO,OB510_FAN_OFF_MASK,-OB510_FAN_ON_MASK,OB510_FAN_OFF_MASK}},
+       { OB6000|OB6100, {EC,OB6000_STA1,OB6000_STA1,OB6000_FAN_MASK,OB6000_FAN_MASK,-OB6000_FAN_MASK}},
+       { OB4150|AMILOD, {EC,OB4150_STA1,0,OB4150_FAN_MASK,0,0}},
+       { XE2,           {PIO,OB500_GPO1,0,XE2_FAN_MASK,0,0}},
+       { 0,}
+};
+
+static struct omnibook_feature __declared_feature fan_driver = {
         .name = "fan",
         .enabled = 1,
         .read = omnibook_fan_read,
         .write = omnibook_fan_write,
         .init = omnibook_fan_init,
         .ectypes = XE3GF|OB500|OB510|OB6000|OB6100|OB4150|XE2|AMILOD|TSP10,
+        .tbl = fan_table,
 };
 
 module_param_named(fan, fan_feature.enabled, int, S_IRUGO);
index e7aeca6ab39d5aeb7cb78315265575bc2d3c80ad..d5b49e9cec1be6861568e99c95e1ae5904681710 100644 (file)
  * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
  */
 
-#ifdef OMNIBOOK_STANDALONE
 #include "omnibook.h"
-#else
-#include <linux/omnibook.h>
-#endif
 
 #include <linux/ctype.h>
 #include "ec.h"
@@ -56,7 +52,7 @@ static int omnibook_get_fan_policy(void)
         */
        if (omnibook_ectype & (XE3GF) ) {
                for (i = 0; i <= OMNIBOOK_FAN_LEVELS; i++) {
-                       if ((retval = omnibook_ec_read(XE3GF_FOT + i, &tmp)))
+                       if ((retval = legacy_ec_read(XE3GF_FOT + i, &tmp)))
                                return retval;
                        omnibook_fan_policy[i] = tmp;
                }
@@ -90,7 +86,7 @@ static int omnibook_set_fan_policy(void)
                }
                for (i = 0; i <= OMNIBOOK_FAN_LEVELS; i++) {
                        if ((retval =
-                            omnibook_ec_write(XE3GF_FOT + i, omnibook_fan_policy[i])))
+                            legacy_ec_write(XE3GF_FOT + i, omnibook_fan_policy[i])))
                                return retval;
                }
        } else {
@@ -121,7 +117,7 @@ static int omnibook_set_fan_policy_defaults(void)
         */
        if (omnibook_ectype & (XE3GF) ) {
                for (i = 0; i <= OMNIBOOK_FAN_LEVELS; i++) {
-                       if ((retval = omnibook_ec_write(XE3GF_FOT + i, fan_defaults[i])))
+                       if ((retval = legacy_ec_write(XE3GF_FOT + i, fan_defaults[i])))
                                return retval;
                }
        } else {
@@ -132,7 +128,7 @@ static int omnibook_set_fan_policy_defaults(void)
        return retval;
 }
 
-static int omnibook_fan_policy_read(char *buffer)
+static int omnibook_fan_policy_read(char *buffer,struct omnibook_operation *io_op)
 {
        int retval;
        int len = 0;
@@ -163,7 +159,7 @@ static int omnibook_fan_policy_read(char *buffer)
        return len;
 }
 
-static int omnibook_fan_policy_write(char *buffer)
+static int omnibook_fan_policy_write(char *buffer,struct omnibook_operation *io_op)
 {
        int n = 0;
        char *b;
@@ -205,7 +201,7 @@ static int omnibook_fan_policy_write(char *buffer)
        return 0;
 }
 
-static struct omnibook_feature __declared_feature fan_policy_feature = {
+static struct omnibook_feature __declared_feature fan_policy_driver = {
         .name = "fan_policy",
         .enabled = 1,
         .read = omnibook_fan_policy_read,
@@ -213,6 +209,6 @@ static struct omnibook_feature __declared_feature fan_policy_feature = {
         .ectypes = XE3GF,
 };
 
-module_param_named(fan_policy, fan_policy_feature.enabled, int, S_IRUGO);
+module_param_named(fan_policy, fan_policy_driver.enabled, int, S_IRUGO);
 MODULE_PARM_DESC(fan_policy, "Use 0 to disable, 1 to enable fan control policy support");
 /* End of file */
index d6da6bc24a6c3157d395a3d7750251b8e9788a92..3fd00a9f1a52070c9eb6b9c99796b5425fd7a9fa 100644 (file)
--- a/hotkeys.c
+++ b/hotkeys.c
  * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
  */
 
-#ifdef OMNIBOOK_STANDALONE
 #include "omnibook.h"
-#else
-#include <linux/omnibook.h>
-#endif
-
 #include "ec.h"
 
-/* 
- * There is no information about reading Hotkeys status
- */
-static int omnibook_hotkeys_enabled = 0;
 
 /*
- * Some laptop model have require more work to enable an Fn+button hotkeys
+ * Save state for suspend/resume operation
  */
-static int omnibook_fnkeys_enabled = 0;
+static unsigned int saved_state;
 
-/*
- * Enable hotkeys sending command to the i8042
- */
-static int omnibook_hotkeys_on(void)
-{
-       int retval;
-       
-       if ((retval =omnibook_kbc_command
-           (OMNIBOOK_KBC_CONTROL_CMD, OMNIBOOK_KBC_CMD_ONETOUCH_ENABLE))) {
-               printk(O_ERR "Hotkeys enable command failed.\n");
-               return retval;
-       }
-       omnibook_hotkeys_enabled = 1;
-       printk(O_INFO "Enabling Hotkey buttons.\n");
-       return 0;
-}
+/* Predefined convinient on/off states */
+#define HKEY_ON  HKEY_ONETOUCH|HKEY_MULTIMEDIA|HKEY_FN|HKEY_DOCK|HKEY_FNF5
+#define HKEY_OFF 0
 
-/*
- * Disable hotkeys sending command to the i8042
- */
-static int omnibook_hotkeys_off(void)
+static int omnibook_hotkeys_set(struct omnibook_operation *io_op, unsigned int state)
 {
-       int retval;
+       int write_capability;
+
+       write_capability = io_op->backend->hotkeys_set(io_op, state);
+       if( write_capability < 0)
+               return write_capability;
+
+       /* Update saved state */
+       saved_state = state & write_capability;
        
-       if ((retval = omnibook_kbc_command
-           (OMNIBOOK_KBC_CONTROL_CMD, OMNIBOOK_KBC_CMD_ONETOUCH_DISABLE))) {
-               printk(O_ERR "Hotkeys disable command failed.\n");
-               return retval;
-       }
-       omnibook_hotkeys_enabled = 0;
-       printk(O_INFO "Disabling Hotkey buttons.\n");
        return 0;
 }
 
-/*
- * Enable Fn+foo key writing 75h to EC index 45h
- */
-static int omnibook_fnkeys_on(void)
+static int omnibook_hotkeys_get(struct omnibook_operation *io_op, unsigned int *state)
 {
-       int retval;
        
-       if ((retval = omnibook_cdimode_write(TSM70_FN_INDEX, TSM70_FN_ENABLE))) {
-               printk(O_ERR "fnkeys enable command failed.\n");
-               return retval;
-       }
-       omnibook_fnkeys_enabled = 1;
-       printk(O_INFO "Enabling Fn keys.\n");
-       return 0;
-}
+       unsigned int read_state = 0;
+       int read_capability = 0;
+       
+       if(io_op->backend->hotkeys_get)
+               read_capability = io_op->backend->hotkeys_get(io_op, &read_state);
+       if(read_capability < 0)
+               return read_capability;
 
-/*
- * FIXME Not implemented
- */
-static int omnibook_fnkeys_off(void)
-{
-       printk(O_WARN "Disabling of Fn keys not implemented.\n");
+       /* Return previously set state for the fields that are write only */
+       *state = (read_state & read_capability) + (saved_state & ~read_capability);
+       
        return 0;
 }
 
@@ -97,104 +64,106 @@ static int omnibook_fnkeys_off(void)
  */
  
 /*
- * omnibook_*keys_enabled = 1 means here "It was enabled prior to suspend, 
- * please reenable"
+ * Restore previously saved state
  */
-static int omnibook_hotkeys_resume(void)
-{
-       int retval = 0;
-       retval = (omnibook_hotkeys_enabled ? omnibook_hotkeys_on() : 0);
-       if (omnibook_ectype & TSM30X)
-               retval = (omnibook_fnkeys_enabled ? omnibook_fnkeys_on() : 0);
-       return retval;
-}
-
-static int omnibook_hotkeys_suspend(void)
+static int omnibook_hotkeys_resume(struct omnibook_operation *io_op)
 {
-       int retval = 0;
-       retval = (omnibook_hotkeys_enabled ? omnibook_hotkeys_off() : 0);
-       if (omnibook_ectype & TSM30X)
-               retval = (omnibook_fnkeys_enabled ? omnibook_fnkeys_off() : 0);
-       return retval;
+       int retval;
+       retval = io_op->backend->hotkeys_set(io_op, saved_state);
+       return min(retval,0);
 }
 
-static int omnibook_hotkeys_enable(void)
+/*
+ * Save state and disable hotkeys upon suspend (FIXME is the disabling required ?)
+ */
+static int omnibook_hotkeys_suspend(struct omnibook_operation *io_op)
 {
        int retval = 0;
 
-       if (!omnibook_hotkeys_enabled )
-               retval = omnibook_hotkeys_on();
-       if ((!omnibook_fnkeys_enabled) && ( omnibook_ectype & TSM30X ))
-               retval = omnibook_fnkeys_on();
+       retval = omnibook_hotkeys_get(io_op, &saved_state);
+       if(retval < 0)
+               return retval;
 
-       return retval;
+       retval = io_op->backend->hotkeys_set(io_op, HKEY_OFF);
+       if(retval < 0)
+               return retval;
+       
+       return 0;
 }
 
-static int omnibook_hotkeys_disable(void)
-{
-       int retval = 0;
-
-       if (omnibook_hotkeys_enabled )
-               retval = omnibook_hotkeys_off();
-       if (omnibook_fnkeys_enabled && ( omnibook_ectype & TSM30X ))
-               retval = omnibook_fnkeys_off();
-
-       return retval;
-}
+static const char pretty_name[][27] = {
+       "Onetouch buttons",
+       "Multimedia hotkeys are",
+       "Fn hotkeys are",
+       "Stick key is",
+       "Press Fn twice to lock is",
+       "Dock events are",
+       "Fn + F5 hotkey is"
+};
 
-static int omnibook_hotkeys_read(char *buffer)
+static int omnibook_hotkeys_read(char *buffer,struct omnibook_operation *io_op)
 {
        int len = 0;
-
-       len += sprintf(buffer + len, "Hotkey buttons are %s\n",
-                     (omnibook_hotkeys_enabled) ? "enabled" : "disabled");
-
-       if (omnibook_ectype & TSM30X )
-               len += sprintf(buffer + len, "Fn keys are %s\n",
-                           (omnibook_fnkeys_enabled) ? "enabled" : "disabled");
-       return len;
-}
-
-static int omnibook_hotkeys_write(char *buffer)
-{
-       int retval = 0;
-       switch (*buffer) {
-       case '0':
-               retval = omnibook_hotkeys_disable();
-               break;
-       case '1':
-               retval = omnibook_hotkeys_enable();
-               break;
-       default:
-               retval = -EINVAL;
+       int read_capability, write_capability;
+       unsigned int read_state, mask;
+
+       read_capability = omnibook_hotkeys_get(io_op, &read_state);
+       if(read_capability < 0)
+               return read_capability;
+
+       write_capability = omnibook_hotkeys_set(io_op, read_state);
+       if(write_capability < 0)
+               return write_capability;
+
+       for( mask = DISPLAY_LCD_ON ; mask <= HKEY_FNF5; mask = mask << 1) {
+       /* we assume write capability or read capability imply support */
+                if( (read_capability | write_capability ) & mask )
+                       len += sprintf(buffer + len, "%s %s.\n", 
+                               pretty_name[ ffs(mask) - 1 ],
+                               ( read_state & mask ) ? "enabled" : "disabled");
        }
-       return retval;
+       return len;
 }
 
-static int omnibook_hotkeys_init(void)
+static int omnibook_hotkeys_write(char *buffer,struct omnibook_operation *io_op)
 {
-       int retval = 0;
+       unsigned int state;     
+       char *endp;
        
-       if ((omnibook_ectype & TSM30X) && omnibook_cdimode_init()) {
-               retval = -ENODEV;
-               goto out;
+       if (strncmp(buffer, "off", 3) == 0)
+               omnibook_hotkeys_set(io_op, HKEY_OFF);
+       else if (strncmp(buffer, "on", 2) == 0)
+               omnibook_hotkeys_set(io_op, HKEY_ON);
+       else {
+               state = simple_strtoul(buffer, &endp, 16);
+               if (endp == buffer)
+                       return -EINVAL;
+               else
+                       omnibook_hotkeys_set(io_op, state);
        }
-                       
-       retval = omnibook_hotkeys_enable();
+       return 0;
+}
 
-out:
-       return retval;
+static int __init omnibook_hotkeys_init(struct omnibook_operation *io_op)
+{      
+       printk(O_INFO "Enabling all hotkeys.\n");
+       return omnibook_hotkeys_set(io_op, HKEY_ON);
 }
 
-static void omnibook_hotkeys_cleanup(void)
+static void __exit omnibook_hotkeys_cleanup(struct omnibook_operation *io_op)
 {
-       omnibook_hotkeys_disable();
-       
-       if (omnibook_ectype & TSM30X)
-               omnibook_cdimode_exit();
+       printk(O_INFO "Disabling all hotkeys.\n");
+       omnibook_hotkeys_set(io_op, HKEY_OFF);
 }
 
-static struct omnibook_feature __declared_feature hotkeys_feature = {
+static struct omnibook_tbl hotkey_table[] __initdata = {
+       { XE3GF|XE3GC|OB500|OB510|OB6000|OB6100|XE4500|AMILOD|TSP10, {KBC,}},
+       { TSM30X,       {CDI,}},
+       { TSM40,        {SMI,}},
+       { 0,}
+};
+
+static struct omnibook_feature __declared_feature hotkeys_driver = {
         .name = "hotkeys",
         .enabled = 1,
         .read = omnibook_hotkeys_read,
@@ -203,9 +172,10 @@ static struct omnibook_feature __declared_feature hotkeys_feature = {
         .exit = omnibook_hotkeys_cleanup,
         .suspend = omnibook_hotkeys_suspend,
         .resume = omnibook_hotkeys_resume,
-        .ectypes = XE3GF|XE3GC|OB500|OB510|OB6000|OB6100|XE4500|AMILOD|TSP10|TSM30X,
+        .ectypes = XE3GF|XE3GC|OB500|OB510|OB6000|OB6100|XE4500|AMILOD|TSP10|TSM30X|TSM40,
+        .tbl = hotkey_table,
 };
 
-module_param_named(hotkeys, hotkeys_feature.enabled, int, S_IRUGO);
+module_param_named(hotkeys, hotkeys_driver.enabled, int, S_IRUGO);
 MODULE_PARM_DESC(hotkeys, "Use 0 to disable, 1 to enable hotkeys handling");
 /* End of file */
diff --git a/info.c b/info.c
index 4049d88b8e779dc2bb44d89616569e361f4064f5..386f7f930f667c04f23b326dd30bd807f5269f13 100644 (file)
--- a/info.c
+++ b/info.c
  * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
  */
 
-#ifdef OMNIBOOK_STANDALONE
 #include "omnibook.h"
-#else
-#include <linux/omnibook.h>
-#endif
 
 #include <linux/dmi.h>
 #include <linux/version.h>
 
-static int omnibook_version_read(char *buffer)
+static int omnibook_version_read(char *buffer,struct omnibook_operation *io_op)
 {
        int len = 0;
 
@@ -33,7 +29,7 @@ static int omnibook_version_read(char *buffer)
        return len;
 }
 
-static int omnibook_dmi_read(char *buffer)
+static int omnibook_dmi_read(char *buffer,struct omnibook_operation *io_op)
 {
        int len = 0;
 
@@ -70,19 +66,19 @@ static int omnibook_dmi_read(char *buffer)
        return len;
 }
 
-static struct omnibook_feature __declared_feature version_feature = {
+static struct omnibook_feature __declared_feature version_driver = {
         .name = "version",
         .enabled = 1,
         .read = omnibook_version_read,
 };
 
-static struct omnibook_feature __declared_feature dmi_feature = {
+static struct omnibook_feature __declared_feature dmi_driver = {
         .name = "dmi",
         .enabled = 1,
         .read = omnibook_dmi_read,
 };
 
-module_param_named(dmi, dmi_feature.enabled, int, S_IRUGO);
+module_param_named(dmi, dmi_driver.enabled, int, S_IRUGO);
 MODULE_PARM_DESC(dmi, "Use 0 to disable, 1 to enable DMI informations display support");
 
 /* End of file */
diff --git a/init.c b/init.c
index 99721860229398cd4f1843cd5b4ecc8153ba2a72..b39face3ae8d5889a873fde237489ccb2fa91fad 100644 (file)
--- a/init.c
+++ b/init.c
  * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
  */
 
-#ifdef OMNIBOOK_STANDALONE
 #include "omnibook.h"
-#else
-#include <linux/omnibook.h>
-#endif
 
 #include <linux/proc_fs.h>
 #include <linux/dmi.h>
@@ -38,7 +34,8 @@
 
 static struct proc_dir_entry *omnibook_proc_root = NULL;
 
-int omnibook_ectype = NONE;
+enum omnibook_ectype_t omnibook_ectype = NONE;
+
 static char* laptop_model __initdata;
 
 static int omnibook_userset = 0;
@@ -88,8 +85,8 @@ static struct platform_device omnibook_device = {
 static struct omnibook_feature *omnibook_available_feature;
 
 /* Delimiters of the .features section wich holds all the omnibook_feature structs */
-extern struct omnibook_feature _features_start[];
-extern struct omnibook_feature _features_end[];
+extern struct omnibook_feature _start_features_driver[];
+extern struct omnibook_feature _end_features_driver[];
 
 static int __init dmi_matched(struct dmi_system_id *dmi)
 {
@@ -113,7 +110,7 @@ static int procfile_read_dispatch(char *page, char **start, off_t off,
        if (!feature || !feature->read)
                return -EINVAL;
 
-       len = feature->read(page);
+       len = feature->read(page,feature->io_op);
        if (len < 0)
                return len;
 
@@ -155,7 +152,7 @@ static int procfile_write_dispatch(struct file *file,
        /* Make sure the string is \0 terminated */
        kernbuf[count] = '\0';
 
-       retval = feature->write(kernbuf);
+       retval = feature->write(kernbuf,feature->io_op);
        if (retval == 0)
                retval = count;
 
@@ -164,23 +161,71 @@ static int procfile_write_dispatch(struct file *file,
        return retval;
 }
 
+/*
+ * Match an ectype and return pointer to corresponding omnibook_operation.
+ * Also make corresponding backend initialisation if necessary, and skip
+ * to the next entry if it fails.
+ */
+static struct omnibook_operation * omnibook_backend_match(struct omnibook_tbl *tbl)
+{
+       int i;
+       struct omnibook_operation *matched = NULL;
+
+       for (i = 0; tbl[i].ectypes ; i++) {
+               if (omnibook_ectype & tbl[i].ectypes) {
+                       if(tbl[i].io_op.backend->init && tbl[i].io_op.backend->init(&tbl[i].io_op)) {
+                               dprintk("Backend %s init failed, skipping entry.\n", tbl[i].io_op.backend->name);
+                               continue;
+                       } 
+                       matched = &tbl[i].io_op;
+                       dprintk("Returning table entry n°%i.\n",i);
+                       break;
+               }
+       }
+       return matched;
+}
+
+
 /* 
  * Initialise a feature and add it to the linked list of active features
  */
 static int __init omnibook_init(struct omnibook_feature *feature)
 {
-       int retval;
+       int retval = 0;
        mode_t pmode;
        struct proc_dir_entry *proc_entry;
+       struct omnibook_operation *op;
 
        if (!feature)
                return -EINVAL;
 
-       if (feature->init) {
-               retval = feature->init();
-               if (retval)
+/*
+ * Select appropriate backend for feature operations
+ * We copy the io_op field so the tbl can be initdata
+ */
+       if(feature->tbl) {
+               dprintk("begin table match of %s feature.\n",feature->name);
+               op = omnibook_backend_match(feature->tbl);
+               if(!op) {
+                       dprintk("match failed: disabling %s.\n",feature->name);
                        return -ENODEV;
-       }
+               }
+               feature->io_op = kmalloc(sizeof(struct omnibook_operation),GFP_KERNEL);
+               if (!feature->io_op)
+                       return -ENOMEM;
+               memcpy(feature->io_op, op, sizeof(struct omnibook_operation));
+       } else
+               dprintk("%s feature has no backend table, io_op not initialized.\n",feature->name);
+
+/*
+ * Specific feature init code
+ */
+       if (feature->init && (retval = feature->init(feature->io_op)))
+               goto err;
+
+/*
+ * procfs file setup
+ */
        if (feature->name && feature->read) {
                pmode = S_IFREG | S_IRUGO;
                if (feature->write) {
@@ -189,21 +234,22 @@ static int __init omnibook_init(struct omnibook_feature *feature)
                                pmode |= S_IWUGO;
                }
                /*
-                * Special case for apmemu
+                * FIXME: Special case for apmemu (not under /proc/omnibook)
                 */
-               if (feature->proc_entry) {
+               if (feature->proc_entry)
                        proc_entry = create_proc_entry(feature->proc_entry, pmode,
                                                      NULL);
-               } else {
-               proc_entry = create_proc_entry(feature->name, pmode,
+               else
+                       proc_entry = create_proc_entry(feature->name, pmode,
                                               omnibook_proc_root);
-               }
+
                if (!proc_entry) {
                        printk(O_ERR
                               "Unable to create proc entry %s\n",feature->name);
                        if (feature->exit)
-                               feature->exit();
-                       return -ENOENT;
+                               feature->exit(feature->io_op);
+                       retval = -ENOENT;
+                       goto err;
                }
                proc_entry->data = feature;
                proc_entry->read_proc = &procfile_read_dispatch;
@@ -213,6 +259,9 @@ static int __init omnibook_init(struct omnibook_feature *feature)
        }
        list_add_tail(&feature->list, &omnibook_available_feature->list);
        return 0;
+err:
+       kfree(feature->io_op);
+       return retval;
 }
 
 
@@ -233,9 +282,9 @@ static int __init omnibook_probe(struct platform_device *dev)
                return -ENOMEM;
        INIT_LIST_HEAD(&omnibook_available_feature->list);
        
-       for (i=0; i < _features_end - _features_start; i++ ) {
+       for (i=0; i < _end_features_driver - _start_features_driver; i++ ) {
                
-               feature = &_features_start[i];
+               feature = &_start_features_driver[i];
 
                if (!feature->enabled)  
                        continue;
@@ -266,12 +315,17 @@ static int __exit omnibook_remove(struct platform_device *dev)
        list_for_each_safe(p, n, &omnibook_available_feature->list) {
                feature = list_entry(p, struct omnibook_feature, list);
                list_del(p);
-               if (feature->exit)
-                       feature->exit();
+               /* Feature specific cleanup */
+                if (feature->exit)
+                        feature->exit(feature->io_op);
+               /* Generic backend cleanup */
+               if (feature->io_op && feature->io_op->backend->exit)
+                       feature->io_op->backend->exit(feature->io_op);
                if (feature->proc_entry)
                        remove_proc_entry(feature->proc_entry, NULL);
                else if (feature->name)
                        remove_proc_entry(feature->name, omnibook_proc_root);
+               kfree(feature->io_op);
        }
        kfree(omnibook_available_feature);
        
@@ -290,7 +344,7 @@ static int omnibook_suspend(struct platform_device *dev, pm_message_t state)
        list_for_each(p, &omnibook_available_feature->list) {
                feature = list_entry(p, struct omnibook_feature, list);
                if (feature->suspend) {
-                       retval = feature->suspend();
+                       retval = feature->suspend(feature->io_op);
                        if (!retval)
                                printk(O_ERR
                                        "Unable to suspend the %s feature",
@@ -312,7 +366,7 @@ static int omnibook_resume(struct platform_device *dev)
        list_for_each(p, &omnibook_available_feature->list) {
                feature = list_entry(p, struct omnibook_feature, list);
                if (feature->resume) {
-                       retval = feature->resume();
+                       retval = feature->resume(feature->io_op);
                        if (!retval)
                                printk(O_ERR
                                       "Unable to resume the %s feature",
@@ -353,7 +407,7 @@ static int __init omnibook_module_init(void)
            
        if (omnibook_ectype != NONE)
                printk(O_WARN
-                      "Forced load with EC firmware type %i.\n", ffs(omnibook_ectype));
+                      "Forced load with EC type %i.\n", ffs(omnibook_ectype));
        else if ( dmi_check_system(omnibook_ids) ) 
                printk(O_INFO "%s detected.\n", laptop_model);
        else
diff --git a/lcd.c b/lcd.c
index 2e4c2f7c61f7e727a93589a2782931fcf40447bf..3a06a0b2b9d9d449744475a5a705572adcb2a4fc 100644 (file)
--- a/lcd.c
+++ b/lcd.c
  * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
  */
 
-#ifdef OMNIBOOK_STANDALONE
 #include "omnibook.h"
-#else
-#include <linux/omnibook.h>
-#endif
-
 #include <linux/err.h>
 
 #ifdef CONFIG_OMNIBOOK_BACKLIGHT
@@ -30,7 +25,7 @@
 
 #include "ec.h"
 
-static int omnibook_max_brightness;
+static unsigned int omnibook_max_brightness;
 
 #ifdef CONFIG_OMNIBOOK_BACKLIGHT
 
@@ -47,24 +42,15 @@ static struct backlight_properties omnibookbl_data = {
 
 #endif
 
-static const struct omnibook_io_operation lcd_io_table[] = {
-       { TSM30X,               CDI, TSM70_LCD_READ, TSM70_LCD_WRITE, 0},
-       { XE3GF|TSP10|TSM40,    EC, XE3GF_BRTS, XE3GF_BRTS, XE3GF_BRTS_MASK},
-       { XE3GC,                EC, XE3GC_BTVL, XE3GC_BTVL, XE3GC_BTVL_MASK},
-       { AMILOD,               EC, AMILOD_CBRG, AMILOD_CBRG, XE3GC_BTVL_MASK},
-       { TSA105,               EC, A105_BNDT, A105_BNDT, A105_BNDT_MASK},
-       { 0,}
-};
-
-static struct omnibook_io_operation *lcd_io;
-
 #ifdef CONFIG_OMNIBOOK_BACKLIGHT
 static int omnibook_get_backlight(struct backlight_device *bd)
 {
        int retval = 0;
+       struct omnibook_operation *io_op;
        u8 brgt;
        
-       retval = omnibook_io_read(lcd_io, &brgt);
+       io_op = class_get_devdata(&bd->class_dev);
+       retval = io_op->backend->byte_read(io_op, &brgt);
        if (!retval)
                retval = brgt;
        
@@ -73,27 +59,29 @@ static int omnibook_get_backlight(struct backlight_device *bd)
 
 static int omnibook_set_backlight(struct backlight_device *bd)
 {
-       int intensity = bd->props->brightness;
-       return omnibook_io_write(lcd_io, intensity);
+       u8 intensity = bd->props->brightness;
+       struct omnibook_operation *io_op;
+
+       io_op = class_get_devdata(&bd->class_dev);
+       return io_op->backend->byte_write(io_op, intensity);
 }
 #endif
 
-static int omnibook_brightness_read(char *buffer)
+static int omnibook_brightness_read(char *buffer,struct omnibook_operation *io_op)
 {
        int len = 0;
-       int retval;
        u8 brgt;
 
-       retval = omnibook_io_read(lcd_io, &brgt);
-       if (retval)
-               return retval;
+       io_op->backend->byte_read(io_op, &brgt);
 
-       len += sprintf(buffer + len, "LCD brightness: %2d\n", brgt);
+       len += sprintf(buffer + len, "LCD brightness: %2d (max value: %d)\n",
+                       brgt,
+                       omnibook_max_brightness);
 
        return len;
 }
 
-static int omnibook_brightness_write(char *buffer)
+static int omnibook_brightness_write(char *buffer,struct omnibook_operation *io_op)
 {
        int brgt = 0;
        char *endp;
@@ -103,21 +91,21 @@ static int omnibook_brightness_write(char *buffer)
        else if (strncmp(buffer, "on", 2) == 0)
                omnibook_lcd_blank(0);
        else {
-               brgt = simple_strtol(buffer, &endp, 10);
+               brgt = simple_strtoul(buffer, &endp, 10);
                if ((endp == buffer) || (brgt < 0) || (brgt > omnibook_max_brightness))
                        return -EINVAL;
                else
-                       omnibook_io_write(lcd_io, brgt);
+                       io_op->backend->byte_write(io_op, brgt);
        }
        return 0;
 }
 
-static int omnibook_brightness_init(void)
+static int __init omnibook_brightness_init(struct omnibook_operation *io_op)
 {
        /*
         * FIXME: What is exactly de max value for each model ?
         * I know that it's 7 for the TSM30X, TSM40 and TSA105
-        * and previous versions of this driver assumed it was 10 for
+        * and previous versions of this driver (wrongly) assumed it was 10 for
         * all models.
         * 
         * TSM30X
@@ -126,19 +114,16 @@ static int omnibook_brightness_init(void)
         */
        if (omnibook_ectype & (TSM30X|TSM40|TSA105) )
                omnibook_max_brightness = 7;
-       else
+       else {
                omnibook_max_brightness = 10;
-               
-       printk(O_INFO "LCD brightness is between 0 and %i.\n",
-               omnibook_max_brightness);
-       
-       if (!(lcd_io = omnibook_io_match(lcd_io_table)))
-               return -ENODEV;
+               printk(O_WARN "Assuming that LCD brightness is between 0 and %i,\n", omnibook_max_brightness);
+               printk(O_WARN "please contact http://sourceforge.net/projects/omnibook to confirm.\n");
+       }
 
 #ifdef CONFIG_OMNIBOOK_BACKLIGHT
        omnibookbl_data.max_brightness = omnibook_max_brightness;
            omnibook_backlight_device =
-           backlight_device_register(OMNIBOOK_MODULE_NAME, NULL, &omnibookbl_data);
+           backlight_device_register(OMNIBOOK_MODULE_NAME, (void *) io_op, &omnibookbl_data);
        if (IS_ERR(omnibook_backlight_device)) {
                printk(O_ERR "Unable to register as backlight device.\n");
                return -ENODEV;
@@ -147,16 +132,24 @@ static int omnibook_brightness_init(void)
        return 0;
 }
 
-static void omnibook_brightness_cleanup(void)
+static void __exit omnibook_brightness_cleanup(struct omnibook_operation *io_op)
 {
 #ifdef CONFIG_OMNIBOOK_BACKLIGHT
        backlight_device_unregister(omnibook_backlight_device);
 #endif
-
-       if(lcd_io->type == CDI)
-               omnibook_cdimode_exit();
 }
-static struct omnibook_feature __declared_feature lcd_feature = {
+
+static struct omnibook_tbl lcd_table[] __initdata = {
+       { TSM30X,               {CDI,TSM70_LCD_READ,TSM70_LCD_WRITE,0,0,0}},
+       { TSM40,                {SMI,SMI_GET_LCD_BRIGHTNESS,SMI_SET_LCD_BRIGHTNESS,0,0,0}},
+       { XE3GF|TSP10|TSM30X,   SIMPLE_BYTE(EC,XE3GF_BRTS,XE3GF_BRTS_MASK)},
+       { XE3GC,                SIMPLE_BYTE(EC,XE3GC_BTVL,XE3GC_BTVL_MASK)},
+       { AMILOD,               SIMPLE_BYTE(EC,AMILOD_CBRG,XE3GC_BTVL_MASK)},
+       { TSA105,               SIMPLE_BYTE(EC,A105_BNDT,A105_BNDT_MASK)},
+       { 0,}
+};
+
+static struct omnibook_feature __declared_feature lcd_driver = {
         .name = "lcd",
         .enabled = 1,
         .read = omnibook_brightness_read,
@@ -164,9 +157,10 @@ static struct omnibook_feature __declared_feature lcd_feature = {
         .init = omnibook_brightness_init,
         .exit = omnibook_brightness_cleanup,
         .ectypes = XE3GF|XE3GC|AMILOD|TSP10|TSM30X|TSM40|TSA105,
+        .tbl = lcd_table,
 };
 
-module_param_named(lcd, lcd_feature.enabled, int, S_IRUGO);
+module_param_named(lcd, lcd_driver.enabled, int, S_IRUGO);
 MODULE_PARM_DESC(lcd, "Use 0 to disable, 1 to enable to LCD brightness support");
 
 /* End of file */
index 3d046dcf80b135e6834c350d1dcd41172b541c0f..445d43714e83882d3f61932fabbbb620675a0588 100644 (file)
@@ -1,19 +1,21 @@
-diff -Nru linux-2.6.17/arch/i386/Kconfig linux-2.6.17-omnibook/arch/i386/Kconfig
 --- linux-2.6.17/arch/i386/Kconfig     2006-06-18 03:49:35.000000000 +0200
-+++ linux-2.6.17-omnibook/arch/i386/Kconfig    2006-08-04 17:09:26.680717114 +0200
-@@ -334,6 +334,42 @@
++++ linux-2.6.17-omke/arch/i386/Kconfig        2006-09-07 19:16:40.994446032 +0200
+@@ -334,6 +334,54 @@
          Say Y if you intend to run this kernel on a Toshiba portable.
          Say N otherwise.
  
 +config OMNIBOOK
-+      tristate "HP (omnibook) laptop support"
-+      help
-+          This adds a driver to support some features of laptops manufactured
-+          by Compal Electronics, Inc as ODM such as HP OmniBook, Pavilion,
-+          Compal ACL00 and Toshiba Satellite (wich have Pheonix BIOS and is
-+          not supported by Toshiba driver) and Acer Aspire series laptops.
++       tristate "HP Omnibook and Toshiba laptop support"
++       depends on PCI && X86 && EXPERIMENTAL
++       ---help---
++          This adds a driver to support some features of laptops such as 
++        HP OmniBook, Pavilion, Compal ACL00 ,Toshiba Satellite which have 
++        a Phoenix BIOS and are not supported by other Toshiba drivers
++          and some Acer Aspire series laptops.
 +
-+          For this driver see the site at: <http://www.sf.net/projects/omke/>.
++        Most of these are manufactured by Compal Electronics, Inc as ODM
++          
++        See  <http://www.sf.net/projects/omnibook/>.
 +
 +          Say Y if you intend to run this kernel on a supported portable.
 +          Say N otherwise.
@@ -22,41 +24,50 @@ diff -Nru linux-2.6.17/arch/i386/Kconfig linux-2.6.17-omnibook/arch/i386/Kconfig
 +          inserted in and removed from the running kernel whenever you want).
 +          If you want to compile it as a module, say M here and read
 +          Documentation/modules.txt.
-+          The module is called omnibook.ko because originally it was intended
-+          to support HP OmniBooks only.
++          
++        The module is called omnibook.ko due to historical reasons.
 +
-+config OMNIBOOK_APMEMU
-+      bool "HP omnibook APM emulation"
-+      depends on OMNIBOOK
-+      help
-+        Enable APM emulation by default in the omnibook module. This is
-+        mainly for laptops that don't have perfect ACPI support for battery
-+        level monitoring.
++config OMNIBOOK_LEGACY
++       bool "HP omnibook legacy features"
++       depends on OMNIBOOK
++       default y if !ACPI 
++       ---help---
++       This option enable support for some legacy features of the omnibook
++         driver, including:
++         * /proc/apm emulation.
++       * non-ACPI support code.
++       * AC adapter and Battery monitoring default enabling.
++       This is mainly for laptops with no or broken ACPI support.
++
++       If you are unsure, say N.
 +
 +config OMNIBOOK_BACKLIGHT
-+      bool "HP omnibook backlight support"
-+      depends on OMNIBOOK
-+      select BACKLIGHT_CLASS_DEVICE
-+      help
-+        Enable registration of the omnibook module as a backlight device.
-+        This allow query and control of the LCD brightness via sysfs.
++       bool "HP omnibook backlight support"
++       depends on OMNIBOOK
++       select BACKLIGHT_CLASS_DEVICE
++       default y
++       ---help---
++         Enable registration of the omnibook module as a backlight device.
++         This allow query and control of the LCD brightness via sysfs.
++       
++       If you are unsure, say Y.
 +
  config I8K
        tristate "Dell laptop support"
        ---help---
-diff -Nru linux-2.6.17/drivers/misc/Makefile linux-2.6.17-omnibook/drivers/misc/Makefile
+diff -Nru linux-2.6.17/drivers/misc/Makefile linux-2.6.17-omke/drivers/misc/Makefile
 --- linux-2.6.17/drivers/misc/Makefile 2006-06-18 03:49:35.000000000 +0200
-+++ linux-2.6.17-omnibook/drivers/misc/Makefile        2006-08-04 17:09:26.681716962 +0200
++++ linux-2.6.17-omke/drivers/misc/Makefile    2006-09-07 14:16:09.775221578 +0200
 @@ -5,3 +5,5 @@
  
  obj-$(CONFIG_IBM_ASM) += ibmasm/
  obj-$(CONFIG_HDPU_FEATURES)   += hdpuftrs/
 +obj-$(CONFIG_OMNIBOOK) += omnibook/
 +
-diff -Nru linux-2.6.17/drivers/misc/omnibook/Makefile linux-2.6.17-omnibook/drivers/misc/omnibook/Makefile
+diff -Nru linux-2.6.17/drivers/misc/omnibook/Makefile linux-2.6.17-omke/drivers/misc/omnibook/Makefile
 --- linux-2.6.17/drivers/misc/omnibook/Makefile        1970-01-01 01:00:00.000000000 +0100
-+++ linux-2.6.17-omnibook/drivers/misc/omnibook/Makefile       2006-08-04 17:09:26.684716506 +0200
-@@ -0,0 +1,27 @@
++++ linux-2.6.17-omke/drivers/misc/omnibook/Makefile   2006-09-07 18:15:18.927168481 +0200
+@@ -0,0 +1,28 @@
 +
 +# Makefile -- makefile for the HP OmniBook support module
 +
@@ -81,8 +92,9 @@ diff -Nru linux-2.6.17/drivers/misc/omnibook/Makefile linux-2.6.17-omnibook/driv
 +EXTRA_LDFLAGS += $(src)/sections.lds
 +obj-$(CONFIG_OMNIBOOK) += omnibook.o
 +
-+omnibook-objs := ac.o battery.o blank.o display.o dock.o \
-+ec.o fan.o fan_policy.o init.o lcd.o onetouch.o \
-+temperature.o touchpad.o dump.o info.o \
-+apmemu.o muteled.o
-+
++omnibook-objs := init.o ec.o compal.o acpi.o nbsmi.o \
++ac.o apmemu.o battery.o blank.o bluetooth.o display.o dock.o dump.o \
++fan.o fan_policy.o hotkeys.o info.o lcd.o muteled.o temperature.o \
++touchpad.o wireless.o
+
+
index 5938a62199e648ba2d530986a3a8dc41f0acb9e2..620c4bb1c0872f5ef1b2bdd147b4bd1006a96dcd 100644 (file)
--- a/muteled.c
+++ b/muteled.c
  * General Public License for more details.
  *
  * Written by Thomas Perl <thp@perli.net>, 2006
+ * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
  */
 
-#ifdef OMNIBOOK_STANDALONE
 #include "omnibook.h"
-#else
-#include <linux/omnibook.h>
-#endif
-
 #include "ec.h"
 
 /* There is no information about reading MUTE LED status */
 static int omnibook_muteled_enabled = 0;
 
-static int omnibook_muteled_on(void)
-{
-       if (omnibook_kbc_command(OMNIBOOK_KBC_CONTROL_CMD, OMNIBOOK_KBC_CMD_MUTELED_ON)) {
-               printk(KERN_ERR "%s: failed muteled on command.\n", OMNIBOOK_MODULE_NAME);
-               return -EIO;
-       }
-        omnibook_muteled_enabled = 1;
-       return 0;
-}
-
-static int omnibook_muteled_off(void)
+static int omnibook_muteled_set(struct omnibook_operation *io_op, int status)
 {
-       if (omnibook_kbc_command(OMNIBOOK_KBC_CONTROL_CMD, OMNIBOOK_KBC_CMD_MUTELED_OFF)) {
-               printk(KERN_ERR "%s: failed muteled off command.\n", OMNIBOOK_MODULE_NAME);
+       if (omnibook_toggle(io_op, !!status)) {
+               printk(O_ERR "Failed muteled %s command.\n", status ? "on" : "off");
                return -EIO;
        }
-        omnibook_muteled_enabled = 0;
        return 0;
 }
 
-
-static int omnibook_muteled_disable(void)
-{
-        omnibook_muteled_off();
-        return 0;
-}
-
-static int omnibook_muteled_enable(void)
-{
-        omnibook_muteled_on();
-        return 0;
-}
-
-static int omnibook_muteled_read(char *buffer)
+/*
+ * Hardware query is unsupported, reading is unreliable.
+ */
+static int omnibook_muteled_read(char *buffer,struct omnibook_operation *io_op)
 {
        int len = 0;
 
-       len += sprintf(buffer+len, "The mute LED is %s\n", (omnibook_muteled_enabled) ? "on" : "off");
+       len += sprintf(buffer+len, "Last mute LED action was an %s command.\n", 
+                       (omnibook_muteled_enabled) ? "on" : "off");
 
        return len;
 }
 
-static int omnibook_muteled_write(char *buffer)
+static int omnibook_muteled_write(char *buffer,struct omnibook_operation *io_op)
 {
-       int retval;     
-       
-       switch (*buffer) {
-       case '0':
-               if ((retval = omnibook_muteled_disable()));
-                       return retval;
-               break;
-       case '1':
-               if ((retval = omnibook_muteled_enable()));
-                       return retval;
-               break;
-       default:
+       int cmd;        
+
+       if ( *buffer == '0' || *buffer == '1') {
+               cmd = *buffer - '0';
+               if(!omnibook_muteled_set(io_op, cmd)) {
+                       omnibook_muteled_enabled = cmd;
+                       printk(O_INFO "Switching mute LED to %s state.\n", 
+                               cmd ? "on" : "off");
+               }
+       } else {
                return -EINVAL;
        }
        return 0;
 }
 
+static int omnibook_muteled_resume(struct omnibook_operation *io_op)
+{      
+       return omnibook_muteled_set(io_op,omnibook_muteled_enabled);            
+}
+
+static struct omnibook_tbl muteled_table[] __initdata = {
+       { XE4500, COMMAND(KBC,OMNIBOOK_KBC_CMD_MUTELED_ON,OMNIBOOK_KBC_CMD_MUTELED_OFF)},
+       { 0,}
+};
 
-static struct omnibook_feature __declared_feature muteled_feature = {
+static struct omnibook_feature __declared_feature muteled_driver = {
         .name = "muteled",
         .enabled = 1,
         .read = omnibook_muteled_read,
         .write = omnibook_muteled_write,
+        .resume = omnibook_muteled_resume,
         .ectypes = XE4500,
+        .tbl = muteled_table,
 };
 
-module_param_named(muteled, muteled_feature.enabled, int, S_IRUGO);
+module_param_named(muteled, muteled_driver.enabled, int, S_IRUGO);
 MODULE_PARM_DESC(muteled, "Use 0 to disable, 1 to enable 'Audo Mute' LED control");
 
diff --git a/nbsmi.c b/nbsmi.c
new file mode 100644 (file)
index 0000000..7734d73
--- /dev/null
+++ b/nbsmi.c
@@ -0,0 +1,595 @@
+/*
+ * nbsmi.c -- Toshiba SMI low-level acces code
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * Written by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ *
+ * Sources of inspirations for this code were:
+ * -Toshiba via provided hardware specification
+ * -Thorsten Zachmann with the 's1bl' project
+ * -Frederico Munoz with the 'tecra_acpi' project
+ * Thanks to them
+ */
+#include "omnibook.h"
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16))
+#include <asm/semaphore.h>
+#define DEFINE_MUTEX(lock)             DECLARE_MUTEX(lock)
+#define mutex_lock(lock)               down(lock)
+#define mutex_lock_interruptible(lock) down_interruptible(lock)
+#define mutex_unlock(lock)             up(lock)
+#else
+#include <linux/mutex.h>
+#endif
+
+#include <linux/preempt.h>
+#include <linux/pci.h>
+#include <linux/kref.h>
+#include <asm/io.h>
+#include <asm/mc146818rtc.h>
+#include "ec.h"
+
+/*
+ * ATI's IXP PCI-LPC bridge
+ */
+#define PCI_DEVICE_ID_ATI_SB400 0x4377
+
+#define INTEL_PMBASE   0x40
+#define INTEL_GPE0_EN  0x2c
+
+#define BUFFER_SIZE    0x20
+#define INTEL_OFFSET   0x60
+#define        INTEL_SMI_PORT  0xb2 /* APM_CNT port in INTEL ICH specs */
+#define ATI_OFFSET     0xef
+#define        ATI_SMI_PORT    0xb0
+
+#define        EC_INDEX_PORT   0x300
+#define EC_DATA_PORT   0x301
+
+/* Masks decode for GetAeral */
+#define WLEX_MASK      0x4
+#define WLAT_MASK      0x8
+#define BTEX_MASK      0x1
+#define BTAT_MASK      0x2
+
+/* 
+ * We serialize access to this backend using a mutex
+ * Crital sections around #SMI triggering are run atomically using a spinlock 
+ */
+static DEFINE_MUTEX(smi_lock);
+static DEFINE_SPINLOCK(smi_spinlock);
+
+/*
+ * Private data of this backend
+ */
+static struct kref *refcount;
+static struct pci_dev *lpc_bridge;     /* Southbridge chip ISA bridge/LPC interface PCI device */
+static u8 start_offset;
+static int already_failed = 0;         /* Backend init already failed at leat once */
+
+/*
+ * Possible list of supported southbridges
+ * Here mostly to implement a more or less clean PCI probing
+ * Works only because of previous DMI probing.
+ * It's in compal.c
+ */
+extern const struct pci_device_id lpc_bridge_table[];
+
+/*
+ * Since we are going to trigger an SMI, all registers may be mangled in the
+ * process. So we save and restore all registers and eflags in the stack.
+ * We also disable preemtion and IRQs upon SMI call.
+ */
+static inline void save_all_regs_flag(void)
+{      
+       spin_lock_irq(&smi_spinlock);
+       __asm__ __volatile__("pushal ; pushfl");
+}
+
+static inline void restore_all_regs_flag(void)
+{
+       __asm__ __volatile__("popfl; popal"
+                            :
+                            : 
+                            : "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi");
+       spin_unlock_irq(&smi_spinlock); 
+}
+
+static inline void ati_do_smi_call(int *retval, u16 function)
+{
+       outw( function, ATI_SMI_PORT ); /* Call to SMI */
+       *retval = inw(ATI_SMI_PORT + 1);
+}
+
+static inline void intel_do_smi_call(int *retval, u16 function, u32 sci_en)
+{
+       u32 state;
+       
+       state = inl(sci_en);
+       outl( 0, sci_en );
+
+       outw( function, INTEL_SMI_PORT ); /* Call to SMI */
+       
+/*
+ * Success/Failure state in now stored in eax
+ */
+       __asm__ __volatile__("movl %%eax, %0"
+                            :
+                            : "m" (retval)
+                           );
+
+       outl( state, sci_en );  
+}
+
+
+static int nbsmi_smi_command(u16 function,const u8 *inputbuffer, u8 *outputbuffer)
+{
+       u32 retval;
+       u32 sci_en;
+       int count;
+       
+       for(count = 0; count < BUFFER_SIZE; count++) {
+               outb( count + start_offset, RTC_PORT(2) );
+               outb( *(inputbuffer + count), RTC_PORT(3) );
+       }
+
+
+/* 
+ * We have to write 0xe4XX to smi_port
+ * where XX is the SMI function code
+ */    
+       function = ( function & 0xff ) << 8;
+       function |= 0xe4;
+       
+
+       switch (lpc_bridge->vendor) {
+               case PCI_VENDOR_ID_INTEL:
+/* 
+ * We get the PMBASE offset ( bits 15:7 at 0x40 offset of PCI config space )
+ * And we access offset 2c (GPE0_EN), save the state, disable all SCI
+ * and restore the state in intel_do_smi_call function
+ */
+                       pci_read_config_dword(lpc_bridge, INTEL_PMBASE, &sci_en);
+                       sci_en = sci_en & 0xff80; /* Keep bits 15:7 */
+                       sci_en += INTEL_GPE0_EN;  /* GPEO_EN offset */
+                       save_all_regs_flag();
+                       intel_do_smi_call(&retval,function,sci_en);
+                       restore_all_regs_flag();
+                       break;
+               case PCI_VENDOR_ID_ATI:
+                       save_all_regs_flag();
+                       ati_do_smi_call(&retval,function);
+                       restore_all_regs_flag();
+                       break;
+               default:
+                       BUG();
+       }
+
+       for(count = 0; count < BUFFER_SIZE; count++) {
+               outb( count + start_offset, RTC_PORT(2) );
+               *(outputbuffer + count) = inb( RTC_PORT(3) );
+       }
+       
+       return retval;
+}
+
+
+static int nbsmi_smi_read_command(const struct omnibook_operation *io_op, u8 *data)
+{
+       int retval;
+       u8 *inputbuffer;
+       u8 *outputbuffer;
+       
+       if(!lpc_bridge)
+               return -ENODEV;
+
+       if(mutex_lock_interruptible(&smi_lock))
+               return -ERESTARTSYS;
+       
+       inputbuffer = kcalloc(BUFFER_SIZE,sizeof(u8),GFP_KERNEL);
+       if(!inputbuffer) {
+               retval = -ENOMEM;
+               goto error1;
+       }
+       
+       outputbuffer = kcalloc(BUFFER_SIZE,sizeof(u8),GFP_KERNEL);
+       if(!inputbuffer) {
+               retval = -ENOMEM;
+               goto error2;
+       }
+       
+       retval = nbsmi_smi_command( (u16) io_op->read_addr, inputbuffer, outputbuffer);
+       if(!retval)
+               goto out;
+       
+       *data = outputbuffer[0];
+
+       if(io_op->read_mask)
+               *data &= io_op->read_mask;
+
+out:
+       kfree(outputbuffer);
+error2:
+       kfree(inputbuffer);
+error1:
+       mutex_unlock(&smi_lock);
+       return retval;
+}
+
+static int nbsmi_smi_write_command(const struct omnibook_operation *io_op, u8 data) 
+{
+       int retval;
+       u8 *inputbuffer;
+       u8 *outputbuffer;
+       
+       if(!lpc_bridge)
+               return -ENODEV;
+
+       if(mutex_lock_interruptible(&smi_lock))
+               return -ERESTARTSYS;
+       
+       inputbuffer = kcalloc(BUFFER_SIZE,sizeof(u8),GFP_KERNEL);
+       if(!inputbuffer) {
+               retval = -ENOMEM;
+               goto error1;
+       }
+       
+       outputbuffer = kcalloc(BUFFER_SIZE,sizeof(u8),GFP_KERNEL);
+       if(!inputbuffer) {
+               retval = -ENOMEM;
+               goto error2;
+       }
+       
+       inputbuffer[0] = data;
+
+       retval = nbsmi_smi_command( (u16) io_op->write_addr, inputbuffer, outputbuffer);
+       
+       kfree(outputbuffer);
+error2:
+       kfree(inputbuffer);
+error1:
+       mutex_unlock(&smi_lock);
+       return retval;
+}
+
+
+/*
+ * Read/Write to INDEX/DATA interface at port 0x300 (SMSC Mailbox registers)
+ * Used by Hotkeys feature under already taken mutex.
+ */
+static void nbsmi_ec_read_command(u16 index, u16 *data)
+{
+       spin_lock_irq(&smi_spinlock);
+       outw(index,EC_INDEX_PORT);
+       *data = inw(EC_DATA_PORT);      
+       spin_unlock_irq(&smi_spinlock);
+}
+
+static void nbsmi_ec_write_command(u16 index, u16 data)
+{
+       spin_lock_irq(&smi_spinlock);
+       outw(index,EC_INDEX_PORT);
+       outw(data,EC_DATA_PORT);
+       spin_unlock_irq(&smi_spinlock);
+}
+
+/*
+ * Try to init the backend
+ * This function can be called blindly as it use a kref
+ * to check if the init sequence was already done.
+ */
+
+static int omnibook_nbsmi_init(const struct omnibook_operation *io_op)
+{
+       int retval = 0;
+       int i;
+       u16 ec_data;
+       u32 smi_port = 0;
+
+/* ectypes other than TSM40 have no business with this backend */      
+       if(!(omnibook_ectype & TSM40))
+               return -ENODEV;
+
+       if(already_failed) {
+               dprintk("NbSmi backend init already failed, skipping.\n");
+               return -ENODEV;
+       }
+
+       if(!refcount) {
+               /* Fist use of the backend */
+               mutex_lock(&smi_lock);
+               dprintk("Try to init NbSmi\n"); 
+               refcount = kmalloc(sizeof(struct kref),GFP_KERNEL);
+               if(!refcount) {
+                       retval= -ENOMEM;
+                       goto out;
+               }
+
+               kref_init(refcount);
+
+               /* PCI probing: find the LPC Super I/O bridge PCI device */
+               for (i = 0; !lpc_bridge && lpc_bridge_table[i].vendor; ++i)
+                       lpc_bridge = pci_get_device(lpc_bridge_table[i].vendor, lpc_bridge_table[i].device, NULL);
+
+               if (!lpc_bridge) {
+                       printk(O_ERR "Fail to find a supported LPC I/O bridge, please report\n");
+                       retval = -ENODEV;
+                       goto error1;
+               }
+               
+               if((retval = pci_enable_device(lpc_bridge))) {
+                       printk(O_ERR "Unable to enable PCI device.\n");
+                       goto error2;
+               }
+               
+               switch (lpc_bridge->vendor) {
+               case PCI_VENDOR_ID_INTEL:
+                       start_offset = INTEL_OFFSET;
+                       smi_port = INTEL_SMI_PORT;
+                       break;
+               case PCI_VENDOR_ID_ATI:
+                       start_offset = ATI_OFFSET;
+                       smi_port = ATI_SMI_PORT;
+                       break;
+               default:
+                       BUG();
+               }
+               
+               if(!request_region(smi_port, 2 , OMNIBOOK_MODULE_NAME)) {
+                       printk(O_ERR "Request SMI I/O region error\n");
+                       retval = -ENODEV;
+                       goto error2;
+               }
+
+               if(!request_region(EC_INDEX_PORT, 2 , OMNIBOOK_MODULE_NAME)) {
+                       printk(O_ERR "Request EC I/O region error\n");
+                       retval = -ENODEV;
+                       goto error3;
+               }
+
+
+               /*
+                * Try some heuristic tests to avoid enabling this interface on unsuported laptops:
+                * See what a port 300h read index 8f gives. Guess there is nothing if read 0xffff
+                */
+
+               nbsmi_ec_read_command(SMI_FN_PRESSED, &ec_data);
+               dprintk("NbSmi test probe read: %x\n",ec_data);
+               if(ec_data == 0xffff) {
+                       printk(O_ERR "Probing at SMSC Mailbox registers failed, disabling NbSmi\n");
+                       retval = -ENODEV;
+                       goto error4;
+               }
+       
+       
+               dprintk("NbSmi init ok\n");
+               goto out;
+       } else {
+               dprintk("NbSmi has already been initialized\n");
+               kref_get(refcount);
+               return 0;
+       }
+error4:
+       release_region(EC_INDEX_PORT,2);
+error3:
+       release_region(smi_port,2);
+error2:
+       pci_dev_put(lpc_bridge);
+       lpc_bridge = NULL;
+error1:
+       kfree(refcount);
+       refcount = NULL;
+       already_failed = 1;
+out:
+       mutex_unlock(&smi_lock);
+       return retval;
+}
+
+static void nbsmi_free(struct kref *ref)
+{
+       u32 smi_port = 0;
+
+       mutex_lock(&smi_lock);
+       dprintk("NbSmi not used anymore: disposing\n");
+       
+       switch (lpc_bridge->vendor) {
+       case PCI_VENDOR_ID_INTEL:
+               smi_port = INTEL_SMI_PORT;
+               break;
+       case PCI_VENDOR_ID_ATI:
+               smi_port = ATI_SMI_PORT;
+               break;
+       default:
+               BUG();
+       }
+       
+       pci_dev_put(lpc_bridge);
+       release_region(smi_port,2);
+       release_region(EC_INDEX_PORT,2);
+       kfree(refcount);
+       lpc_bridge = NULL;
+       refcount = NULL;
+       mutex_unlock(&smi_lock);
+}
+
+static void omnibook_nbsmi_exit(const struct omnibook_operation *io_op)
+{
+/* ectypes other than TSM40 have no business with this backend */
+       BUG_ON(!(omnibook_ectype & TSM40));
+       dprintk("Trying to dispose NbSmi\n");
+       kref_put(refcount,nbsmi_free);
+}
+
+static int omnibook_nbsmi_get_wireless(const struct omnibook_operation *io_op, unsigned int *state)
+{
+       int retval = 0;
+       struct omnibook_operation aerial_op;
+       u8 data;
+       
+       aerial_op.read_addr = SMI_GET_KILL_SWITCH;
+
+       if((retval = nbsmi_smi_read_command(&aerial_op, &data)))
+               goto out;
+       
+       *state = data ? KILLSWITCH : 0; /* Make it 1 or 0 */
+
+       aerial_op.read_addr = SMI_GET_AERIAL;
+
+       if((retval = nbsmi_smi_read_command(&aerial_op, &data)))
+               goto out;
+
+       *state |= ( data & WLEX_MASK ) ? WIFI_EX : 0;
+       *state |= ( data & WLAT_MASK ) ? WIFI_STA : 0;
+       *state |= ( data & BTEX_MASK ) ? BT_EX : 0;
+       *state |= ( data & BTAT_MASK ) ? BT_STA : 0;
+
+out:
+       return retval;
+}
+
+
+static int omnibook_nbsmi_set_wireless(const struct omnibook_operation *io_op, unsigned int state)
+{
+       int retval = 0;
+       u8 data = 0;
+       struct omnibook_operation aerial_op;
+
+       aerial_op.write_addr = SMI_SET_AERIAL;
+       
+       data |= state & BT_STA;
+       data |= ( state & WIFI_STA ) << 0x1 ;
+
+       retval = nbsmi_smi_write_command(&aerial_op, data);
+       
+       return retval;
+}
+
+/*
+ * Hotkeys handling
+ */
+static int omnibook_nbmsi_hotkeys_get(const struct omnibook_operation *io_op, unsigned int *state)
+{
+       int retval;
+       u8 data = 0;
+       struct omnibook_operation hotkeys_op;
+       
+       hotkeys_op.read_addr = SMI_GET_FN_INTERFACE;
+
+       retval = nbsmi_smi_read_command(&hotkeys_op, &data);
+       if(retval < 0)
+               return retval;  
+
+       *state = ( data & SMI_FN_KEYS_MASK ) ? HKEY_FN : 0;
+       *state |= ( data & SMI_STICK_KEYS_MASK ) ? HKEY_STICK : 0;
+       *state |= ( data & SMI_FN_TWICE_LOCK_MASK ) ? HKEY_TWICE_LOCK : 0;
+       *state |= ( data & SMI_FN_DOCK_MASK ) ? HKEY_DOCK : 0;
+
+       return HKEY_FN|HKEY_STICK|HKEY_TWICE_LOCK|HKEY_DOCK;
+}
+
+static int omnibook_nbmsi_hotkeys_set(const struct omnibook_operation *io_op, unsigned int state)
+{
+       int retval;
+       u8 data = 0;
+       struct omnibook_operation hotkeys_op;
+
+       hotkeys_op.write_addr = SMI_SET_FN_INTERFACE;
+       data |= ( state & HKEY_FN ) ? SMI_FN_KEYS_MASK : 0;
+       data |= ( state & HKEY_STICK) ? SMI_STICK_KEYS_MASK : 0;
+       data |= ( state & HKEY_TWICE_LOCK) ? SMI_FN_TWICE_LOCK_MASK : 0;
+       data |= ( state & HKEY_DOCK) ? SMI_FN_DOCK_MASK : 0;
+
+       retval = nbsmi_smi_write_command(&hotkeys_op, data);
+       if(retval < 0)
+               return retval;
+
+       hotkeys_op.write_addr = SMI_SET_FN_F5_INTERFACE;
+       data = !!( state & HKEY_FNF5); 
+
+       retval = nbsmi_smi_write_command(&hotkeys_op, data);
+       if(retval < 0)
+               return retval;
+       else
+               return HKEY_FN|HKEY_STICK|HKEY_TWICE_LOCK|HKEY_DOCK|HKEY_FNF5;
+}
+
+static const unsigned int nbsmi_display_mode_list[] = {
+       DISPLAY_LCD_ON,
+       DISPLAY_LCD_ON|DISPLAY_CRT_ON,
+       DISPLAY_CRT_ON,
+       DISPLAY_LCD_ON|DISPLAY_TVO_ON,
+       DISPLAY_TVO_ON,
+};
+
+static int  omnibook_nbmsi_display_get(const struct omnibook_operation *io_op, unsigned int *state)
+{
+       int retval = 0;
+       u8 data;
+       struct omnibook_operation display_op;
+
+       display_op.read_addr = SMI_GET_DISPLAY_STATE;
+
+       retval = nbsmi_smi_read_command(&display_op, &data);
+       if(retval < 0)
+               return retval;
+
+       if( data > (ARRAY_SIZE(nbsmi_display_mode_list) - 1))
+               return -EIO;    
+       
+       *state = nbsmi_display_mode_list[data];
+
+       return DISPLAY_LCD_ON|DISPLAY_CRT_ON|DISPLAY_TVO_ON;
+}
+
+static int omnibook_nbmsi_display_set(const struct omnibook_operation *io_op, unsigned int state)
+{
+       int retval = 0;
+       int i;
+       u8 matched = 0;
+       struct omnibook_operation display_op;
+
+       display_op.write_addr = SMI_SET_DISPLAY_STATE;
+
+       for(i = 0; i < ARRAY_SIZE(nbsmi_display_mode_list); i++) {
+               if(nbsmi_display_mode_list[i] == state) {
+                       matched = i;
+                       break;
+               }       
+       }
+       if(!matched) {
+               printk("Display mode %x is unsupported.\n", state);
+               return -EINVAL;
+       }
+       
+       retval = nbsmi_smi_write_command(&display_op, matched);
+       if(retval < 0)
+               return retval;
+
+       return DISPLAY_LCD_ON|DISPLAY_CRT_ON|DISPLAY_TVO_ON;
+}
+
+
+
+struct omnibook_backend nbsmi_backend = {
+       .name = "nbsmi",
+       .init = omnibook_nbsmi_init,
+       .exit = omnibook_nbsmi_exit,
+       .byte_read = nbsmi_smi_read_command,
+       .byte_write = nbsmi_smi_write_command,
+       .aerial_get = omnibook_nbsmi_get_wireless,
+       .aerial_set = omnibook_nbsmi_set_wireless,
+       .hotkeys_get = omnibook_nbmsi_hotkeys_get,
+       .hotkeys_set = omnibook_nbmsi_hotkeys_set,
+       .display_get = omnibook_nbmsi_display_get,
+       .display_set = omnibook_nbmsi_display_set,
+};
index fbfd6f65239226f1c7179555363cdd30e1bd02bd..451f2702d0adcac33835bc99460af1e8a5827d1e 100644 (file)
  * EC types
  */
 
-extern int omnibook_ectype;
-
-#define        NONE    0       /* 0  Default/unknown EC type */ 
-#define        XE3GF   (1<<0)  /* 1  HP OmniBook XE3 GF, most Toshiba Satellites and more */
-#define        XE3GC   (1<<1)  /* 2  HP OmniBook XE3 GC, GD, GE and compatible */
-#define        OB500   (1<<2)  /* 3  HP OmniBook 500 and compatible */
-#define        OB510   (1<<3)  /* 4  HP OmniBook 510 */
-#define        OB6000  (1<<4)  /* 5  HP OmniBook 6000 */
-#define        OB6100  (1<<5)  /* 6  HP OmniBook 6100 */
-#define        XE4500  (1<<6)  /* 7  HP OmniBook xe4500 and compatible */
-#define        OB4150  (1<<7)  /* 8  HP OmniBook 4150 */
-#define        XE2     (1<<8)  /* 9  HP OmniBook XE2 */
-#define        AMILOD  (1<<9)  /* 10 Fujitsu Amilo D */
-#define        TSP10   (1<<10) /* 11 Toshiba Satellite P10, P15, P20 and compatible */
-#define        TSM30X  (1<<11) /* 12 Toshiba Satellite M30X, M35X, M40X, M70 and compatible */
-#define        TSM40   (1<<12) /* 13 Toshiba Satellite M40 */
-#define        TSA105  (1<<13) /* 14 Toshiba Satellite A105 */
+extern enum omnibook_ectype_t {
+       NONE   = 0,       /* 0  Default/unknown EC type */ 
+       XE3GF  = (1<<0),  /* 1  HP OmniBook XE3 GF, most old Toshiba Satellites */
+       XE3GC  = (1<<1),  /* 2  HP OmniBook XE3 GC, GD, GE and compatible */
+       OB500  = (1<<2),  /* 3  HP OmniBook 500 and compatible */
+       OB510  = (1<<3),  /* 4  HP OmniBook 510 */
+       OB6000 = (1<<4),  /* 5  HP OmniBook 6000 */
+       OB6100 = (1<<5),  /* 6  HP OmniBook 6100 */
+       XE4500 = (1<<6),  /* 7  HP OmniBook xe4500 and compatible */
+       OB4150 = (1<<7),  /* 8  HP OmniBook 4150 */
+       XE2    = (1<<8),  /* 9  HP OmniBook XE2 */
+       AMILOD = (1<<9),  /* 10 Fujitsu Amilo D */
+       TSP10  = (1<<10), /* 11 Toshiba Satellite P10, P15, P20 and compatible */
+       TSM30X = (1<<11), /* 12 Toshiba Satellite M30X, M35X, M40X, M70 and compatible */
+       TSM40  = (1<<12), /* 13 Toshiba Satellite M40 */
+       TSA105 = (1<<13)  /* 14 Toshiba Satellite A105 */
+} omnibook_ectype;
+
 /*
  * This represent a feature provided by this module
  */
 
+struct omnibook_operation;
+
 struct omnibook_feature {
        char *name;             /* Name */
        char *proc_entry;       /* Specify proc entry relative to /proc (will be omnibook/name otherwise) */
        int enabled;            /* Set from module parameter */
-       int (*read) (char *);   /* Procfile read function */
-       int (*write) (char *);  /* Procfile write function */
-       int (*init) (void);     /* Specific Initialization function */
-       void (*exit) (void);    /* Specific Cleanup function */
-       int (*suspend) (void);  /* PM Suspend function */
-       int (*resume) (void);   /* PM Resume function */
+       int (*read) (char *,struct omnibook_operation *);       /* Procfile read function */
+       int (*write) (char *,struct omnibook_operation *);/* Procfile write function */
+       int (*init) (struct omnibook_operation *);      /* Specific Initialization function */
+       void (*exit) (struct omnibook_operation *);     /* Specific Cleanup function */
+       int (*suspend) (struct omnibook_operation *);   /* PM Suspend function */
+       int (*resume) (struct omnibook_operation *);    /* PM Resume function */
        int ectypes;            /* Type(s) of EC we support for this feature (bitmask) */
+       struct omnibook_tbl *tbl;
+       struct omnibook_operation *io_op;
        struct list_head list;
 };
 
@@ -91,10 +95,55 @@ enum {
 };
 
 
-extern int omnibook_lcd_blank(int blank);
-extern int omnibook_get_ac(void);
-extern int omnibook_get_battery_status(int num, struct omnibook_battery_state *battstat);
-extern int set_omnibook_param(const char *val, struct kernel_param *kp);
+/*
+ * State of a Wifi/Bluetooth adapter
+ */
+enum {
+       WIFI_EX = (1<<0),       /* 1 1=present 0=absent */
+       WIFI_STA = (1<<1),      /* 2 1=enabled 0=disabled */
+       KILLSWITCH = (1<<2),    /* 4 1=radio on 0=radio off */
+       BT_EX = (1<<3),         /* 8 1=present 0=absent */
+       BT_STA = (1<<4),        /* 16 1=enabled 0=disabled */
+};
+
+/*
+ * Hotkeys state backend neutral masks
+ */
+enum {
+       HKEY_ONETOUCH = (1<<0),         /* 1  Ontetouch button scancode generation */
+       HKEY_MULTIMEDIA = (1<<1),       /* 2  "Multimedia hotkeys" scancode generation */       
+       HKEY_FN = (1<<2),               /* 4  Fn + foo hotkeys scancode generation */
+       HKEY_STICK = (1<<3),            /* 8  Stick key (no clue what this is about) */
+       HKEY_TWICE_LOCK = (1<<4),       /* 16 Press Fn twice to lock */
+       HKEY_DOCK = (1<<5),             /* 32 (Un)Dock events scancode generation */
+       HKEY_FNF5 = (1<<6),             /* 64 Fn + F5 (toggle display) is enabled */
+};
+
+
+/*
+ * Display state backend neutral masks
+ * _ON masks = port is powered up and running
+ * _DET masks = a display have been detected to be plugged in the port 
+ */
+
+enum { 
+       DISPLAY_LCD_ON = (1<<0),        /* 1 Internal LCD panel */
+       DISPLAY_CRT_ON = (1<<1),        /* 2 External VGA port */
+       DISPLAY_TVO_ON = (1<<2),        /* 4 External TV-OUT port */
+       DISPLAY_DVI_ON = (1<<3),        /* 8 External DVI port */
+       DISPLAY_LCD_DET = (1<<4),       /* 16 Internal LCD panel */
+       DISPLAY_CRT_DET = (1<<5),       /* 32 External VGA port */
+       DISPLAY_TVO_DET = (1<<6),       /* 64 External TV-OUT port */
+       DISPLAY_DVI_DET = (1<<7),       /* 128 External DVI port */
+};
+
+
+
+int omnibook_lcd_blank(int blank);
+int omnibook_get_ac(struct omnibook_operation *io_op);
+int omnibook_get_battery_status(int num, struct omnibook_battery_state *battstat);
+int set_omnibook_param(const char *val, struct kernel_param *kp);
+
 
 #define __declared_feature __attribute__ (( __section__(".features"),  __aligned__(__alignof__ (struct omnibook_feature)))) __attribute_used__
 
@@ -125,7 +174,7 @@ extern int set_omnibook_param(const char *val, struct kernel_param *kp);
 #else
 #undef  CONFIG_OMNIBOOK_BACKLIGHT
 #endif /* BACKLIGHT_CLASS_DEVICE */
-#undef CONFIG_OMNIBOOK_APMEMU
+#undef CONFIG_OMNIBOOK_LEGACY
 #endif /* OMNIBOOK_STANDALONE */
 
 /* End of file */
index 70a539d847925b3d806156bd7d463e36c937ccd9..7fc90dd88326c24770a093286c9f55d7ecc95a41 100644 (file)
@@ -1,9 +1,11 @@
-SECTIONS{
+SECTIONS
+{
   .data :
     {
-      _features_start = .;
+      . = ALIGN(32);
+      _start_features_driver = .;
       *(.features)
-      _features_end = .;
+      _end_features_driver = .;
       *(.data)
     } 
 }
index 869ea43fcfc6d3d03509071dfe9c4cca2775fa5e..694e462c1d87497ff0c37f31f5911f0daa2165d9 100644 (file)
  * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
  */
 
-#ifdef OMNIBOOK_STANDALONE
 #include "omnibook.h"
-#else
-#include <linux/omnibook.h>
-#endif
-
 #include "ec.h"
 
-static int omnibook_get_cpu_temp(void)
+static int omnibook_temperature_read(char *buffer, struct omnibook_operation *io_op)
 {
-       u8 temp = 0;
+       int len = 0;
        int retval;
-       /*
-        * XE3GF
-        * TSP10
-        * TSM30X 
-        */
-       if (omnibook_ectype & (XE3GF|TSP10|TSM30X) ) {
-               if ((retval = omnibook_ec_read(XE3GF_CTMP, &temp)))
-                       return retval;
-               retval = temp;
-       /*
-        * XE3GC
-        * AMILOD 
-        */
-       } else if (omnibook_ectype & (XE3GC|AMILOD) ) {
-               if ((retval = omnibook_ec_read(XE3GC_CTMP, &temp)))
-                       return retval;
-               retval = temp;
-       /*
-        * OB500
-        * OB510
-        * OB6000
-        * OB6100
-        * XE4500
-        * XE2
-        */
-       } else if (omnibook_ectype & (OB500|OB510|OB6000|OB6100|XE4500|XE2) ) {
-               if ((retval = omnibook_ec_read(OB500_CTMP, &temp)))
-                       return retval;
-               retval = temp;
-       /*
-        * OB4150 
-        */
-       } else if (omnibook_ectype & (OB4150) ) {
+       u8 temp;
        
-               if ((retval = omnibook_ec_read(OB4150_TMP, &temp)))
-                       return retval;
-               retval = temp;
-       } else {
-               printk(O_INFO
-                      "Temperature monitoring is unsupported on this machine.\n");
-               retval = -ENODEV;
-       }
-       return retval;
-}
-
-static int omnibook_temperature_read(char *buffer)
-{
-       int len = 0;
-       int cpu_temp;
-
-       cpu_temp = omnibook_get_cpu_temp();
-       if (cpu_temp < 0)
-               return cpu_temp;
+       if((retval = io_op->backend->byte_read(io_op, &temp)))
+               return retval;
 
        len +=
-           sprintf(buffer + len, "CPU temperature:            %2d C\n",
-                   cpu_temp);
+           sprintf(buffer + len, "CPU temperature:            %2d C\n", temp);
 
        return len;
 }
 
-static struct omnibook_feature __declared_feature temperature_feature = {
+static struct omnibook_tbl temp_table[] __initdata = {
+       { XE3GF|TSP10|TSM30X,                   SIMPLE_BYTE(EC,XE3GF_CTMP,0)},
+       { XE3GC|AMILOD,                         SIMPLE_BYTE(EC,XE3GC_CTMP,0)},
+       { OB500|OB510|OB6000|OB6100|XE4500|XE2, SIMPLE_BYTE(EC,OB500_CTMP,0)},
+       { OB4150,                               SIMPLE_BYTE(EC,OB4150_TMP,0)},
+       { 0,}
+};
+       
+static struct omnibook_feature __declared_feature temperature_driver = {
         .name = "temperature",
         .enabled = 1,
         .read = omnibook_temperature_read,
         .ectypes = XE3GF|XE3GC|OB500|OB510|OB6000|OB6100|XE4500|OB4150|XE2|AMILOD|TSP10|TSM30X,
+        .tbl = temp_table,
 };
 
-module_param_named(temperature, temperature_feature.enabled, int, S_IRUGO);
+module_param_named(temperature, temperature_driver.enabled, int, S_IRUGO);
 MODULE_PARM_DESC(temperature, "Use 0 to disable, 1 to enable thermal status and policy support");
 /* End of file */
index 672f3a5d1ce1eb60cb4eabefc193e41a109c0068..d7193a7520f22d52da210ffbb6a8553f3ddc3d1d 100644 (file)
  * Modified by Mathieu Bérard <mathieu.berard@crans.org>, 2006
  */
 
-#ifdef OMNIBOOK_STANDALONE
 #include "omnibook.h"
-#else
-#include <linux/omnibook.h>
-#endif
-
 #include "ec.h"
 
-/* Touchpad is enabled by default */
+/* Touchpad is assumed to be enabled by default */
 static int omnibook_touchpad_enabled = 1;
 
-static int omnibook_touchpad_on(void)
+static int omnibook_touchpad_set(struct omnibook_operation *io_op, int status)
 {
-       if (omnibook_kbc_command
-           (OMNIBOOK_KBC_CONTROL_CMD, OMNIBOOK_KBC_CMD_TOUCHPAD_ENABLE)) {
-               printk(O_ERR "Failed touchpad enable command.\n");
-               return -EIO;
+       int retval = 0;
+       if ((retval = omnibook_toggle(io_op, !!status))) {
+               printk(O_ERR "Failed touchpad %sable command.\n", status ? "en" : "dis");
        }
-       return 0;
-}
-
-static int omnibook_touchpad_off(void)
-{
-       if (omnibook_kbc_command
-           (OMNIBOOK_KBC_CONTROL_CMD, OMNIBOOK_KBC_CMD_TOUCHPAD_DISABLE)) {
-               printk(O_ERR "Failed touchpad disable command.\n");
-               return -EIO;
-       }
-       return 0;
+       return retval;
 }
 
 /*
- * Power management handlers: redisable touchpad on resume
+ * Power management handlers: redisable touchpad on resume (if requested)
  */
-int omnibook_touchpad_resume(void)
+static int omnibook_touchpad_resume(struct omnibook_operation *io_op)
 {
        int retval;
-       retval = (omnibook_touchpad_enabled ? 0 : omnibook_touchpad_off());
+       retval = (omnibook_touchpad_enabled ? 0 : omnibook_touchpad_set(io_op, 0));
        return retval;
 }
 
-static int omnibook_touchpad_enable(void)
-{
-       /*
-        * XE3GF
-        * XE3GC
-        * TSP10 
-        */
-       if (omnibook_ectype & (XE3GF|XE3GC|TSP10) ) {
-       
-               if (!omnibook_touchpad_enabled) {
-                       if (omnibook_touchpad_on())
-                               return -EIO;
-                       omnibook_touchpad_enabled = 1;
-                       printk(O_INFO "Touchpad is enabled.\n");
-               }
-       /*
-        * These models have stickpointer, not touchpad:
-        * OB500
-        * OB510
-        */
-       } else if (omnibook_ectype & (OB500|OB510) ) {
-       
-               omnibook_touchpad_enabled = 0;
-               return -ENODEV;
-       } else {
-               omnibook_touchpad_enabled = 1;
-               return -ENODEV;
-       }
-       return 0;
-}
-
-static int omnibook_touchpad_disable(void)
-{
-       /*
-        * XE3GF
-        * XE3GC
-        * TSP10 
-        */
-       if (omnibook_ectype & (XE3GF|XE3GC|TSP10) ) {
-               if (omnibook_touchpad_enabled) {
-                       if (omnibook_touchpad_off()) {
-                               return -EIO;
-                       }
-                       omnibook_touchpad_enabled = 0;
-                       printk(O_INFO "Touchpad is disabled.\n");
-               }
-       /*
-        * These models have stickpointer, not touchpad:
-        * OB500
-        * OB510
-        */
-       } else if (omnibook_ectype & (OB500|OB510) ) {
-               omnibook_touchpad_enabled = 0;
-               return -ENODEV;
-       } else {
-               omnibook_touchpad_enabled = 1;
-               return -ENODEV;
-       }
-       return 0;
-}
-
-static int omnibook_touchpad_read(char *buffer)
+/*
+ * Hardware query is unsupported, so reading is unreliable.
+ */
+static int omnibook_touchpad_read(char *buffer, struct omnibook_operation *io_op)
 {
        int len = 0;
+       
 
        len +=
-           sprintf(buffer + len, "Touchpad is %s\n",
-                   (omnibook_touchpad_enabled) ? "enabled" : "disabled");
+           sprintf(buffer + len, "Last touchpad action was an %s command.\n",
+                   (omnibook_touchpad_enabled) ? "enable" : "disable");
 
        return len;
 }
 
-static int omnibook_touchpad_write(char *buffer)
+static int omnibook_touchpad_write(char *buffer, struct omnibook_operation *io_op)
 {
-       switch (*buffer) {
-       case '0':
-               omnibook_touchpad_disable();
-               break;
-       case '1':
-               omnibook_touchpad_enable();
-               break;
-       default:
+       int cmd;
+
+       if ( *buffer == '0' || *buffer == '1') {
+               cmd = *buffer - '0';
+               if(!omnibook_touchpad_set(io_op, cmd)) {
+                       omnibook_touchpad_enabled = cmd;
+                       printk(O_INFO "%sabling touchpad.\n", cmd ? "En" : "Dis");
+               }
+       } else {
                return -EINVAL;
        }
        return 0;
 }
 
-static void omnibook_touchpad_cleanup(void)
+/*
+ * Reenable touchpad upon exit
+ */
+static void __exit omnibook_touchpad_cleanup(struct omnibook_operation *io_op)
 {
-       omnibook_touchpad_enable();
+       omnibook_touchpad_set(io_op,1);
+       printk(O_INFO "Enabling touchpad.\n");
 }
 
-static struct omnibook_feature __declared_feature touchpad_feature = {
+static struct omnibook_tbl touchpad_table[] __initdata = {
+       { XE3GF|XE3GC|TSP10, COMMAND(KBC,OMNIBOOK_KBC_CMD_TOUCHPAD_ENABLE,OMNIBOOK_KBC_CMD_TOUCHPAD_DISABLE)},
+       { TSM30X, {CDI, 0, TSM70_FN_INDEX, 0, TSM70_TOUCHPAD_ON, TSM70_TOUCHPAD_OFF}},
+       { 0,}
+};
+
+static struct omnibook_feature __declared_feature touchpad_driver = {
         .name = "touchpad",
         .enabled = 1,
         .read = omnibook_touchpad_read,
         .write = omnibook_touchpad_write,
         .exit = omnibook_touchpad_cleanup,
         .resume = omnibook_touchpad_resume,
-        .ectypes = XE3GF|XE3GC|TSP10,
+        .ectypes = XE3GF|XE3GC|TSP10|TSM30X,
+        .tbl = touchpad_table,
 };
 
-module_param_named(touchpad, touchpad_feature.enabled, int, S_IRUGO);
+module_param_named(touchpad, touchpad_driver.enabled, int, S_IRUGO);
 MODULE_PARM_DESC(touchpad, "Use 0 to disable, 1 to enable touchpad handling");
 
 /* End of file */
diff --git a/wireless.c b/wireless.c
new file mode 100644 (file)
index 0000000..91e2ec2
--- /dev/null
@@ -0,0 +1,101 @@
+/*
+ * wireless.c Wifi feature
+ * 
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2, or (at your option) any
+ * later version.
+ * 
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * Written by Mathieu Bérard <mathieu.berard@crans.org>, 2006
+ *
+ */
+
+#include "omnibook.h"
+#include "ec.h"
+
+static int omnibook_wifi_read(char *buffer,struct omnibook_operation *io_op)
+{
+       int len = 0;
+       int retval;
+       unsigned int state;
+       
+       if((retval = io_op->backend->aerial_get(io_op,&state)))
+               return retval;
+       
+       len += sprintf(buffer + len,"Wifi adapter is %s", (state & WIFI_EX) ? "present" : "absent");
+       if (state & WIFI_EX)
+               len += sprintf(buffer + len," and %s", (state & WIFI_STA) ? "enabled" : "disabled");
+       len += sprintf(buffer + len,".\n");
+       len += sprintf(buffer + len,"Wifi Kill switch is %s.\n", (state & KILLSWITCH) ? "on" : "off");
+       
+       return len;
+       
+}
+
+static int omnibook_wifi_write(char *buffer,struct omnibook_operation *io_op)
+{
+       int retval = 0; 
+       unsigned int state;
+       
+       if((retval = io_op->backend->aerial_get(io_op,&state)))
+               return retval;
+       
+       if(*buffer == '0' )
+               state &= ~WIFI_STA;
+       else if (*buffer == '1' )
+               state |= WIFI_STA;
+       else
+               return -EINVAL;
+       
+       if((retval = io_op->backend->aerial_set(io_op, state)))
+               return retval;
+
+       return retval;  
+}
+
+static struct omnibook_feature wifi_feature;
+
+static int __init omnibook_wifi_init(struct omnibook_operation *io_op)
+{
+       int retval = 0;
+       unsigned int state;
+       
+/*
+ *  Refuse enabling/disabling a non-existent device
+ */
+       
+       if((retval = io_op->backend->aerial_get(io_op, &state)))
+               return retval;
+       
+       if(!(state & WIFI_EX))
+               wifi_feature.write = NULL;      
+       
+       return retval;
+}
+
+/*
+ * Shared with bluetooth.c
+ */
+struct omnibook_tbl wireless_table[] __initdata = {
+       { TSM30X, {ACPI, 0, 0, 0, 0, 0}}, /* stubs to select backend */
+       { TSM40,  {SMI, 0, 0, 0, 0, 0}}, /* stubs to select backend */
+       { 0,}
+};
+
+static struct omnibook_feature __declared_feature wifi_driver = {
+       .name = "wifi",
+       .enabled = 1,
+       .read = omnibook_wifi_read,
+       .write = omnibook_wifi_write,
+       .init = omnibook_wifi_init,
+       .ectypes = TSM30X|TSM40,
+       .tbl = wireless_table,
+};
+
+module_param_named(wifi, wifi_driver.enabled, int, S_IRUGO);
+MODULE_PARM_DESC(wifi, "Use 0 to disable, 1 to enable Wifi adapter control");