[PATCH 1/3] UBUNTU: SAUCE: toshiba_acpi -- pull in current -dev version of driver
Andy Whitcroft
apw at canonical.com
Sat Jan 31 15:07:56 UTC 2009
OriginalLocation: http://memebeam.org/free-software/toshiba_acpi/toshiba_acpi-dev_toshiba_test5-linux_2.6.26.patch
Bug: #269831
Pull in the current version of the -dev version of the toshiba_acpi
driver. Forward ported to 2.6.28, modified the version number to make
it cleaner.
Signed-off-by: Andy Whitcroft <apw at canonical.com>
---
drivers/acpi/toshiba_acpi.c | 210 ++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 209 insertions(+), 1 deletions(-)
diff --git a/drivers/acpi/toshiba_acpi.c b/drivers/acpi/toshiba_acpi.c
index 40e60fc..1165bad 100644
--- a/drivers/acpi/toshiba_acpi.c
+++ b/drivers/acpi/toshiba_acpi.c
@@ -29,12 +29,26 @@
* Yasushi Nagato - changes for linux kernel 2.4 -> 2.5
* Rob Miller - TV out and hotkeys help
*
+ * PLEASE NOTE
+ *
+ * This is an experimental version of toshiba_acpi which includes emulation
+ * of the original toshiba driver's /proc/toshiba and /dev/toshiba,
+ * allowing Toshiba userspace utilities to work. The relevant code was
+ * based on toshiba.c (copyright 1996-2001 Jonathan A. Buzzard) and
+ * incorporated into this driver with help from Gintautas Miliauskas,
+ * Charles Schwieters, and Christoph Burger-Scheidlin.
+ *
+ * Caveats:
+ * * hotkey status in /proc/toshiba is not implemented
+ * * to make accesses to /dev/toshiba load this driver instead of
+ * the original driver, you will have to modify your module
+ * auto-loading configuration
*
* TODO
*
*/
-#define TOSHIBA_ACPI_VERSION "0.19"
+#define TOSHIBA_ACPI_VERSION "0.19-dev"
#define PROC_INTERFACE_VERSION 1
#include <linux/kernel.h>
@@ -42,6 +56,10 @@
#include <linux/init.h>
#include <linux/types.h>
#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/miscdevice.h>
+#include <linux/toshiba.h>
+#include <asm/io.h>
#include <linux/backlight.h>
#include <linux/platform_device.h>
#include <linux/rfkill.h>
@@ -654,6 +672,191 @@ static char *read_version(char *p)
return p;
}
+/* /dev/toshiba and /proc/toshiba handlers {{{
+ *
+ * ISSUE: lots of magic numbers and mysterious code
+ */
+
+#define TOSH_MINOR_DEV 181
+#define OLD_PROC_TOSHIBA "toshiba"
+
+static int
+tosh_acpi_bridge(SMMRegisters* regs)
+{
+ acpi_status status;
+
+ /* assert(sizeof(SMMRegisters) == sizeof(u32)*HCI_WORDS); */
+ status = hci_raw((u32*)regs, (u32*)regs);
+ if (status == AE_OK && (regs->eax & 0xff00) == HCI_SUCCESS)
+ return 0;
+
+ return -EINVAL;
+}
+
+static int
+tosh_ioctl(struct inode* ip, struct file* fp, unsigned int cmd,
+ unsigned long arg)
+{
+ SMMRegisters regs;
+ unsigned short ax,bx;
+ int err;
+
+ if ((!arg) || (cmd != TOSH_SMM))
+ return -EINVAL;
+
+ if (copy_from_user(®s, (SMMRegisters*)arg, sizeof(SMMRegisters)))
+ return -EFAULT;
+
+ ax = regs.eax & 0xff00;
+ bx = regs.ebx & 0xffff;
+
+ /* block HCI calls to read/write memory & PCI devices */
+ if (((ax==HCI_SET) || (ax==HCI_GET)) && (bx>0x0069))
+ return -EINVAL;
+
+ err = tosh_acpi_bridge(®s);
+
+ if (copy_to_user((SMMRegisters*)arg, ®s, sizeof(SMMRegisters)))
+ return -EFAULT;
+
+ return err;
+}
+
+static int
+tosh_get_machine_id(void __iomem *bios)
+{
+ int id;
+ unsigned short bx,cx;
+ unsigned long address;
+
+ id = (0x100*(int) readb(bios+0xfffe))+((int) readb(bios+0xfffa));
+
+ /* do we have a SCTTable machine identication number on our hands */
+ if (id==0xfc2f) {
+ bx = 0xe6f5; /* cheat */
+ /* now twiddle with our pointer a bit */
+ address = 0x00000000 + bx;
+ cx = readw(bios + address);
+ address = 0x00000009 + bx + cx;
+ cx = readw(bios + address);
+ address = 0x0000000a + cx;
+ cx = readw(bios + address);
+ /* now construct our machine identification number */
+ id = ((cx & 0xff)<<8)+((cx & 0xff00)>>8);
+ }
+
+ return id;
+}
+
+static int tosh_id;
+static int tosh_bios;
+static int tosh_date;
+static int tosh_sci;
+
+static struct file_operations tosh_fops = {
+ .owner = THIS_MODULE,
+ .ioctl = tosh_ioctl
+};
+
+static struct miscdevice tosh_device = {
+ TOSH_MINOR_DEV,
+ "toshiba",
+ &tosh_fops
+};
+
+static void
+setup_tosh_info(void __iomem *bios)
+{
+ int major, minor;
+ int day, month, year;
+
+ tosh_id = tosh_get_machine_id(bios);
+
+ /* get the BIOS version */
+ major = readb(bios + 0xe009)-'0';
+ minor = ((readb(bios + 0xe00b)-'0')*10)+(readb(bios + 0xe00c)-'0');
+ tosh_bios = (major*0x100)+minor;
+
+ /* get the BIOS date */
+ day = ((readb(bios + 0xfff5)-'0')*10)+(readb(bios + 0xfff6)-'0');
+ month = ((readb(bios + 0xfff8)-'0')*10)+(readb(bios + 0xfff9)-'0');
+ year = ((readb(bios + 0xfffb)-'0')*10)+(readb(bios + 0xfffc)-'0');
+ tosh_date = (((year-90) & 0x1f)<<10) | ((month & 0xf)<<6)
+ | ((day & 0x1f)<<1);
+}
+
+/* /proc/toshiba read handler */
+static int
+tosh_proc_show(struct seq_file *m, void *v)
+{
+ /* TODO: tosh_fn_status() */
+ int key = 0;
+
+ /* Format:
+ * 0) Linux driver version (this will change if format changes)
+ * 1) Machine ID
+ * 2) SCI version
+ * 3) BIOS version (major, minor)
+ * 4) BIOS date (in SCI date format)
+ * 5) Fn Key status
+ */
+
+ seq_printf(m, "1.1 0x%04x %d.%d %d.%d 0x%04x 0x%02x\n",
+ tosh_id,
+ (tosh_sci & 0xff00)>>8,
+ tosh_sci & 0xff,
+ (tosh_bios & 0xff00)>>8,
+ tosh_bios & 0xff,
+ tosh_date,
+ key);
+
+ return 0;
+}
+
+static int tosh_proc_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, tosh_proc_show, NULL);
+}
+
+static const struct file_operations tosh_proc_fops = {
+ .owner = THIS_MODULE,
+ .open = tosh_proc_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int __init
+old_driver_emulation_init(void)
+{
+ int status;
+ void __iomem *bios = ioremap(0xf0000, 0x10000);
+ if (!bios)
+ return -ENOMEM;
+
+ if ((status = misc_register(&tosh_device))) {
+ printk(MY_ERR "failed to register misc device %d (\"%s\")\n",
+ tosh_device.minor, tosh_device.name);
+ return status;
+ }
+
+ setup_tosh_info(bios);
+ proc_create(OLD_PROC_TOSHIBA, 0, NULL, &tosh_proc_fops);
+
+ iounmap(bios);
+
+ return 0;
+}
+
+static void __exit
+old_driver_emulation_exit(void)
+{
+ remove_proc_entry(OLD_PROC_TOSHIBA, NULL);
+ misc_deregister(&tosh_device);
+}
+
+/* }}} end of /dev/toshiba and /proc/toshiba handlers */
+
/* proc and module init
*/
@@ -720,6 +923,8 @@ static void toshiba_acpi_exit(void)
if (toshiba_proc_dir)
remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
+ old_driver_emulation_exit();
+
platform_device_unregister(toshiba_acpi.p_dev);
return;
@@ -761,6 +966,9 @@ static int __init toshiba_acpi_init(void)
return ret;
}
+ if ((ret = old_driver_emulation_init()))
+ return ret;
+
force_fan = 0;
key_event_valid = 0;
--
1.6.1.2.419.g0d87e
More information about the kernel-team
mailing list