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