1 ---- linux-2.6/drivers/platform/x86/toshiba_acpi.c.orig 2008-08-30 22:12:50.000000000 -0700
2 +++ linux-2.6/drivers/platform/x86/toshiba_acpi.c 2008-08-31 12:03:07.000000000 -0700
4 * Yasushi Nagato - changes for linux kernel 2.4 -> 2.5
5 * Rob Miller - TV out and hotkeys help
9 + * This is an experimental version of toshiba_acpi which includes emulation
10 + * of the original toshiba driver's /proc/toshiba and /dev/toshiba,
11 + * allowing Toshiba userspace utilities to work. The relevant code was
12 + * based on toshiba.c (copyright 1996-2001 Jonathan A. Buzzard) and
13 + * incorporated into this driver with help from Gintautas Miliauskas,
14 + * Charles Schwieters, and Christoph Burger-Scheidlin.
17 + * * hotkey status in /proc/toshiba is not implemented
18 + * * to make accesses to /dev/toshiba load this driver instead of
19 + * the original driver, you will have to modify your module
20 + * auto-loading configuration
26 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
28 -#define TOSHIBA_ACPI_VERSION "0.19"
29 +#define TOSHIBA_ACPI_VERSION "experimental-dev-toshiba-test-5"
30 #define PROC_INTERFACE_VERSION 1
32 #include <linux/kernel.h>
34 #include <linux/rfkill.h>
35 #include <linux/input.h>
36 #include <linux/slab.h>
37 +#include <linux/miscdevice.h>
38 +#include <linux/toshiba.h>
41 #include <asm/uaccess.h>
47 +/* /dev/toshiba and /proc/toshiba handlers {{{
49 + * ISSUE: lots of magic numbers and mysterious code
52 +#define TOSH_MINOR_DEV 181
53 +#define OLD_PROC_TOSHIBA "toshiba"
56 +tosh_acpi_bridge(SMMRegisters* regs)
60 + /* assert(sizeof(SMMRegisters) == sizeof(u32)*HCI_WORDS); */
61 + status = hci_raw((u32*)regs, (u32*)regs);
62 + if (status == AE_OK && (regs->eax & 0xff00) == HCI_SUCCESS)
69 +tosh_ioctl(struct inode* ip, struct file* fp, unsigned int cmd,
73 + unsigned short ax,bx;
76 + if ((!arg) || (cmd != TOSH_SMM))
79 + if (copy_from_user(®s, (SMMRegisters*)arg, sizeof(SMMRegisters)))
82 + ax = regs.eax & 0xff00;
83 + bx = regs.ebx & 0xffff;
85 + /* block HCI calls to read/write memory & PCI devices */
86 + if (((ax==HCI_SET) || (ax==HCI_GET)) && (bx>0x0069))
89 + err = tosh_acpi_bridge(®s);
91 + if (copy_to_user((SMMRegisters*)arg, ®s, sizeof(SMMRegisters)))
98 +tosh_get_machine_id(void __iomem *bios)
101 + unsigned short bx,cx;
102 + unsigned long address;
104 + id = (0x100*(int) readb(bios+0xfffe))+((int) readb(bios+0xfffa));
106 + /* do we have a SCTTable machine identication number on our hands */
108 + bx = 0xe6f5; /* cheat */
109 + /* now twiddle with our pointer a bit */
110 + address = 0x00000000 + bx;
111 + cx = readw(bios + address);
112 + address = 0x00000009 + bx + cx;
113 + cx = readw(bios + address);
114 + address = 0x0000000a + cx;
115 + cx = readw(bios + address);
116 + /* now construct our machine identification number */
117 + id = ((cx & 0xff)<<8)+((cx & 0xff00)>>8);
124 +static int tosh_bios;
125 +static int tosh_date;
126 +static int tosh_sci;
128 +static struct file_operations tosh_fops = {
129 + .owner = THIS_MODULE,
130 + .unlocked_ioctl = tosh_ioctl
133 +static struct miscdevice tosh_device = {
140 +setup_tosh_info(void __iomem *bios)
143 + int day, month, year;
145 + tosh_id = tosh_get_machine_id(bios);
147 + /* get the BIOS version */
148 + major = readb(bios + 0xe009)-'0';
149 + minor = ((readb(bios + 0xe00b)-'0')*10)+(readb(bios + 0xe00c)-'0');
150 + tosh_bios = (major*0x100)+minor;
152 + /* get the BIOS date */
153 + day = ((readb(bios + 0xfff5)-'0')*10)+(readb(bios + 0xfff6)-'0');
154 + month = ((readb(bios + 0xfff8)-'0')*10)+(readb(bios + 0xfff9)-'0');
155 + year = ((readb(bios + 0xfffb)-'0')*10)+(readb(bios + 0xfffc)-'0');
156 + tosh_date = (((year-90) & 0x1f)<<10) | ((month & 0xf)<<6)
157 + | ((day & 0x1f)<<1);
160 +/* /proc/toshiba read handler */
162 +tosh_proc_show(struct seq_file *m, void *v)
164 + /* TODO: tosh_fn_status() */
168 + * 0) Linux driver version (this will change if format changes)
171 + * 3) BIOS version (major, minor)
172 + * 4) BIOS date (in SCI date format)
176 + seq_printf(m, "1.1 0x%04x %d.%d %d.%d 0x%04x 0x%02x\n",
178 + (tosh_sci & 0xff00)>>8,
180 + (tosh_bios & 0xff00)>>8,
188 +static int tosh_proc_open(struct inode *inode, struct file *file)
190 + return single_open(file, tosh_proc_show, NULL);
193 +static const struct file_operations tosh_proc_fops = {
194 + .owner = THIS_MODULE,
195 + .open = tosh_proc_open,
197 + .llseek = seq_lseek,
198 + .release = single_release,
202 +old_driver_emulation_init(void)
205 + void __iomem *bios = ioremap(0xf0000, 0x10000);
209 + if ((status = misc_register(&tosh_device))) {
210 + pr_err("failed to register misc device %d (\"%s\")\n",
211 + tosh_device.minor, tosh_device.name);
215 + setup_tosh_info(bios);
216 + proc_create(OLD_PROC_TOSHIBA, 0, NULL, &tosh_proc_fops);
224 +old_driver_emulation_exit(void)
226 + remove_proc_entry(OLD_PROC_TOSHIBA, NULL);
227 + misc_deregister(&tosh_device);
230 +/* }}} end of /dev/toshiba and /proc/toshiba handlers */
232 /* proc and module init
236 if (toshiba_proc_dir)
237 remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
239 + old_driver_emulation_exit();
246 acpi_status status = AE_OK;
253 TOSHIBA_ACPI_VERSION);
254 pr_info(" HCI method: %s\n", method_hci);
256 + if ((status2 = old_driver_emulation_init()))