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