]>
Commit | Line | Data |
---|---|---|
7f651772 | 1 | --- linux-2.6.21/drivers/acpi/toshiba_acpi.c.21.orig 2007-04-28 00:49:26.000000000 +0300 |
2 | +++ linux-2.6.21/drivers/acpi/toshiba_acpi.c 2007-05-15 19:23:32.000000000 +0300 | |
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 | ||
26 | -#define TOSHIBA_ACPI_VERSION "0.18" | |
27 | +#define TOSHIBA_ACPI_VERSION "experimental-dev-toshiba-test-5" | |
28 | #define PROC_INTERFACE_VERSION 1 | |
29 | ||
30 | #include <linux/kernel.h> | |
31 | @@ -41,6 +55,9 @@ | |
32 | #include <linux/init.h> | |
33 | #include <linux/types.h> | |
34 | #include <linux/proc_fs.h> | |
35 | +#include <linux/miscdevice.h> | |
36 | +#include <linux/toshiba.h> | |
37 | +#include <asm/io.h> | |
38 | #include <linux/backlight.h> | |
39 | ||
40 | #include <asm/uaccess.h> | |
41 | @@ -490,6 +507,179 @@ | |
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 | |
160 | +tosh_get_info(char* buffer, char** start, off_t fpos, int length) | |
161 | +{ | |
162 | + char* temp = buffer; | |
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 | + | |
175 | + temp += sprintf(temp, "1.1 0x%04x %d.%d %d.%d 0x%04x 0x%02x\n", | |
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 | + | |
184 | + return temp-buffer; | |
185 | +} | |
186 | + | |
187 | +static int __init | |
188 | +old_driver_emulation_init(void) | |
189 | +{ | |
190 | + int status; | |
191 | + void __iomem *bios = ioremap(0xf0000, 0x10000); | |
192 | + if (!bios) | |
193 | + return -ENOMEM; | |
194 | + | |
195 | + if ((status = misc_register(&tosh_device))) { | |
196 | + printk(MY_ERR "failed to register misc device %d (\"%s\")\n", | |
197 | + tosh_device.minor, tosh_device.name); | |
198 | + return status; | |
199 | + } | |
200 | + | |
201 | + setup_tosh_info(bios); | |
202 | + create_proc_info_entry(OLD_PROC_TOSHIBA, 0, NULL, tosh_get_info); | |
203 | + | |
204 | + iounmap(bios); | |
205 | + | |
206 | + return 0; | |
207 | +} | |
208 | + | |
209 | +static void __exit | |
210 | +old_driver_emulation_exit(void) | |
211 | +{ | |
212 | + remove_proc_entry(OLD_PROC_TOSHIBA, NULL); | |
213 | + misc_deregister(&tosh_device); | |
214 | +} | |
215 | + | |
216 | +/* }}} end of /dev/toshiba and /proc/toshiba handlers */ | |
217 | + | |
218 | /* proc and module init | |
219 | */ | |
220 | ||
221 | @@ -548,6 +738,8 @@ | |
222 | if (toshiba_proc_dir) | |
223 | remove_proc_entry(PROC_TOSHIBA, acpi_root_dir); | |
224 | ||
225 | + old_driver_emulation_exit(); | |
226 | + | |
227 | return; | |
228 | } | |
229 | ||
230 | @@ -555,6 +747,7 @@ | |
231 | { | |
232 | acpi_status status = AE_OK; | |
233 | u32 hci_result; | |
234 | + int status2; | |
235 | ||
236 | if (acpi_disabled) | |
237 | return -ENODEV; | |
238 | @@ -571,6 +764,9 @@ | |
239 | TOSHIBA_ACPI_VERSION); | |
240 | printk(MY_INFO " HCI method: %s\n", method_hci); | |
241 | ||
242 | + if ((status2 = old_driver_emulation_init())) | |
243 | + return status2; | |
244 | + | |
245 | force_fan = 0; | |
246 | key_event_valid = 0; | |
247 |