From 6f7e3dc950b3ed8b05dc408b8626c3444c52140a Mon Sep 17 00:00:00 2001 From: =?utf8?q?Mathieu=20B=C3=A9rard?= Date: Sun, 12 Nov 2006 23:29:39 +0000 Subject: [PATCH] * Cleanup in fan_pollicy, dump, battery * Kill legacy_ec_read/write * nbsmi.c: make use of backend private data pointer by folding all global variables in a struct remove smi_spinlock and use preempt_* and local_irq_* instead try to improve hotkeys reliability * acpi.c : hopefuly finish bluetooth work * A few other small cleanup all over the place --- acpi.c | 11 +- battery.c | 271 +++++++++++++++++++------------- blank.c | 11 +- dump.c | 13 +- ec.c | 24 --- fan_policy.c | 161 +++++++++---------- hardware.h | 2 - init.c | 2 - kbc.c | 5 +- lib.c | 8 + misc/omnibook-integration.patch | 2 +- nbsmi.c | 237 ++++++++++++++++------------ omnibook.h | 33 +--- pio.c | 24 +-- polling.c | 4 +- 15 files changed, 428 insertions(+), 380 deletions(-) diff --git a/acpi.c b/acpi.c index c3f2489..67e5481 100644 --- a/acpi.c +++ b/acpi.c @@ -57,6 +57,9 @@ static char ec_dev_list[][20] = { #define TOSH_BT_POWER_ON "BTPO" #define TOSH_BT_POWER_OFF "BTPF" #define TOSH_BT_STATUS "BTST" +#define TOSH_BT_KSST_MASK 0x1 +#define TOSH_BT_USB_MASK 0x40 +#define TOSH_BT_POWER_MASK 0x80 /* * ACPI driver for Toshiba Bluetooth device @@ -91,14 +94,14 @@ static int omnibook_acpi_init(const struct omnibook_operation *io_op) int retval = 0; acpi_handle dev_handle, method_handle; int i; - struct acpi_backend_data *priv_data = io_op->backend->data; + struct acpi_backend_data *priv_data; if (unlikely(acpi_disabled)) { printk(O_ERR "ACPI is disabled: feature unavailable.\n"); return -ENODEV; } - if (!priv_data) { + if (!io_op->backend->data) { dprintk("Try to init ACPI backend\n"); mutex_init(&io_op->backend->mutex); mutex_lock(&io_op->backend->mutex); @@ -273,10 +276,10 @@ static int get_bt_status(const struct acpi_backend_data *priv_data, unsigned int if ((retval = omnibook_acpi_execute(priv_data->bt_handle, TOSH_BT_STATUS, 0, &raw_state))) return retval; - printk(O_INFO "BTST raw_state: %x\n", raw_state); + dprintk("BTST raw_state: %x\n", raw_state); - /* FIXME: raw_state => state translation */ *state = BT_EX; + *state |= ((raw_state & TOSH_BT_USB_MASK) && (raw_state & TOSH_BT_POWER_MASK)) ? BT_STA : 0; return retval; } diff --git a/battery.c b/battery.c index 189afdf..a98dfff 100644 --- a/battery.c +++ b/battery.c @@ -18,27 +18,51 @@ #include "omnibook.h" #include "hardware.h" -static int ec_read16(u8 addr, u16 * data) +struct omnibook_battery_info { + u8 type; /* 1 - Li-Ion, 2 NiMH */ + u16 sn; /* Serial number */ + u16 dv; /* Design Voltage */ + u16 dc; /* Design Capacity */ +}; + +struct omnibook_battery_state { + u16 pv; /* Present Voltage */ + u16 rc; /* Remaining Capacity */ + u16 lc; /* Last Full Capacity */ + u8 gauge; /* Gauge in % */ + u8 status; /* 0 - unknown, 1 - charged, 2 - discharging, 3 - charging, 4 - critical) */ +}; + +enum { + OMNIBOOK_BATTSTAT_UNKNOWN, + OMNIBOOK_BATTSTAT_CHARGED, + OMNIBOOK_BATTSTAT_DISCHARGING, + OMNIBOOK_BATTSTAT_CHARGING, + OMNIBOOK_BATTSTAT_CRITICAL +}; + +#define BAT_OFFSET 0x10 + +static int __backend_u16_read(struct omnibook_operation *io_op, u16 *data) { int retval; - u8 high; - u8 low; - u16 result; - retval = legacy_ec_read(addr, &low); + u8 byte; + + retval = __backend_byte_read(io_op, &byte); if (retval) return retval; - retval = legacy_ec_read(addr + 0x01, &high); - result = ((high << 8) + low); - *data = result; + *data = byte; + io_op->read_addr += 1; + retval = __backend_byte_read(io_op, &byte); + *data += (byte << 8); return retval; } -static int omnibook_battery_present(int num) +static int omnibook_battery_present(struct omnibook_operation *io_op, int num) { int retval; - int i; u8 bat; - u8 mask = 0; + int i; /* * XE3GF @@ -46,28 +70,28 @@ static int omnibook_battery_present(int num) * TSM30X */ if (omnibook_ectype & (XE3GF | TSP10 | TSM30X)) { - - if (num >= 2) - return -EINVAL; - if ((retval = legacy_ec_read(XE3GF_BAL, &bat))) - return retval; - mask = XE3GF_BAL0_MASK; + io_op->read_addr = XE3GF_BAL; + io_op->read_mask = XE3GF_BAL0_MASK; for (i = 0; i < num; i++) - mask = mask << 1; - /* - * XE3GC - * AMILOD - */ + io_op->read_mask = io_op->read_mask << 1; + retval = __backend_byte_read(io_op, &bat); + /* + * XE3GC + * AMILOD + */ } else if (omnibook_ectype & (XE3GC | AMILOD)) { - if (num >= 2) - return -EINVAL; - if ((retval = legacy_ec_read(XE3GC_BAT, &bat))) - return retval; - mask = XE3GC_BAT0_MASK; + io_op->read_addr = XE3GC_BAT; + io_op->read_mask = XE3GC_BAT0_MASK; for (i = 0; i < num; i++) - mask = mask << 1; - } - return (bat & mask) ? 1 : 0; + io_op->read_mask = io_op->read_mask << 1; + retval = __backend_byte_read(io_op, &bat); + } else + retval = -ENODEV; + + /* restore default read_mask */ + io_op->read_mask = 0; + + return !!bat; } /* @@ -80,50 +104,53 @@ static int omnibook_battery_present(int num) * 1 - Battery is not present * 2 - Not supported */ -static int omnibook_get_battery_info(int num, struct omnibook_battery_info *battinfo) +static int omnibook_get_battery_info(struct omnibook_operation *io_op, + int num, + struct omnibook_battery_info *battinfo) { int retval; - u32 offset; - /* * XE3GF * TSP10 * TSM30X */ if (omnibook_ectype & (XE3GF | TSP10 | TSM30X)) { - offset = 0x10; - retval = omnibook_battery_present(num); + retval = omnibook_battery_present(io_op, num); if (retval < 0) return retval; if (retval) { - if ((retval = - legacy_ec_read(XE3GF_BTY0 + (offset * num), &(*battinfo).type))) + io_op->read_addr = XE3GF_BTY0 + (BAT_OFFSET * num); + if ((retval = __backend_byte_read(io_op, &(*battinfo).type))) return retval; - if ((retval = ec_read16(XE3GF_BSN0 + (offset * num), &(*battinfo).sn))) + io_op->read_addr = XE3GF_BSN0 + (BAT_OFFSET * num); + if ((retval = __backend_u16_read(io_op, &(*battinfo).sn))) return retval; - if ((retval = ec_read16(XE3GF_BDV0 + (offset * num), &(*battinfo).dv))) + io_op->read_addr = XE3GF_BDV0 + (BAT_OFFSET * num); + if ((retval = __backend_u16_read(io_op, &(*battinfo).dv))) return retval; - if ((retval = ec_read16(XE3GF_BDC0 + (offset * num), &(*battinfo).dc))) + io_op->read_addr = XE3GF_BDC0 + (BAT_OFFSET * num); + if ((retval = __backend_u16_read(io_op, &(*battinfo).dc))) return retval; (*battinfo).type = ((*battinfo).type & XE3GF_BTY_MASK) ? 1 : 0; } else return 1; - /* - * XE3GC - */ + /* + * XE3GC + */ } else if (omnibook_ectype & (XE3GC)) { - offset = 0x10; - retval = omnibook_battery_present(num); + retval = omnibook_battery_present(io_op, num); if (retval < 0) return retval; if (retval) { - if ((retval = ec_read16(XE3GC_BDV0 + (offset * num), &(*battinfo).dv))) + io_op->read_addr = XE3GC_BDV0 + (BAT_OFFSET * num); + if ((retval = __backend_u16_read(io_op, &(*battinfo).dv))) return retval; - if ((retval = ec_read16(XE3GC_BDC0 + (offset * num), &(*battinfo).dc))) + io_op->read_addr = XE3GC_BDC0 + (BAT_OFFSET * num); + if ((retval = __backend_u16_read(io_op, &(*battinfo).dc))) return retval; - if ((retval = - legacy_ec_read(XE3GC_BTY0 + (offset * num), &(*battinfo).type))) + io_op->read_addr = XE3GC_BTY0 + (BAT_OFFSET * num); + if ((retval = __backend_byte_read(io_op, &(*battinfo).type))) return retval; (*battinfo).type = ((*battinfo).type & XE3GC_BTY_MASK) ? 1 : 0; @@ -134,17 +161,18 @@ static int omnibook_get_battery_info(int num, struct omnibook_battery_info *batt * AMILOD */ } else if (omnibook_ectype & (AMILOD)) { - offset = 0x10; - retval = omnibook_battery_present(num); + retval = omnibook_battery_present(io_op, num); if (retval < 0) return retval; if (retval) { - if ((retval = ec_read16(AMILOD_BDV0 + (offset * num), &(*battinfo).dv))) + io_op->read_addr = AMILOD_BDV0 + (BAT_OFFSET * num); + if ((retval = __backend_u16_read(io_op, &(*battinfo).dv))) return retval; - if ((retval = ec_read16(AMILOD_BDC0 + (offset * num), &(*battinfo).dc))) + io_op->read_addr = AMILOD_BDC0 + (BAT_OFFSET * num); + if ((retval = __backend_u16_read(io_op, &(*battinfo).dc))) return retval; - if ((retval = - legacy_ec_read(AMILOD_BTY0 + (offset * num), &(*battinfo).type))) + io_op->read_addr = AMILOD_BTY0 + (BAT_OFFSET * num); + if ((retval = __backend_byte_read(io_op, &(*battinfo).type))) return retval; (*battinfo).type = ((*battinfo).type & AMILOD_BTY_MASK) ? 1 : 0; @@ -159,9 +187,7 @@ static int omnibook_get_battery_info(int num, struct omnibook_battery_info *batt } else if (omnibook_ectype & (OB500 | OB510)) { switch (num) { case 0: - break; case 1: - break; case 2: break; default: @@ -175,15 +201,14 @@ static int omnibook_get_battery_info(int num, struct omnibook_battery_info *batt } else if (omnibook_ectype & (OB6000 | OB6100 | XE4500)) { switch (num) { case 0: - break; case 1: break; default: return -EINVAL; } - } else { + } else return 2; - } + return 0; } @@ -195,13 +220,14 @@ static int omnibook_get_battery_info(int num, struct omnibook_battery_info *batt * 1 - Battery is not present * 2 - Not supported */ -static int omnibook_get_battery_status(int num, struct omnibook_battery_state *battstat) +static int omnibook_get_battery_status(struct omnibook_operation *io_op, + int num, + struct omnibook_battery_state *battstat) { int retval; u8 status; u16 dc; int gauge; - u8 offset; /* * XE3GF @@ -209,21 +235,24 @@ static int omnibook_get_battery_status(int num, struct omnibook_battery_state *b * TSM30X */ if (omnibook_ectype & (XE3GF | TSP10 | TSM30X)) { - offset = 0x10; - retval = omnibook_battery_present(num); + retval = omnibook_battery_present(io_op, num); if (retval < 0) return retval; if (retval) { - if ((retval = legacy_ec_read(XE3GF_BST0 + (offset * num), &status))) + io_op->read_addr = XE3GF_BST0 + (BAT_OFFSET * num); + if ((retval = __backend_byte_read(io_op, &status))) return retval; - if ((retval = ec_read16(XE3GF_BRC0 + (offset * num), &(*battstat).rc))) + io_op->read_addr = XE3GF_BRC0 + (BAT_OFFSET * num); + if ((retval = __backend_u16_read(io_op, &(*battstat).rc))) return retval; - if ((retval = ec_read16(XE3GF_BPV0 + (offset * num), &(*battstat).pv))) + io_op->read_addr = XE3GF_BPV0 + (BAT_OFFSET * num); + if ((retval = __backend_u16_read(io_op, &(*battstat).pv))) return retval; - if ((retval = ec_read16(XE3GF_BFC0 + (offset * num), &(*battstat).lc))) + io_op->read_addr = XE3GF_BFC0 + (BAT_OFFSET * num); + if ((retval = __backend_u16_read(io_op, &(*battstat).lc))) return retval; - if ((retval = - legacy_ec_read(XE3GF_GAU0 + (offset * num), &(*battstat).gauge))) + io_op->read_addr = XE3GF_GAU0 + (BAT_OFFSET * num); + if ((retval = __backend_byte_read(io_op, &(*battstat).gauge))) return retval; if (status & XE3GF_BST_MASK_CRT) @@ -239,22 +268,25 @@ static int omnibook_get_battery_status(int num, struct omnibook_battery_state *b } } else return 1; - /* - * XE3GC - */ + /* + * XE3GC + */ } else if (omnibook_ectype & (XE3GC)) { - offset = 0x10; - retval = omnibook_battery_present(num); + retval = omnibook_battery_present(io_op, num); if (retval < 0) return retval; if (retval) { - if ((retval = legacy_ec_read(XE3GC_BST0 + (offset * num), &status))) + io_op->read_addr = XE3GC_BST0 + (BAT_OFFSET * num); + if ((retval = __backend_byte_read(io_op, &status))) return retval; - if ((retval = ec_read16(XE3GC_BRC0 + (offset * num), &(*battstat).rc))) + io_op->read_addr = XE3GC_BRC0 + (BAT_OFFSET * num); + if ((retval = __backend_u16_read(io_op, &(*battstat).rc))) return retval; - if ((retval = ec_read16(XE3GC_BPV0 + (offset * num), &(*battstat).pv))) + io_op->read_addr = XE3GC_BPV0 + (BAT_OFFSET * num); + if ((retval = __backend_u16_read(io_op, &(*battstat).pv))) return retval; - if ((retval = ec_read16(XE3GC_BDC0 + (offset * num), &dc))) + io_op->read_addr = XE3GC_BDC0 + (BAT_OFFSET * num); + if ((retval = __backend_u16_read(io_op, &dc))) return retval; if (status & XE3GC_BST_MASK_CRT) @@ -273,22 +305,25 @@ static int omnibook_get_battery_status(int num, struct omnibook_battery_state *b (*battstat).lc = 0; /* Unknown */ } else return 1; - /* - * AMILOD - */ + /* + * AMILOD + */ } else if (omnibook_ectype & (AMILOD)) { - offset = 0x10; - retval = omnibook_battery_present(num); + retval = omnibook_battery_present(io_op, num); if (retval < 0) return retval; if (retval) { - if ((retval = legacy_ec_read(AMILOD_BST0 + (offset * num), &status))) + io_op->read_addr = AMILOD_BST0 + (BAT_OFFSET * num); + if ((retval = __backend_byte_read(io_op, &status))) return retval; - if ((retval = ec_read16(AMILOD_BRC0 + (offset * num), &(*battstat).rc))) + io_op->read_addr = AMILOD_BRC0 + (BAT_OFFSET * num); + if ((retval = __backend_u16_read(io_op, &(*battstat).rc))) return retval; - if ((retval = ec_read16(AMILOD_BPV0 + (offset * num), &(*battstat).pv))) + io_op->read_addr = AMILOD_BPV0 + (BAT_OFFSET * num); + if ((retval = __backend_u16_read(io_op, &(*battstat).pv))) return retval; - if ((retval = ec_read16(AMILOD_BDC0 + (offset * num), &dc))) + io_op->read_addr = AMILOD_BDC0 + (BAT_OFFSET * num); + if ((retval = __backend_u16_read(io_op, &dc))) return retval; if (status & AMILOD_BST_MASK_CRT) @@ -314,27 +349,36 @@ static int omnibook_get_battery_status(int num, struct omnibook_battery_state *b } else if (omnibook_ectype & (OB500 | OB510)) { switch (num) { case 0: - if ((retval = legacy_ec_read(OB500_BT1S, &status))) + io_op->read_addr = OB500_BT1S; + if ((retval = __backend_byte_read(io_op, &status))) return retval; - if ((retval = ec_read16(OB500_BT1C, &(*battstat).rc))) + io_op->read_addr = OB500_BT1C; + if ((retval = __backend_u16_read(io_op, &(*battstat).rc))) return retval; - if ((retval = ec_read16(OB500_BT1V, &(*battstat).pv))) + io_op->read_addr = OB500_BT1V; + if ((retval = __backend_u16_read(io_op, &(*battstat).pv))) return retval; break; case 1: - if ((retval = legacy_ec_read(OB500_BT2S, &status))) + io_op->read_addr = OB500_BT2S; + if ((retval = __backend_byte_read(io_op, &status))) return retval; - if ((retval = ec_read16(OB500_BT2C, &(*battstat).rc))) + io_op->read_addr = OB500_BT2C; + if ((retval = __backend_u16_read(io_op, &(*battstat).rc))) return retval; - if ((retval = ec_read16(OB500_BT2V, &(*battstat).pv))) + io_op->read_addr = OB500_BT2V; + if ((retval = __backend_u16_read(io_op, &(*battstat).pv))) return retval; break; case 2: - if ((retval = legacy_ec_read(OB500_BT3S, &status))) + io_op->read_addr = OB500_BT3S; + if ((retval = __backend_byte_read(io_op, &status))) return retval; - if ((retval = ec_read16(OB500_BT3C, &(*battstat).rc))) + io_op->read_addr = OB500_BT3C; + if ((retval = __backend_u16_read(io_op, &(*battstat).rc))) return retval; - if ((retval = ec_read16(OB500_BT3V, &(*battstat).pv))) + io_op->read_addr = OB500_BT3V; + if ((retval = __backend_u16_read(io_op, &(*battstat).pv))) return retval; break; default: @@ -359,19 +403,25 @@ static int omnibook_get_battery_status(int num, struct omnibook_battery_state *b } else if (omnibook_ectype & (OB6000 | OB6100 | XE4500)) { switch (num) { case 0: - if ((retval = legacy_ec_read(OB500_BT1S, &status))) + io_op->read_addr = OB500_BT1S; + if ((retval = __backend_byte_read(io_op, &status))) return retval; - if ((retval = ec_read16(OB500_BT1C, &(*battstat).rc))) + io_op->read_addr = OB500_BT1C; + if ((retval = __backend_u16_read(io_op, &(*battstat).rc))) return retval; - if ((retval = ec_read16(OB500_BT1V, &(*battstat).pv))) + io_op->read_addr = OB500_BT1V; + if ((retval = __backend_u16_read(io_op, &(*battstat).pv))) return retval; break; case 1: - if ((retval = legacy_ec_read(OB500_BT3S, &status))) + io_op->read_addr = OB500_BT3S; + if ((retval = __backend_byte_read(io_op, &status))) return retval; - if ((retval = ec_read16(OB500_BT3C, &(*battstat).rc))) + io_op->read_addr = OB500_BT3C; + if ((retval = __backend_u16_read(io_op, &(*battstat).rc))) return retval; - if ((retval = ec_read16(OB500_BT3V, &(*battstat).pv))) + io_op->read_addr = OB500_BT3V; + if ((retval = __backend_u16_read(io_op, &(*battstat).pv))) return retval; break; default: @@ -428,11 +478,14 @@ static int omnibook_battery_read(char *buffer, struct omnibook_operation *io_op) else if (omnibook_ectype & (TSM30X)) max = 1; + if(mutex_lock_interruptible(&io_op->backend->mutex)) + return -ERESTARTSYS; + for (i = 0; i < max; i++) { - retval = omnibook_get_battery_info(i, &battinfo); + retval = omnibook_get_battery_info(io_op, i, &battinfo); if (retval == 0) { num++; - omnibook_get_battery_status(i, &battstat); + omnibook_get_battery_status(io_op, i, &battstat); typestr = (battinfo.type) ? "Li-Ion" : "NiMH"; switch (battstat.status) { case OMNIBOOK_BATTSTAT_CHARGED: @@ -474,9 +527,16 @@ static int omnibook_battery_read(char *buffer, struct omnibook_operation *io_op) if (num == 0) len += sprintf(buffer + len, "No battery present\n"); + mutex_unlock(&io_op->backend->mutex); + return len; } +static struct omnibook_tbl battery_table[] __initdata = { + {XE3GF | XE3GC | AMILOD | TSP10 | TSM30X, {EC,}}, + {0,} +}; + static struct omnibook_feature __declared_feature battery_driver = { .name = "battery", #ifdef CONFIG_OMNIBOOK_LEGACY @@ -486,6 +546,7 @@ static struct omnibook_feature __declared_feature battery_driver = { #endif .read = omnibook_battery_read, .ectypes = XE3GF | XE3GC | AMILOD | TSP10 | TSM30X, /* FIXME: OB500|OB6000|OB6100|XE4500 */ + .tbl = battery_table, }; module_param_named(battery, battery_driver.enabled, int, S_IRUGO); diff --git a/blank.c b/blank.c index a059d86..23173d3 100644 --- a/blank.c +++ b/blank.c @@ -32,20 +32,11 @@ static DEFINE_SPINLOCK(blank_spinlock); int omnibook_lcd_blank(int blank) { struct omnibook_feature *blank_feature = omnibook_find_feature("blank"); - int retval = 0; if(!blank_feature) return -ENODEV; - if (blank_feature->io_op->backend == PIO) - omnibook_apply_write_mask(blank_feature->io_op, blank); - else if (blank_feature->io_op->backend == KBC || blank_feature->io_op->backend == CDI) - omnibook_toggle(blank_feature->io_op, blank); - else { - retval = -ENODEV; - } - - return retval; + return omnibook_apply_write_mask(blank_feature->io_op, blank); } static int console_blank_register_hook(void) diff --git a/dump.c b/dump.c index b891bf0..ae55281 100644 --- a/dump.c +++ b/dump.c @@ -37,7 +37,8 @@ static int ecdump_read(char *buffer, struct omnibook_operation *io_op) for (i = 0; i < 255; i += 16) { len += sprintf(buffer + len, "EC 0x%02x:", i); for (j = 0; j < 16; j++) { - if (legacy_ec_read(i + j, &v)) + io_op->read_addr = i +j; + if (backend_byte_read(io_op, &v)) break; if (v != ecdump_regs[i + j]) len += sprintf(buffer + len, " *%02x", v); @@ -74,19 +75,25 @@ static int ecdump_write(char *buffer, struct omnibook_operation *io_op) } else return -EINVAL; if (i >= 0 && i < 256 && v >= 0 && v < 256) { - if (legacy_ec_write(i, v)) - return -EIO; + io_op->write_addr = i; + return backend_byte_write(io_op, v); } else return -EINVAL; return 0; } +static struct omnibook_tbl dump_table[] __initdata = { + {ALL_ECTYPES, {EC,}}, + {0,} +}; + static struct omnibook_feature __declared_feature dump_driver = { .name = "dump", .enabled = 0, .read = ecdump_read, .write = ecdump_write, + .tbl = dump_table, }; module_param_named(dump, dump_driver.enabled, int, S_IRUGO); diff --git a/ec.c b/ec.c index 3960966..8f02283 100644 --- a/ec.c +++ b/ec.c @@ -161,30 +161,6 @@ static int omnibook_ec_write(const struct omnibook_operation *io_op, u8 data) 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 = SIMPLE_BYTE(EC, addr, 0); - retval = omnibook_ec_read(&io_op, data); - 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 = SIMPLE_BYTE(EC, addr, 0); - retval = omnibook_ec_write(&io_op, data); - return retval; -} - static int omnibook_ec_display(const struct omnibook_operation *io_op, unsigned int *state) { int retval; diff --git a/fan_policy.c b/fan_policy.c index cee6bdf..67915ff 100644 --- a/fan_policy.c +++ b/fan_policy.c @@ -26,7 +26,7 @@ * Do not change these values unless you exactly know what you do. */ -#define OMNIBOOK_FAN_LEVELS 7 +#define OMNIBOOK_FAN_LEVELS 8 #define OMNIBOOK_FAN_MIN 25 /* Minimal value of fan off temperature */ #define OMNIBOOK_FOT_MAX 75 /* Maximal value of fan off temperature */ #define OMNIBOOK_FAN_MAX 95 /* Maximal value of fan on temperature */ @@ -39,91 +39,52 @@ #define OMNIBOOK_FAN6_DEFAULT 95 /* Default value of fan level 6 temperature */ #define OMNIBOOK_FAN7_DEFAULT 95 /* Default value of fan level 7 temperature */ -static u8 omnibook_fan_policy[OMNIBOOK_FAN_LEVELS]; +static const u8 fan_defaults[] = { + OMNIBOOK_FOT_DEFAULT, + OMNIBOOK_FAN1_DEFAULT, + OMNIBOOK_FAN2_DEFAULT, + OMNIBOOK_FAN3_DEFAULT, + OMNIBOOK_FAN4_DEFAULT, + OMNIBOOK_FAN5_DEFAULT, + OMNIBOOK_FAN6_DEFAULT, + OMNIBOOK_FAN7_DEFAULT, +}; -static int omnibook_get_fan_policy(void) +static int omnibook_get_fan_policy(struct omnibook_operation *io_op, u8 *fan_policy) { - int retval = 0; + int retval ; int i; - u8 tmp; - /* - * XE3GF - */ - if (omnibook_ectype & (XE3GF)) { - for (i = 0; i <= OMNIBOOK_FAN_LEVELS; i++) { - if ((retval = legacy_ec_read(XE3GF_FOT + i, &tmp))) - return retval; - omnibook_fan_policy[i] = tmp; - } - } else { - printk(O_INFO "Fan policy is unsupported on this machine.\n"); - retval = -ENODEV; + for (i = 0; i < OMNIBOOK_FAN_LEVELS; i++) { + io_op->read_addr = XE3GF_FOT + i; + if ((retval = __backend_byte_read(io_op, &fan_policy[i]))) + return retval; } - return retval; + return 0; } -static int omnibook_set_fan_policy(void) +static int omnibook_set_fan_policy(struct omnibook_operation *io_op, const u8 *fan_policy) { int retval; int i; - /* - * XE3GF - */ - if (omnibook_ectype & (XE3GF)) { - if (omnibook_fan_policy[0] > OMNIBOOK_FOT_MAX) + if (fan_policy[0] > OMNIBOOK_FOT_MAX) + return -EINVAL; + + for (i = 0; i < OMNIBOOK_FAN_LEVELS; i++) { + if ((fan_policy[i] > fan_policy[i + 1]) + || (fan_policy[i] < OMNIBOOK_FAN_MIN) + || (fan_policy[i] > OMNIBOOK_FAN_MAX)) return -EINVAL; - for (i = 0; i < OMNIBOOK_FAN_LEVELS; i++) { - if ((omnibook_fan_policy[i] > omnibook_fan_policy[i + 1]) - || (omnibook_fan_policy[i] < OMNIBOOK_FAN_MIN) - || (omnibook_fan_policy[i] > OMNIBOOK_FAN_MAX)) - return -EINVAL; - if (omnibook_fan_policy[i + 1] > OMNIBOOK_FAN_MAX) - return -EINVAL; - } - for (i = 0; i <= OMNIBOOK_FAN_LEVELS; i++) { - if ((retval = legacy_ec_write(XE3GF_FOT + i, omnibook_fan_policy[i]))) - return retval; - } - } else { - printk(O_INFO "Fan policy is unsupported on this machine.\n"); - retval = -ENODEV; } - - return retval; -} - -static int omnibook_set_fan_policy_defaults(void) -{ - int retval; - int i; - u8 fan_defaults[] = { - OMNIBOOK_FOT_DEFAULT, - OMNIBOOK_FAN1_DEFAULT, - OMNIBOOK_FAN2_DEFAULT, - OMNIBOOK_FAN3_DEFAULT, - OMNIBOOK_FAN4_DEFAULT, - OMNIBOOK_FAN5_DEFAULT, - OMNIBOOK_FAN6_DEFAULT, - OMNIBOOK_FAN7_DEFAULT, - }; - - /* - * XE3GF - */ - if (omnibook_ectype & (XE3GF)) { - for (i = 0; i <= OMNIBOOK_FAN_LEVELS; i++) { - if ((retval = legacy_ec_write(XE3GF_FOT + i, fan_defaults[i]))) - return retval; - } - } else { - printk(O_INFO "Fan policy is unsupported on this machine.\n"); - retval = -ENODEV; + for (i = 0; i < OMNIBOOK_FAN_LEVELS; i++) { + io_op->write_addr = XE3GF_FOT + i; + if ((retval = __backend_byte_write(io_op, fan_policy[i]))) + return retval; } - return retval; + return 0; } static int omnibook_fan_policy_read(char *buffer, struct omnibook_operation *io_op) @@ -131,16 +92,24 @@ static int omnibook_fan_policy_read(char *buffer, struct omnibook_operation *io_ int retval; int len = 0; u8 i; + u8 fan_policy[OMNIBOOK_FAN_LEVELS]; + + if(mutex_lock_interruptible(&io_op->backend->mutex)) + return -ERESTARTSYS; - if ((retval = omnibook_get_fan_policy())) + retval = omnibook_get_fan_policy(io_op, &fan_policy[0]); + + mutex_unlock(&io_op->backend->mutex); + + if(retval) return retval; - len += sprintf(buffer + len, "Fan off temperature: %2d C\n", omnibook_fan_policy[0]); - len += sprintf(buffer + len, "Fan on temperature: %2d C\n", omnibook_fan_policy[1]); - for (i = 2; i <= OMNIBOOK_FAN_LEVELS; i++) { + len += sprintf(buffer + len, "Fan off temperature: %2d C\n", fan_policy[0]); + len += sprintf(buffer + len, "Fan on temperature: %2d C\n", fan_policy[1]); + for (i = 2; i < OMNIBOOK_FAN_LEVELS; i++) { len += sprintf(buffer + len, "Fan level %1d temperature: %2d C\n", i, - omnibook_fan_policy[i]); + fan_policy[i]); } len += sprintf(buffer + len, "Minimal temperature to set: %2d C\n", OMNIBOOK_FAN_MIN); len += sprintf(buffer + len, "Maximal temperature to set: %2d C\n", OMNIBOOK_FAN_MAX); @@ -155,9 +124,13 @@ static int omnibook_fan_policy_write(char *buffer, struct omnibook_operation *io char *endp; int retval; int temp; + u8 fan_policy[OMNIBOOK_FAN_LEVELS]; - if ((retval = omnibook_get_fan_policy())) - return retval; + if(mutex_lock_interruptible(&io_op->backend->mutex)) + return -ERESTARTSYS; + + if ((retval = omnibook_get_fan_policy(io_op, &fan_policy[0]))) + goto out; /* * Could also be done much simpler using sscanf(,"%u %u ... @@ -168,34 +141,46 @@ static int omnibook_fan_policy_write(char *buffer, struct omnibook_operation *io b = buffer; do { dprintk("n=[%i] b=[%s]\n", n, b); - if (n > OMNIBOOK_FAN_LEVELS) - return -EINVAL; + if (n > OMNIBOOK_FAN_LEVELS) { + retval = -EINVAL; + goto out; + } if (!isspace(*b)) { temp = simple_strtoul(b, &endp, 10); if (endp != b) { /* there was a match */ - omnibook_fan_policy[n++] = temp; + fan_policy[n++] = temp; b = endp; - } else - return -EINVAL; + } else { + retval = -EINVAL; + goto out; + } } else b++; } while ((*b != '\0') && (*b != '\n')); /* A zero value set the defaults */ - if ((omnibook_fan_policy[0] == 0) && (n == 1)) { - if ((retval = omnibook_set_fan_policy_defaults())) - return retval; - } else if ((retval = omnibook_set_fan_policy())) - return retval; - return 0; + if ((fan_policy[0] == 0) && (n == 1)) + retval = omnibook_set_fan_policy(io_op, &fan_defaults[0]); + else + retval = omnibook_set_fan_policy(io_op, &fan_policy[0]); + + out: + mutex_unlock(&io_op->backend->mutex); + return retval; } +static struct omnibook_tbl fan_policy_table[] __initdata = { + {XE3GF, {EC,}}, + {0,} +}; + static struct omnibook_feature __declared_feature fan_policy_driver = { .name = "fan_policy", .enabled = 1, .read = omnibook_fan_policy_read, .write = omnibook_fan_policy_write, .ectypes = XE3GF, + .tbl = fan_policy_table, }; module_param_named(fan_policy, fan_policy_driver.enabled, int, S_IRUGO); diff --git a/hardware.h b/hardware.h index 5abf2fb..7a046cc 100644 --- a/hardware.h +++ b/hardware.h @@ -89,8 +89,6 @@ extern struct omnibook_backend compal_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); diff --git a/init.c b/init.c index 9c9ba5f..ce701e8 100644 --- a/init.c +++ b/init.c @@ -86,8 +86,6 @@ static char *laptop_model __initdata; static int omnibook_userset = 0; -struct input_dev *omnibook_input_dev; - /* * The platform_driver interface was added in linux 2.6.15 */ diff --git a/kbc.c b/kbc.c index 7177a7c..5a7ff71 100644 --- a/kbc.c +++ b/kbc.c @@ -105,7 +105,7 @@ static int omnibook_kbc_write_data(u8 data) spin_lock_irq(&omnibook_kbc_lock); retval = omnibook_kbc_wait(OMNIBOOK_KBC_STAT_IBF); if (retval) - goto end;; + goto end; outb(data, OMNIBOOK_KBC_DATA); retval = omnibook_kbc_wait(OMNIBOOK_KBC_STAT_IBF); end: @@ -142,9 +142,6 @@ static int omnibook_kbc_hotkeys(const struct omnibook_operation *io_op, unsigned /* * Backend interface declarations */ - -struct mutex kbc_mutex; - struct omnibook_backend kbc_backend = { .name = "i8042", .hotkeys_write_cap = HKEY_ONETOUCH, diff --git a/lib.c b/lib.c index 04328b8..728e70f 100644 --- a/lib.c +++ b/lib.c @@ -21,12 +21,20 @@ #include "compat.h" #include +/* + * Generic funtion for applying a mask on a value + * Hack: degenerate to omnibook_toggle if there is no read method + * of if the read address is 0, this is used in blank.c + */ int __omnibook_apply_write_mask(const struct omnibook_operation *io_op, int toggle) { int retval = 0; int mask; u8 data; + if(!(io_op->backend->byte_read && io_op->read_addr)) + return __omnibook_toggle(io_op,toggle); + if ((retval = __backend_byte_read(io_op, &data))) return retval; diff --git a/misc/omnibook-integration.patch b/misc/omnibook-integration.patch index 445d437..13027f4 100644 --- a/misc/omnibook-integration.patch +++ b/misc/omnibook-integration.patch @@ -30,7 +30,7 @@ +config OMNIBOOK_LEGACY + bool "HP omnibook legacy features" + depends on OMNIBOOK -+ default y if !ACPI ++ default y if !ACPI + ---help--- + This option enable support for some legacy features of the omnibook + driver, including: diff --git a/nbsmi.c b/nbsmi.c index 94bb6e2..c0c47be 100644 --- a/nbsmi.c +++ b/nbsmi.c @@ -28,6 +28,7 @@ #include #include #include +#include /* copied from drivers/input/serio/i8042-io.h */ #define I8042_KBD_PHYS_DESC "isa0060/serio0" @@ -43,11 +44,13 @@ #define BUFFER_SIZE 0x20 #define INTEL_OFFSET 0x60 #define INTEL_SMI_PORT 0xb2 /* APM_CNT port in INTEL ICH specs */ + /* * Toshiba Specs state 0xef here but: * -this would overflow (ef + 19 > ff) * -code from Toshiba use e0, which make much more sense */ + #define ATI_OFFSET 0xe0 #define ATI_SMI_PORT 0xb0 @@ -60,17 +63,15 @@ #define BTEX_MASK 0x1 #define BTAT_MASK 0x2 -/* - * Crital sections around #SMI triggering are run atomically using a spinlock - */ -static DEFINE_SPINLOCK(smi_spinlock); - /* * Private data of this backend */ -static struct pci_dev *lpc_bridge; /* Southbridge chip ISA bridge/LPC interface PCI device */ -static u8 start_offset; -static struct input_dev *nbsmi_input_dev; +struct nbsmi_backend_data { + struct pci_dev *lpc_bridge; /* Southbridge chip ISA bridge/LPC interface PCI device */ + u8 start_offset; /* Start offset in CMOS memory */ + struct input_dev *nbsmi_input_dev; + struct work_struct fnkey_work; +}; /* * Possible list of supported southbridges @@ -86,12 +87,13 @@ extern const struct pci_device_id lpc_bridge_table[]; * process. * We also disable preemtion and IRQs upon SMI call. */ - -static inline u32 ati_do_smi_call( u16 function) +static inline u32 ati_do_smi_call(u16 function) { unsigned long flags; u32 retval = 0; - spin_lock_irqsave(&smi_spinlock,flags); + + local_irq_save(flags); + preempt_disable(); /* * eflags, eax, ebx, ecx, edx, esi and edi are clobbered upon writing to SMI_PORT @@ -108,7 +110,6 @@ static inline u32 ati_do_smi_call( u16 function) * retval = -EIO; [too bad] * out: */ - __asm__ __volatile__("outw %%ax, %2; \ orw %%ax, %%ax; \ jz 1f; \ @@ -121,16 +122,19 @@ static inline u32 ati_do_smi_call( u16 function) : "a"(function), "N"(ATI_SMI_PORT), "N"(ATI_SMI_PORT+1), "i"(-EIO) : "memory", "ebx", "ecx", "edx", "esi", "edi", "cc"); - spin_unlock_irqrestore(&smi_spinlock,flags); + local_irq_restore(flags); + preempt_enable_no_resched(); return retval; } -static inline u32 intel_do_smi_call(u16 function) +static inline u32 intel_do_smi_call(u16 function, struct pci_dev *lpc_bridge) { u32 state, sci_en; unsigned long flags; u32 retval = 0; - spin_lock_irqsave(&smi_spinlock,flags); + + local_irq_save(flags); + preempt_disable(); /* * We get the PMBASE offset ( bits 15:7 at 0x40 offset of PCI config space ) @@ -141,7 +145,7 @@ static inline u32 intel_do_smi_call(u16 function) sci_en = sci_en & 0xff80; /* Keep bits 15:7 */ sci_en += INTEL_GPE0_EN; /* GPEO_EN offset */ state = inl(sci_en); - outl(0,sci_en); + outl(0, sci_en); /* * eflags, eax, ebx, ecx, edx, esi and edi are clobbered upon writing to SMI_PORT @@ -165,18 +169,22 @@ static inline u32 intel_do_smi_call(u16 function) : "a"(function), "N"(INTEL_SMI_PORT), "i"(-EIO) : "memory", "ebx", "ecx", "edx", "esi", "edi", "cc"); - outl( state, sci_en ); - spin_unlock_irqrestore(&smi_spinlock,flags); + outl(state, sci_en); + local_irq_restore(flags); + preempt_enable_no_resched(); return retval; } -static int nbsmi_smi_command(u16 function, const u8 * inputbuffer, u8 * outputbuffer) +static int nbsmi_smi_command(u16 function, + const u8 * inputbuffer, + u8 * outputbuffer, + struct nbsmi_backend_data *priv_data) { int count; u32 retval = 0; for (count = 0; count < BUFFER_SIZE; count++) { - outb(count + start_offset, RTC_PORT(2)); + outb(count + priv_data->start_offset, RTC_PORT(2)); outb(*(inputbuffer + count), RTC_PORT(3)); } @@ -187,9 +195,9 @@ static int nbsmi_smi_command(u16 function, const u8 * inputbuffer, u8 * outputbu function = (function & 0xff) << 8; function |= 0xe4; - switch (lpc_bridge->vendor) { + switch (priv_data->lpc_bridge->vendor) { case PCI_VENDOR_ID_INTEL: - retval = intel_do_smi_call(function); + retval = intel_do_smi_call(function, priv_data->lpc_bridge); break; case PCI_VENDOR_ID_ATI: retval = ati_do_smi_call(function); @@ -202,7 +210,7 @@ static int nbsmi_smi_command(u16 function, const u8 * inputbuffer, u8 * outputbu printk(O_ERR "smi_command failed with error %u.\n", retval); for (count = 0; count < BUFFER_SIZE; count++) { - outb(count + start_offset, RTC_PORT(2)); + outb(count + priv_data->start_offset, RTC_PORT(2)); *(outputbuffer + count) = inb(RTC_PORT(3)); } @@ -214,8 +222,9 @@ static int nbsmi_smi_read_command(const struct omnibook_operation *io_op, u8 * d int retval; u8 *inputbuffer; u8 *outputbuffer; + struct nbsmi_backend_data *priv_data = io_op->backend->data; - if (!lpc_bridge) + if (!priv_data) return -ENODEV; inputbuffer = kcalloc(BUFFER_SIZE, sizeof(u8), GFP_KERNEL); @@ -230,7 +239,7 @@ static int nbsmi_smi_read_command(const struct omnibook_operation *io_op, u8 * d goto error2; } - retval = nbsmi_smi_command((u16) io_op->read_addr, inputbuffer, outputbuffer); + retval = nbsmi_smi_command((u16) io_op->read_addr, inputbuffer, outputbuffer, priv_data); if (retval) goto out; @@ -252,8 +261,9 @@ static int nbsmi_smi_write_command(const struct omnibook_operation *io_op, u8 da int retval; u8 *inputbuffer; u8 *outputbuffer; + struct nbsmi_backend_data *priv_data = io_op->backend->data; - if (!lpc_bridge) + if (!priv_data) return -ENODEV; inputbuffer = kcalloc(BUFFER_SIZE, sizeof(u8), GFP_KERNEL); @@ -270,7 +280,7 @@ static int nbsmi_smi_write_command(const struct omnibook_operation *io_op, u8 da inputbuffer[0] = data; - retval = nbsmi_smi_command((u16) io_op->write_addr, inputbuffer, outputbuffer); + retval = nbsmi_smi_command((u16) io_op->write_addr, inputbuffer, outputbuffer, priv_data); kfree(outputbuffer); error2: @@ -282,21 +292,17 @@ static int nbsmi_smi_write_command(const struct omnibook_operation *io_op, u8 da /* * Read/Write to INDEX/DATA interface at port 0x300 (SMSC Mailbox registers) */ -void nbsmi_ec_read_command(u8 index, u8 * data) +static inline void nbsmi_ec_read_command(u8 index, u8 * data) { - spin_lock_irq(&smi_spinlock); outb(index, EC_INDEX_PORT); *data = inb(EC_DATA_PORT); - spin_unlock_irq(&smi_spinlock); } #if 0 -static void nbsmi_ec_write_command(u8 index, u8 data) +static inline void nbsmi_ec_write_command(u8 index, u8 data) { - spin_lock_irq(&smi_spinlock); outb(index, EC_INDEX_PORT); outb(data, EC_DATA_PORT); - spin_unlock_irq(&smi_spinlock); } #endif @@ -348,6 +354,7 @@ static struct input_handle *hook_connect(struct input_handler *handler, handle->dev = dev; handle->handler = handler; handle->name = "omnibook_scancode_hook"; + handle->private = handler->private; input_open_device(handle); @@ -366,14 +373,11 @@ static void hook_disconnect(struct input_handle *handle) * the nbsmi backend might sleep. */ -static void omnibook_handle_fnkey(void* data); -DECLARE_WORK(omnibook_fnkey_work, *omnibook_handle_fnkey, NULL); - static void hook_event(struct input_handle *handle, unsigned int event_type, unsigned int event_code, int value) { - if (event_type == EV_MSC && event_code == MSC_SCAN && value == SMI_FN_SCAN ) - schedule_work(&omnibook_fnkey_work); + if (event_type == EV_MSC && event_code == MSC_SCAN && value == SMI_FN_SCAN) + schedule_work(&((struct nbsmi_backend_data *)handle->private)->fnkey_work); } #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)) @@ -406,7 +410,7 @@ static struct input_handler hook_handler = { /* * Detected scancode to keycode table */ -static struct { +static const struct { unsigned int scancode; unsigned int keycode; } nbsmi_scan_table[] = { @@ -424,13 +428,16 @@ static struct { { 0,0}, }; +static void omnibook_handle_fnkey(void* data); + /* * Register the input handler and the input device in the input subsystem */ -static int register_input_subsystem(void) +static int register_input_subsystem(struct nbsmi_backend_data *priv_data) { int i, retval = 0; - + struct input_dev *nbsmi_input_dev; + nbsmi_input_dev = input_allocate_device(); if (!nbsmi_input_dev) { retval = -ENOMEM; @@ -447,7 +454,16 @@ static int register_input_subsystem(void) set_bit(nbsmi_scan_table[i].keycode, nbsmi_input_dev->keybit); retval = input_register_device(nbsmi_input_dev); + if(retval) { + input_free_device(nbsmi_input_dev); + goto out; + } + priv_data->nbsmi_input_dev = nbsmi_input_dev; + + INIT_WORK(&priv_data->fnkey_work, *omnibook_handle_fnkey, priv_data); + + hook_handler.private = priv_data; #if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,18)) retval = input_register_handler(&hook_handler); @@ -460,7 +476,6 @@ static int register_input_subsystem(void) return retval; } - /* * Try to init the backend * This function can be called blindly as it use a kref @@ -472,6 +487,7 @@ static int omnibook_nbsmi_init(const struct omnibook_operation *io_op) int i; u8 ec_data; u32 smi_port = 0; + struct nbsmi_backend_data *priv_data; /* ectypes other than TSM40 have no business with this backend */ if (!(omnibook_ectype & TSM40)) @@ -482,37 +498,43 @@ static int omnibook_nbsmi_init(const struct omnibook_operation *io_op) return -ENODEV; } - if (!lpc_bridge) { + if (!io_op->backend->data) { /* Fist use of the backend */ dprintk("Try to init NbSmi\n"); mutex_init(&io_op->backend->mutex); mutex_lock(&io_op->backend->mutex); kref_init(&io_op->backend->kref); + priv_data = kzalloc(sizeof(struct nbsmi_backend_data), GFP_KERNEL); + if (!priv_data) { + retval = -ENOMEM; + goto error0; + } + /* PCI probing: find the LPC Super I/O bridge PCI device */ - for (i = 0; !lpc_bridge && lpc_bridge_table[i].vendor; ++i) - lpc_bridge = + for (i = 0; !priv_data->lpc_bridge && lpc_bridge_table[i].vendor; ++i) + priv_data->lpc_bridge = pci_get_device(lpc_bridge_table[i].vendor, lpc_bridge_table[i].device, NULL); - if (!lpc_bridge) { + if (!priv_data->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))) { + if ((retval = pci_enable_device(priv_data->lpc_bridge))) { printk(O_ERR "Unable to enable PCI device.\n"); goto error2; } - switch (lpc_bridge->vendor) { + switch (priv_data->lpc_bridge->vendor) { case PCI_VENDOR_ID_INTEL: - start_offset = INTEL_OFFSET; + priv_data->start_offset = INTEL_OFFSET; smi_port = INTEL_SMI_PORT; break; case PCI_VENDOR_ID_ATI: - start_offset = ATI_OFFSET; + priv_data->start_offset = ATI_OFFSET; smi_port = ATI_SMI_PORT; break; default: @@ -544,7 +566,12 @@ static int omnibook_nbsmi_init(const struct omnibook_operation *io_op) goto error4; } - register_input_subsystem(); + retval = register_input_subsystem(priv_data); + if(retval) + goto error4; + + io_op->backend->data = priv_data; + dprintk("NbSmi init ok\n"); mutex_unlock(&io_op->backend->mutex); return 0; @@ -558,9 +585,11 @@ static int omnibook_nbsmi_init(const struct omnibook_operation *io_op) error3: release_region(smi_port, 2); error2: - pci_dev_put(lpc_bridge); - lpc_bridge = NULL; + pci_dev_put(priv_data->lpc_bridge); error1: + kfree(priv_data); + io_op->backend->data = NULL; + error0: io_op->backend->already_failed = 1; mutex_unlock(&io_op->backend->mutex); mutex_destroy(&io_op->backend->mutex); @@ -574,18 +603,20 @@ static void nbsmi_free(struct kref *ref) { u32 smi_port = 0; struct omnibook_backend *backend; + struct nbsmi_backend_data *priv_data; dprintk("NbSmi not used anymore: disposing\n"); + backend = container_of(ref, struct omnibook_backend, kref); + priv_data = backend->data; + flush_scheduled_work(); input_unregister_handler(&hook_handler); - input_unregister_device(nbsmi_input_dev); - - backend = container_of(ref, struct omnibook_backend, kref); + input_unregister_device(priv_data->nbsmi_input_dev); mutex_lock(&backend->mutex); - switch (lpc_bridge->vendor) { + switch (priv_data->lpc_bridge->vendor) { case PCI_VENDOR_ID_INTEL: smi_port = INTEL_SMI_PORT; break; @@ -596,10 +627,11 @@ static void nbsmi_free(struct kref *ref) BUG(); } - pci_dev_put(lpc_bridge); + pci_dev_put(priv_data->lpc_bridge); release_region(smi_port, 2); release_region(EC_INDEX_PORT, 2); - lpc_bridge = NULL; + kfree(priv_data); + backend->data = NULL; mutex_unlock(&backend->mutex); mutex_destroy(&backend->mutex); } @@ -641,7 +673,7 @@ static int adjust_brighness(int delta) brgt = omnibook_max_brightness; else brgt += delta; - + retval = __backend_byte_write(io_op, brgt); out: @@ -658,6 +690,7 @@ static void omnibook_handle_fnkey(void* data) { int i; u8 gen_scan; + struct input_dev *input_dev; if(backend_byte_read(&last_scan_op, &gen_scan)) return; @@ -671,10 +704,12 @@ static void omnibook_handle_fnkey(void* data) adjust_brighness(+1); break; } - for(i=0 ; i < ARRAY_SIZE(nbsmi_scan_table); i++) { + + for(i = 0 ; i < ARRAY_SIZE(nbsmi_scan_table); i++) { if( gen_scan == nbsmi_scan_table[i].scancode) { dprintk("generating keycode %i.\n", nbsmi_scan_table[i].keycode); - omnibook_report_key(nbsmi_input_dev, nbsmi_scan_table[i].keycode); + input_dev = ((struct nbsmi_backend_data *) data)->nbsmi_input_dev; + omnibook_report_key(input_dev, nbsmi_scan_table[i].keycode); break; } } @@ -683,12 +718,9 @@ static void omnibook_handle_fnkey(void* data) static int omnibook_nbsmi_get_wireless(const struct omnibook_operation *io_op, unsigned int *state) { int retval = 0; - struct omnibook_operation aerial_op; + struct omnibook_operation aerial_op = SIMPLE_BYTE(SMI, SMI_GET_KILL_SWITCH, 0); u8 data; - aerial_op.read_addr = SMI_GET_KILL_SWITCH; - aerial_op.read_mask = 0; - if ((retval = nbsmi_smi_read_command(&aerial_op, &data))) goto out; @@ -697,7 +729,6 @@ static int omnibook_nbsmi_get_wireless(const struct omnibook_operation *io_op, u *state = data ? KILLSWITCH : 0; aerial_op.read_addr = SMI_GET_AERIAL; - aerial_op.read_mask = 0; if ((retval = nbsmi_smi_read_command(&aerial_op, &data))) goto out; @@ -717,9 +748,7 @@ static int omnibook_nbsmi_set_wireless(const struct omnibook_operation *io_op, u { int retval = 0; u8 data; - struct omnibook_operation aerial_op; - - aerial_op.write_addr = SMI_SET_AERIAL; + struct omnibook_operation aerial_op = SIMPLE_BYTE(SMI, SMI_SET_AERIAL, 0); data = !!(state & BT_STA); data |= !!(state & WIFI_STA) << 0x1; @@ -731,19 +760,11 @@ static int omnibook_nbsmi_set_wireless(const struct omnibook_operation *io_op, u return retval; } -/* - * Hotkeys reading return completly unreliable results on a least Tecra S1 - * It is therefore disabled - */ -#if 0 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; - hotkeys_op.read_mask = 0; + struct omnibook_operation hotkeys_op = SIMPLE_BYTE(SMI, SMI_GET_FN_INTERFACE, 0); retval = nbsmi_smi_read_command(&hotkeys_op, &data); if (retval < 0) @@ -758,33 +779,52 @@ static int omnibook_nbmsi_hotkeys_get(const struct omnibook_operation *io_op, un return 0; } -#endif + 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; + int i, retval; + u8 data, rdata; + struct omnibook_operation hotkeys_op = SIMPLE_BYTE(SMI, SMI_SET_FN_F5_INTERFACE, 0); - 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; + data = !!(state & HKEY_FNF5); - dprintk("set_hotkeys (Fn interface) raw_state: %x\n", data); + dprintk("set_hotkeys (Fn F5) raw_state: %x\n", data); 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); + hotkeys_op.write_addr = SMI_SET_FN_INTERFACE; + hotkeys_op.read_addr = SMI_GET_FN_INTERFACE; - dprintk("set_hotkeys (Fn F5) raw_state: %x\n", data); + 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; + + dprintk("set_hotkeys (Fn interface) raw_state: %x\n", data); + + /* + * Hardware seems to be quite stubborn and multiple retries may be + * required. The criteria here is simple: retry until probed state match + * the requested one (with timeout). + */ + for (i = 0; i < 250; i++) { + retval = nbsmi_smi_write_command(&hotkeys_op, data); + if (retval) + return retval; + mdelay(1); + retval = nbsmi_smi_read_command(&hotkeys_op, &rdata); + if(retval) + return retval; + if(rdata == data) { + dprintk("check loop ok after %i iters\n.",i); + return 0; + } + } + dprintk("error or check loop timeout !!\n"); - retval = nbsmi_smi_write_command(&hotkeys_op, data); - return retval; } @@ -825,8 +865,9 @@ static int omnibook_nbmsi_display_set(const struct omnibook_operation *io_op, un break; } } - if(matched==255) { - printk("Display mode %x is unsupported.\n", state); + + if(matched == 255) { + printk(O_ERR "Display mode %x is unsupported.\n", state); return -EINVAL; } @@ -839,7 +880,7 @@ static int omnibook_nbmsi_display_set(const struct omnibook_operation *io_op, un struct omnibook_backend nbsmi_backend = { .name = "nbsmi", -/* .hotkey_read_cap = HKEY_FN | HKEY_STICK | HKEY_TWICE_LOCK | HKEY_DOCK, */ + .hotkeys_read_cap = HKEY_FN | HKEY_STICK | HKEY_TWICE_LOCK | HKEY_DOCK, .hotkeys_write_cap = HKEY_FN | HKEY_STICK | HKEY_TWICE_LOCK | HKEY_DOCK | HKEY_FNF5, .init = omnibook_nbsmi_init, .exit = omnibook_nbsmi_exit, @@ -847,7 +888,7 @@ struct omnibook_backend nbsmi_backend = { .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_get = omnibook_nbmsi_hotkeys_get, .hotkeys_set = omnibook_nbmsi_hotkeys_set, .display_get = omnibook_nbmsi_display_get, .display_set = omnibook_nbmsi_display_set, diff --git a/omnibook.h b/omnibook.h index 3001469..ae721f9 100644 --- a/omnibook.h +++ b/omnibook.h @@ -50,6 +50,8 @@ extern enum omnibook_ectype_t { TSA105 = (1<<13) /* 14 Toshiba Satellite A105 */ } omnibook_ectype; +#define ALL_ECTYPES XE3GF|XE3GC|OB500|OB510|OB6000|OB6100|XE4500|OB4150|XE2|AMILOD|TSP10|TSM30X|TSM40|TSA105 + /* * This represent a feature provided by this module */ @@ -71,29 +73,6 @@ struct omnibook_feature { struct list_head list; }; -struct omnibook_battery_info { - u8 type; /* 1 - Li-Ion, 2 NiMH */ - u16 sn; /* Serial number */ - u16 dv; /* Design Voltage */ - u16 dc; /* Design Capacity */ -}; -struct omnibook_battery_state { - u16 pv; /* Present Voltage */ - u16 rc; /* Remaining Capacity */ - u16 lc; /* Last Full Capacity */ - u8 gauge; /* Gauge in % */ - u8 status; /* 0 - unknown, 1 - charged, 2 - discharging, 3 - charging, 4 - critical) */ -}; - -enum { - OMNIBOOK_BATTSTAT_UNKNOWN, - OMNIBOOK_BATTSTAT_CHARGED, - OMNIBOOK_BATTSTAT_DISCHARGING, - OMNIBOOK_BATTSTAT_CHARGING, - OMNIBOOK_BATTSTAT_CRITICAL -}; - - /* * State of a Wifi/Bluetooth adapter */ @@ -176,7 +155,7 @@ void omnibook_report_key(struct input_dev *dev, unsigned int keycode); /* * Configuration for standalone compilation: * -Register as backlight depends on kernel config (requires 2.6.17+ interface) - * -Legacy features disbled by default + * -Legacy features disabled for ACPI enabled system */ #ifdef OMNIBOOK_STANDALONE @@ -185,7 +164,11 @@ void omnibook_report_key(struct input_dev *dev, unsigned int keycode); #else #undef CONFIG_OMNIBOOK_BACKLIGHT #endif /* BACKLIGHT_CLASS_DEVICE */ -#undef CONFIG_OMNIBOOK_LEGACY +#ifdef CONFIG_ACPI_EC +#undef CONFIG_OMNIBOOK_LEGACY +#else +#define CONFIG_OMNIBOOK_LEGACY +#endif /* CONFIG_ACPI_EC */ #endif /* OMNIBOOK_STANDALONE */ /* End of file */ diff --git a/pio.c b/pio.c index e3d3a93..4e197e9 100644 --- a/pio.c +++ b/pio.c @@ -35,25 +35,25 @@ * only at module init/exit time so there is no need for a lock. */ -struct pio_private_data_t { +struct pio_priv_data_t { unsigned long addr; struct kref refcount; struct list_head list; }; -static struct pio_private_data_t pio_private_data = { +static struct pio_priv_data_t pio_priv_data = { .addr = 0, - .list = LIST_HEAD_INIT(pio_private_data.list), + .list = LIST_HEAD_INIT(pio_priv_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, +static struct pio_priv_data_t *omnibook_match_port(struct pio_priv_data_t *data, unsigned long maddr) { - struct pio_private_data_t *cursor; + struct pio_priv_data_t *cursor; list_for_each_entry(cursor, &data->list, list) { if (cursor->addr == maddr) { @@ -66,9 +66,9 @@ static struct pio_private_data_t *omnibook_match_port(struct pio_private_data_t /* * See if we have to request raddr */ -static int omnibook_claim_port(struct pio_private_data_t *data, unsigned long raddr) +static int omnibook_claim_port(struct pio_priv_data_t *data, unsigned long raddr) { - struct pio_private_data_t *match, *new; + struct pio_priv_data_t *match, *new; match = omnibook_match_port(data, raddr); if (match) { @@ -83,7 +83,7 @@ static int omnibook_claim_port(struct pio_private_data_t *data, unsigned long ra return -ENODEV; } - new = kmalloc(sizeof(struct pio_private_data_t), GFP_KERNEL); + new = kmalloc(sizeof(struct pio_priv_data_t), GFP_KERNEL); if (!new) { release_region(raddr, 1); return -ENOMEM; @@ -119,9 +119,9 @@ static int omnibook_pio_init(const struct omnibook_operation *io_op) */ static void omnibook_free_port(struct kref *ref) { - struct pio_private_data_t *data; + struct pio_priv_data_t *data; - data = container_of(ref, struct pio_private_data_t, refcount); + data = container_of(ref, struct pio_priv_data_t, refcount); release_region(data->addr, 1); list_del(&data->list); kfree(data); @@ -132,7 +132,7 @@ static void omnibook_free_port(struct kref *ref) */ static void omnibook_pio_exit(const struct omnibook_operation *io_op) { - struct pio_private_data_t *match; + struct pio_priv_data_t *match; match = omnibook_match_port(io_op->backend->data, io_op->read_addr); if (match) @@ -164,7 +164,7 @@ static int omnibook_io_write(const struct omnibook_operation *io_op, u8 value) */ struct omnibook_backend pio_backend = { .name = "pio", - .data = &pio_private_data, + .data = &pio_priv_data, .init = omnibook_pio_init, .exit = omnibook_pio_exit, .byte_read = omnibook_io_read, diff --git a/polling.c b/polling.c index 3befba9..78b10b3 100644 --- a/polling.c +++ b/polling.c @@ -36,11 +36,11 @@ */ static struct workqueue_struct *omnibook_wq; static int key_polling_enabled; -DEFINE_MUTEX(poll_mutex); +static DEFINE_MUTEX(poll_mutex); static void omnibook_key_poller(void *data); static struct omnibook_feature key_polling_driver; -DECLARE_WORK(omnibook_poll_work, *omnibook_key_poller, &key_polling_driver.io_op); +static DECLARE_WORK(omnibook_poll_work, *omnibook_key_poller, &key_polling_driver.io_op); static struct input_dev *poll_input_dev; -- 2.43.5