]>
Commit | Line | Data |
---|---|---|
2380c486 JR |
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 | |
1221cc69 | 3 | @@ -28,14 +28,28 @@ |
4a638a57 JR |
4 | * Yasushi Nagato - changes for linux kernel 2.4 -> 2.5 |
5 | * Rob Miller - TV out and hotkeys help | |
6 | * | |
7 | + * PLEASE NOTE | |
8 | + * | |
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. | |
15 | + * | |
16 | + * Caveats: | |
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 | |
21 | * | |
22 | * TODO | |
23 | * | |
24 | */ | |
25 | ||
1221cc69 JR |
26 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
27 | ||
2380c486 | 28 | -#define TOSHIBA_ACPI_VERSION "0.19" |
4a638a57 JR |
29 | +#define TOSHIBA_ACPI_VERSION "experimental-dev-toshiba-test-5" |
30 | #define PROC_INTERFACE_VERSION 1 | |
31 | ||
32 | #include <linux/kernel.h> | |
f94a416f | 33 | @@ -60,6 +60,9 @@ |
f94a416f | 34 | #include <linux/rfkill.h> |
d031c9d6 | 35 | #include <linux/input.h> |
36 | #include <linux/slab.h> | |
4a638a57 JR |
37 | +#include <linux/miscdevice.h> |
38 | +#include <linux/toshiba.h> | |
39 | +#include <asm/io.h> | |
4a638a57 JR |
40 | |
41 | #include <asm/uaccess.h> | |
f94a416f | 42 | |
5f2a5423 | 43 | @@ -497,6 +515,191 @@ |
4a638a57 JR |
44 | return p; |
45 | } | |
46 | ||
47 | +/* /dev/toshiba and /proc/toshiba handlers {{{ | |
48 | + * | |
49 | + * ISSUE: lots of magic numbers and mysterious code | |
50 | + */ | |
51 | + | |
52 | +#define TOSH_MINOR_DEV 181 | |
53 | +#define OLD_PROC_TOSHIBA "toshiba" | |
54 | + | |
55 | +static int | |
56 | +tosh_acpi_bridge(SMMRegisters* regs) | |
57 | +{ | |
58 | + acpi_status status; | |
59 | + | |
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) | |
63 | + return 0; | |
64 | + | |
65 | + return -EINVAL; | |
66 | +} | |
67 | + | |
68 | +static int | |
69 | +tosh_ioctl(struct inode* ip, struct file* fp, unsigned int cmd, | |
70 | + unsigned long arg) | |
71 | +{ | |
72 | + SMMRegisters regs; | |
73 | + unsigned short ax,bx; | |
74 | + int err; | |
75 | + | |
76 | + if ((!arg) || (cmd != TOSH_SMM)) | |
77 | + return -EINVAL; | |
78 | + | |
79 | + if (copy_from_user(®s, (SMMRegisters*)arg, sizeof(SMMRegisters))) | |
80 | + return -EFAULT; | |
81 | + | |
82 | + ax = regs.eax & 0xff00; | |
83 | + bx = regs.ebx & 0xffff; | |
84 | + | |
85 | + /* block HCI calls to read/write memory & PCI devices */ | |
86 | + if (((ax==HCI_SET) || (ax==HCI_GET)) && (bx>0x0069)) | |
87 | + return -EINVAL; | |
88 | + | |
89 | + err = tosh_acpi_bridge(®s); | |
90 | + | |
91 | + if (copy_to_user((SMMRegisters*)arg, ®s, sizeof(SMMRegisters))) | |
92 | + return -EFAULT; | |
93 | + | |
94 | + return err; | |
95 | +} | |
96 | + | |
97 | +static int | |
98 | +tosh_get_machine_id(void __iomem *bios) | |
99 | +{ | |
100 | + int id; | |
101 | + unsigned short bx,cx; | |
102 | + unsigned long address; | |
103 | + | |
104 | + id = (0x100*(int) readb(bios+0xfffe))+((int) readb(bios+0xfffa)); | |
105 | + | |
106 | + /* do we have a SCTTable machine identication number on our hands */ | |
107 | + if (id==0xfc2f) { | |
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); | |
118 | + } | |
119 | + | |
120 | + return id; | |
121 | +} | |
122 | + | |
123 | +static int tosh_id; | |
124 | +static int tosh_bios; | |
125 | +static int tosh_date; | |
126 | +static int tosh_sci; | |
127 | + | |
128 | +static struct file_operations tosh_fops = { | |
129 | + .owner = THIS_MODULE, | |
018b2597 | 130 | + .unlocked_ioctl = tosh_ioctl |
4a638a57 JR |
131 | +}; |
132 | + | |
133 | +static struct miscdevice tosh_device = { | |
134 | + TOSH_MINOR_DEV, | |
135 | + "toshiba", | |
136 | + &tosh_fops | |
137 | +}; | |
138 | + | |
139 | +static void | |
140 | +setup_tosh_info(void __iomem *bios) | |
141 | +{ | |
142 | + int major, minor; | |
143 | + int day, month, year; | |
144 | + | |
145 | + tosh_id = tosh_get_machine_id(bios); | |
146 | + | |
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; | |
151 | + | |
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); | |
158 | +} | |
159 | + | |
160 | +/* /proc/toshiba read handler */ | |
161 | +static int | |
5f2a5423 | 162 | +tosh_proc_show(struct seq_file *m, void *v) |
4a638a57 | 163 | +{ |
4a638a57 JR |
164 | + /* TODO: tosh_fn_status() */ |
165 | + int key = 0; | |
166 | + | |
167 | + /* Format: | |
168 | + * 0) Linux driver version (this will change if format changes) | |
169 | + * 1) Machine ID | |
170 | + * 2) SCI version | |
171 | + * 3) BIOS version (major, minor) | |
172 | + * 4) BIOS date (in SCI date format) | |
173 | + * 5) Fn Key status | |
174 | + */ | |
175 | + | |
5f2a5423 | 176 | + seq_printf(m, "1.1 0x%04x %d.%d %d.%d 0x%04x 0x%02x\n", |
4a638a57 JR |
177 | + tosh_id, |
178 | + (tosh_sci & 0xff00)>>8, | |
179 | + tosh_sci & 0xff, | |
180 | + (tosh_bios & 0xff00)>>8, | |
181 | + tosh_bios & 0xff, | |
182 | + tosh_date, | |
183 | + key); | |
184 | + | |
5f2a5423 PS |
185 | + return 0; |
186 | +} | |
187 | + | |
188 | +static int tosh_proc_open(struct inode *inode, struct file *file) | |
189 | +{ | |
190 | + return single_open(file, tosh_proc_show, NULL); | |
4a638a57 JR |
191 | +} |
192 | + | |
5f2a5423 PS |
193 | +static const struct file_operations tosh_proc_fops = { |
194 | + .owner = THIS_MODULE, | |
195 | + .open = tosh_proc_open, | |
196 | + .read = seq_read, | |
197 | + .llseek = seq_lseek, | |
198 | + .release = single_release, | |
199 | +}; | |
200 | + | |
4a638a57 JR |
201 | +static int __init |
202 | +old_driver_emulation_init(void) | |
203 | +{ | |
204 | + int status; | |
205 | + void __iomem *bios = ioremap(0xf0000, 0x10000); | |
206 | + if (!bios) | |
207 | + return -ENOMEM; | |
208 | + | |
209 | + if ((status = misc_register(&tosh_device))) { | |
2c0fa008 | 210 | + pr_err("failed to register misc device %d (\"%s\")\n", |
4a638a57 JR |
211 | + tosh_device.minor, tosh_device.name); |
212 | + return status; | |
213 | + } | |
214 | + | |
215 | + setup_tosh_info(bios); | |
5f2a5423 | 216 | + proc_create(OLD_PROC_TOSHIBA, 0, NULL, &tosh_proc_fops); |
4a638a57 JR |
217 | + |
218 | + iounmap(bios); | |
219 | + | |
220 | + return 0; | |
221 | +} | |
222 | + | |
223 | +static void __exit | |
224 | +old_driver_emulation_exit(void) | |
225 | +{ | |
226 | + remove_proc_entry(OLD_PROC_TOSHIBA, NULL); | |
227 | + misc_deregister(&tosh_device); | |
228 | +} | |
229 | + | |
230 | +/* }}} end of /dev/toshiba and /proc/toshiba handlers */ | |
231 | + | |
232 | /* proc and module init | |
233 | */ | |
234 | ||
5f2a5423 | 235 | @@ -555,6 +758,8 @@ |
4a638a57 JR |
236 | if (toshiba_proc_dir) |
237 | remove_proc_entry(PROC_TOSHIBA, acpi_root_dir); | |
238 | ||
239 | + old_driver_emulation_exit(); | |
240 | + | |
241 | return; | |
242 | } | |
243 | ||
5f2a5423 | 244 | @@ -562,6 +767,7 @@ |
4a638a57 JR |
245 | { |
246 | acpi_status status = AE_OK; | |
247 | u32 hci_result; | |
248 | + int status2; | |
2380c486 JR |
249 | bool bt_present; |
250 | bool bt_on; | |
251 | bool radio_on; | |
5f2a5423 | 252 | @@ -578,6 +784,9 @@ |
4a638a57 | 253 | TOSHIBA_ACPI_VERSION); |
2c0fa008 | 254 | pr_info(" HCI method: %s\n", method_hci); |
4a638a57 JR |
255 | |
256 | + if ((status2 = old_driver_emulation_init())) | |
257 | + return status2; | |
258 | + | |
259 | force_fan = 0; | |
260 | key_event_valid = 0; | |
261 |