Initial commit: Uploaded everything from abs/core
[arch-rock.git] / base / kernel26 / toshiba-acpi.patch
blob6bcd479b70f5df9ed4d7f7899fce82de5843fc08
1 --- linux-2.6.20/drivers/acpi/toshiba_acpi.c.orig 2006-06-22 21:39:40.000000000 -0400
2 +++ linux-2.6.20/drivers/acpi/toshiba_acpi.c 2006-06-22 21:48:07.000000000 -0400
3 @@ -28,12 +28,26 @@
4 * Yasushi Nagato - changes for linux kernel 2.4 -> 2.5
5 * Rob Miller - TV out and hotkeys help
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
22 * TODO
26 -#define TOSHIBA_ACPI_VERSION "0.18-p1"
27 +#define TOSHIBA_ACPI_VERSION "experimental-dev-toshiba-test-5"
28 #define PROC_INTERFACE_VERSION 1
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>
40 #include <asm/uaccess.h>
41 @@ -463,6 +480,179 @@
42 return p;
45 +/* /dev/toshiba and /proc/toshiba handlers {{{
46 + *
47 + * ISSUE: lots of magic numbers and mysterious code
48 + */
50 +#define TOSH_MINOR_DEV 181
51 +#define OLD_PROC_TOSHIBA "toshiba"
53 +static int
54 +tosh_acpi_bridge(SMMRegisters* regs)
56 + acpi_status status;
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;
63 + return -EINVAL;
66 +static int
67 +tosh_ioctl(struct inode* ip, struct file* fp, unsigned int cmd,
68 + unsigned long arg)
70 + SMMRegisters regs;
71 + unsigned short ax,bx;
72 + int err;
74 + if ((!arg) || (cmd != TOSH_SMM))
75 + return -EINVAL;
77 + if (copy_from_user(&regs, (SMMRegisters*)arg, sizeof(SMMRegisters)))
78 + return -EFAULT;
80 + ax = regs.eax & 0xff00;
81 + bx = regs.ebx & 0xffff;
83 + /* block HCI calls to read/write memory & PCI devices */
84 + if (((ax==HCI_SET) || (ax==HCI_GET)) && (bx>0x0069))
85 + return -EINVAL;
87 + err = tosh_acpi_bridge(&regs);
89 + if (copy_to_user((SMMRegisters*)arg, &regs, sizeof(SMMRegisters)))
90 + return -EFAULT;
92 + return err;
95 +static int
96 +tosh_get_machine_id(void __iomem *bios)
98 + int id;
99 + unsigned short bx,cx;
100 + unsigned long address;
102 + id = (0x100*(int) readb(bios+0xfffe))+((int) readb(bios+0xfffa));
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);
118 + return id;
121 +static int tosh_id;
122 +static int tosh_bios;
123 +static int tosh_date;
124 +static int tosh_sci;
126 +static struct file_operations tosh_fops = {
127 + .owner = THIS_MODULE,
128 + .ioctl = tosh_ioctl
131 +static struct miscdevice tosh_device = {
132 + TOSH_MINOR_DEV,
133 + "toshiba",
134 + &tosh_fops
137 +static void
138 +setup_tosh_info(void __iomem *bios)
140 + int major, minor;
141 + int day, month, year;
143 + tosh_id = tosh_get_machine_id(bios);
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;
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);
158 +/* /proc/toshiba read handler */
159 +static int
160 +tosh_get_info(char* buffer, char** start, off_t fpos, int length)
162 + char* temp = buffer;
163 + /* TODO: tosh_fn_status() */
164 + int key = 0;
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 + */
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);
184 + return temp-buffer;
187 +static int __init
188 +old_driver_emulation_init(void)
190 + int status;
191 + void __iomem *bios = ioremap(0xf0000, 0x10000);
192 + if (!bios)
193 + return -ENOMEM;
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;
201 + setup_tosh_info(bios);
202 + create_proc_info_entry(OLD_PROC_TOSHIBA, 0, NULL, tosh_get_info);
204 + iounmap(bios);
206 + return 0;
209 +static void __exit
210 +old_driver_emulation_exit(void)
212 + remove_proc_entry(OLD_PROC_TOSHIBA, NULL);
213 + misc_deregister(&tosh_device);
216 +/* }}} end of /dev/toshiba and /proc/toshiba handlers */
218 /* proc and module init
221 @@ -510,6 +700,7 @@
223 acpi_status status = AE_OK;
224 u32 hci_result;
225 + int status2;
227 if (acpi_disabled)
228 return -ENODEV;
229 @@ -530,6 +721,9 @@
230 TOSHIBA_ACPI_VERSION);
231 printk(MY_INFO " HCI method: %s\n", method_hci);
233 + if ((status2 = old_driver_emulation_init()))
234 + return status2;
236 force_fan = 0;
237 key_event_valid = 0;
239 --- linux-2.6.20/drivers/acpi/toshiba_acpi.c~ 2007-04-09 15:50:40.000000000 +0200
240 +++ linux-2.6.20/drivers/acpi/toshiba_acpi.c 2007-04-09 15:56:34.000000000 +0200
241 @@ -556,6 +750,8 @@
242 if (toshiba_proc_dir)
243 remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
245 + old_driver_emulation_exit();
247 return;
250 --- linux-2.6.20/drivers/acpi/toshiba_acpi.c.orig 2007-02-03 21:59:12.000000000 -0800
251 +++ linux-2.6.20/drivers/acpi/toshiba_acpi.c 2007-02-04 12:06:54.000000000 -0800
252 @@ -27,6 +27,7 @@
253 * engineering the Windows drivers
254 * Yasushi Nagato - changes for linux kernel 2.4 -> 2.5
255 * Rob Miller - TV out and hotkeys help
256 + * Daniel Silverstone - Punting of hotkeys via acpi using a thread
258 * PLEASE NOTE
260 @@ -47,7 +48,7 @@
264 -#define TOSHIBA_ACPI_VERSION "experimental-dev-toshiba-test-5"
265 +#define TOSHIBA_ACPI_VERSION "0.19a-dev"
266 #define PROC_INTERFACE_VERSION 1
268 #include <linux/kernel.h>
269 @@ -55,15 +56,32 @@
270 #include <linux/init.h>
271 #include <linux/types.h>
272 #include <linux/proc_fs.h>
273 +#include <linux/delay.h>
274 +#include <linux/suspend.h>
275 #include <linux/miscdevice.h>
276 #include <linux/toshiba.h>
277 #include <asm/io.h>
278 #include <linux/backlight.h>
280 +#include <linux/freezer.h>
281 #include <asm/uaccess.h>
283 #include <acpi/acpi_drivers.h>
285 +/* Some compatibility for isa legacy interface */
286 +#ifndef isa_readb
288 +#define isa_readb(a) readb(__ISA_IO_base + (a))
289 +#define isa_readw(a) readw(__ISA_IO_base + (a))
290 +#define isa_readl(a) readl(__ISA_IO_base + (a))
291 +#define isa_writeb(b,a) writeb(b,__ISA_IO_base + (a))
292 +#define isa_writew(w,a) writew(w,__ISA_IO_base + (a))
293 +#define isa_writel(l,a) writel(l,__ISA_IO_base + (a))
294 +#define isa_memset_io(a,b,c) memset_io(__ISA_IO_base + (a),(b),(c))
295 +#define isa_memcpy_fromio(a,b,c) memcpy_fromio((a),__ISA_IO_base + (b),(c))
296 +#define isa_memcpy_toio(a,b,c) memcpy_toio(__ISA_IO_base + (a),(b),(c))
298 +#endif
300 MODULE_AUTHOR("John Belmonte");
301 MODULE_DESCRIPTION("Toshiba Laptop ACPI Extras Driver");
302 MODULE_LICENSE("GPL");
303 @@ -233,6 +251,11 @@
304 static int force_fan;
305 static int last_key_event;
306 static int key_event_valid;
307 +static int hotkeys_over_acpi = 1;
308 +static int hotkeys_check_per_sec = 2;
310 +module_param(hotkeys_over_acpi, uint, 0400);
311 +module_param(hotkeys_check_per_sec, uint, 0400);
312 static int arbitrary, arbitrary2, arbitrary1;
314 typedef struct _ProcItem {
315 @@ -460,27 +483,34 @@
316 u32 hci_result;
317 u32 value;
319 - if (!key_event_valid) {
320 - hci_read1(HCI_SYSTEM_EVENT, &value, &hci_result);
321 - if (hci_result == HCI_SUCCESS) {
322 - key_event_valid = 1;
323 - last_key_event = value;
324 - } else if (hci_result == HCI_EMPTY) {
325 - /* better luck next time */
326 - } else if (hci_result == HCI_NOT_SUPPORTED) {
327 - /* This is a workaround for an unresolved issue on
328 - * some machines where system events sporadically
329 - * become disabled. */
330 - hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result);
331 - printk(MY_NOTICE "Re-enabled hotkeys\n");
332 - } else {
333 - printk(MY_ERR "Error reading hotkey status\n");
334 - goto end;
335 + if (!hotkeys_over_acpi) {
336 + if (!key_event_valid) {
337 + hci_read1(HCI_SYSTEM_EVENT, &value, &hci_result);
338 + if (hci_result == HCI_SUCCESS) {
339 + key_event_valid = 1;
340 + last_key_event = value;
341 + } else if (hci_result == HCI_EMPTY) {
342 + /* better luck next time */
343 + } else if (hci_result == HCI_NOT_SUPPORTED) {
344 + /* This is a workaround for an
345 + * unresolved issue on some machines
346 + * where system events sporadically
347 + * become disabled. */
348 + hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result);
349 + printk(MY_NOTICE "Re-enabled hotkeys\n");
350 + } else {
351 + printk(MY_ERR "Error reading hotkey status\n");
352 + goto end;
355 + } else {
356 + key_event_valid = 0;
357 + last_key_event = 0;
360 p += sprintf(p, "hotkey_ready: %d\n", key_event_valid);
361 p += sprintf(p, "hotkey: 0x%04x\n", last_key_event);
362 + p += sprintf(p, "hotkeys_via_acpi: %d\n", hotkeys_over_acpi);
364 end:
365 return p;
366 @@ -558,24 +588,24 @@
369 static int
370 -tosh_get_machine_id(void __iomem *bios)
371 +tosh_get_machine_id(void)
373 int id;
374 unsigned short bx,cx;
375 unsigned long address;
377 - id = (0x100*(int) readb(bios+0xfffe))+((int) readb(bios+0xfffa));
378 + id = (0x100*(int)isa_readb(0xffffe))+((int)isa_readb(0xffffa));
380 /* do we have a SCTTable machine identication number on our hands */
381 if (id==0xfc2f) {
382 bx = 0xe6f5; /* cheat */
383 /* now twiddle with our pointer a bit */
384 - address = 0x00000000 + bx;
385 - cx = readw(bios + address);
386 - address = 0x00000009 + bx + cx;
387 - cx = readw(bios + address);
388 - address = 0x0000000a + cx;
389 - cx = readw(bios + address);
390 + address = 0x000f0000+bx;
391 + cx = isa_readw(address);
392 + address = 0x000f0009+bx+cx;
393 + cx = isa_readw(address);
394 + address = 0x000f000a+cx;
395 + cx = isa_readw(address);
396 /* now construct our machine identification number */
397 id = ((cx & 0xff)<<8)+((cx & 0xff00)>>8);
399 @@ -605,17 +635,17 @@
400 int major, minor;
401 int day, month, year;
403 - tosh_id = tosh_get_machine_id(bios);
404 + tosh_id = tosh_get_machine_id();
406 /* get the BIOS version */
407 - major = readb(bios + 0xe009)-'0';
408 - minor = ((readb(bios + 0xe00b)-'0')*10)+(readb(bios + 0xe00c)-'0');
409 + major = isa_readb(0xfe009)-'0';
410 + minor = ((isa_readb(0xfe00b)-'0')*10)+(isa_readb(0xfe00c)-'0');
411 tosh_bios = (major*0x100)+minor;
413 /* get the BIOS date */
414 - day = ((readb(bios + 0xfff5)-'0')*10)+(readb(bios + 0xfff6)-'0');
415 - month = ((readb(bios + 0xfff8)-'0')*10)+(readb(bios + 0xfff9)-'0');
416 - year = ((readb(bios + 0xfffb)-'0')*10)+(readb(bios + 0xfffc)-'0');
417 + day = ((isa_readb(0xffff5)-'0')*10)+(isa_readb(0xffff6)-'0');
418 + month = ((isa_readb(0xffff8)-'0')*10)+(isa_readb(0xffff9)-'0');
419 + year = ((isa_readb(0xffffb)-'0')*10)+(isa_readb(0xffffc)-'0');
420 tosh_date = (((year-90) & 0x1f)<<10) | ((month & 0xf)<<6)
421 | ((day & 0x1f)<<1);
423 @@ -730,11 +760,137 @@
424 .max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1,
427 +static struct semaphore thread_sem;
428 +static int thread_should_die;
430 +static struct acpi_device *threaded_device = 0;
432 +static void thread_deliver_button_event(u32 value)
434 + if (!threaded_device) return;
435 + if( value == 0x0100 ) {
436 + /* Ignore FN on its own */
437 + } else if( value & 0x80 ) {
438 + acpi_bus_generate_proc_event( threaded_device, 1, value & ~0x80 );
439 + } else {
440 + acpi_bus_generate_proc_event( threaded_device, 0, value );
444 +static int toshiba_acpi_thread(void *data)
446 + int dropped = 0;
447 + u32 hci_result, value;
449 + daemonize("ktoshkeyd");
450 + set_user_nice(current, 4);
451 + thread_should_die = 0;
453 + up(&thread_sem);
455 + do {
456 + /* In case we get stuck; we can rmmod the module here */
457 + if (thread_should_die)
458 + break;
460 + hci_read1(HCI_SYSTEM_EVENT, &value, &hci_result);
461 + if (hci_result == HCI_SUCCESS) {
462 + dropped++;
463 + } else if (hci_result == HCI_EMPTY) {
464 + /* better luck next time */
465 + } else if (hci_result == HCI_NOT_SUPPORTED) {
466 + /* This is a workaround for an unresolved issue on
467 + * some machines where system events sporadically
468 + * become disabled. */
469 + hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result);
470 + printk(MY_NOTICE "Re-enabled hotkeys\n");
472 + } while (hci_result != HCI_EMPTY);
474 + printk(MY_INFO "Dropped %d keys from the queue on startup\n", dropped);
476 + for (;;) {
477 + set_current_state(TASK_INTERRUPTIBLE);
478 + schedule_timeout(HZ / hotkeys_check_per_sec);
480 + if (thread_should_die)
481 + break;
483 + if (try_to_freeze())
484 + continue;
486 + do {
487 + hci_read1(HCI_SYSTEM_EVENT, &value, &hci_result);
488 + if (hci_result == HCI_SUCCESS) {
489 + thread_deliver_button_event(value);
490 + } else if (hci_result == HCI_EMPTY) {
491 + /* better luck next time */
492 + } else if (hci_result == HCI_NOT_SUPPORTED) {
493 + /* This is a workaround for an
494 + * unresolved issue on some machines
495 + * where system events sporadically
496 + * become disabled. */
497 + hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result);
498 + printk(MY_NOTICE "Re-enabled hotkeys\n");
500 + } while (hci_result == HCI_SUCCESS);
502 + set_user_nice(current, -20); /* Become nasty so we are cleaned up
503 + * before the module exits making us oops */
504 + up(&thread_sem);
505 + return 0;
508 +static int acpi_toshkeys_add (struct acpi_device *device)
510 + threaded_device = device;
511 + strcpy(acpi_device_name(device), "Toshiba laptop hotkeys");
512 + strcpy(acpi_device_class(device), "hkey");
513 + return 0;
516 +static int acpi_toshkeys_remove (struct acpi_device *device, int type)
518 + if (threaded_device == device)
519 + threaded_device = 0;
520 + return 0;
523 +static struct acpi_driver acpi_threaded_toshkeys = {
524 + .name = "Toshiba laptop hotkeys driver",
525 + .class = "hkey",
526 + .ids = "TOS6200,TOS6207,TOS6208",
527 + .ops = {
528 + .add = acpi_toshkeys_add,
529 + .remove = acpi_toshkeys_remove,
530 + },
533 +static int __init init_threaded_acpi(void)
535 + acpi_status result = AE_OK;
536 + result = acpi_bus_register_driver(&acpi_threaded_toshkeys);
537 + if( result < 0 )
538 + printk(MY_ERR "Registration of toshkeys acpi device failed\n");
539 + return result;
542 +static void kill_threaded_acpi(void)
544 + acpi_bus_unregister_driver(&acpi_threaded_toshkeys);
547 static void toshiba_acpi_exit(void)
549 if (toshiba_backlight_device)
550 backlight_device_unregister(toshiba_backlight_device);
552 + if (hotkeys_over_acpi) {
553 + thread_should_die = 1;
554 + down(&thread_sem);
555 + kill_threaded_acpi();
558 remove_device();
560 if (toshiba_proc_dir)
561 @@ -798,6 +954,26 @@
562 toshiba_acpi_exit();
565 + if (hotkeys_over_acpi && ACPI_SUCCESS(status)) {
566 + printk(MY_INFO "Toshiba hotkeys are sent as ACPI events\n");
567 + if (hotkeys_check_per_sec < 1)
568 + hotkeys_check_per_sec = 1;
569 + if (hotkeys_check_per_sec > 10)
570 + hotkeys_check_per_sec = 10;
571 + printk(MY_INFO "ktoshkeyd will check %d time%s per second\n",
572 + hotkeys_check_per_sec, hotkeys_check_per_sec==1?"":"s");
573 + if (init_threaded_acpi() >= 0) {
574 + init_MUTEX_LOCKED(&thread_sem);
575 + kernel_thread(toshiba_acpi_thread, NULL, CLONE_KERNEL);
576 + down(&thread_sem);
577 + } else {
578 + remove_device();
579 + remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
580 + status = AE_ERROR;
581 + printk(MY_INFO "ktoshkeyd initialisation failed. Refusing to load module\n");
585 return (ACPI_SUCCESS(status)) ? 0 : -ENODEV;