From: John Belmonte <jvb-ZFKsivP1bGvOQU1ULcgDhA@public.gmane.org>
To: "Grover, Andrew" <andrew.grover-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Cc: acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org
Subject: Re: RE: [PATCH] Toshiba Laptop Extras v0.13
Date: Mon, 09 Sep 2002 23:19:27 +0900 [thread overview]
Message-ID: <3D7CADEF.8010904@prairienet.org> (raw)
In-Reply-To: EDC461A30AC4D511ADE10002A5072CAD0236DE05@orsmsx119.jf.intel.com
[-- Attachment #1: Type: text/plain, Size: 313 bytes --]
Hi Andy,
>> The driver file should now be 2.4 friendly. Will you accept a patch
>> to the ACPI-patched 2.4 kernel adding my driver?
>
> Sure.
Here is a patch to linux-2.4.19 with acpi-20020821. Hopefully it can be
applied to your current 2.4 tree without event.
Thanks,
-John
--
http:// i . /
[-- Attachment #2: toshiba_acpi_0.13-linux_2.4.19-acpi_20020821.patch --]
[-- Type: text/plain, Size: 18149 bytes --]
diff -urN linux-2.4.19-acpi/Documentation/Configure.help linux-2.4.19-acpi-toshiba_acpi/Documentation/Configure.help
--- linux-2.4.19-acpi/Documentation/Configure.help Mon Sep 9 17:18:17 2002
+++ linux-2.4.19-acpi-toshiba_acpi/Documentation/Configure.help Mon Sep 9 18:20:05 2002
@@ -17679,6 +17679,30 @@
This driver handles overheating conditions on laptops. It is HIGHLY
recommended, as your laptop CPU may be damaged without it.
+ACPI Toshiba Laptop Extras
+CONFIG_ACPI_TOSHIBA
+ This driver adds support for access to certain system settings
+ on "legacy free" Toshiba laptops. These laptops can be recognized by
+ their lack of a BIOS setup menu and APM support.
+
+ On these machines, all system configuration is handled through the
+ ACPI. This driver is required for access to controls not covered
+ by the general ACPI drivers, such as LCD brightness, video output,
+ etc.
+
+ This driver differs from the non-ACPI Toshiba laptop driver (located
+ under "Processor type and features") in several aspects.
+ Configuration is accessed by reading and writing text files in the
+ /proc tree instead of by program interface to /dev. Furthermore, no
+ power management functions are exposed, as those are handled by the
+ general ACPI drivers.
+
+ More information about this driver is available at
+ <http://memebeam.org/toys/ToshibaAcpiDriver>.
+
+ If you have a legacy free Toshiba laptop (such as the Libretto L1
+ series), say Y.
+
Advanced Power Management BIOS support
CONFIG_APM
APM is a BIOS specification for saving power using several different
diff -urN linux-2.4.19-acpi/MAINTAINERS linux-2.4.19-acpi-toshiba_acpi/MAINTAINERS
--- linux-2.4.19-acpi/MAINTAINERS Mon Sep 9 17:18:19 2002
+++ linux-2.4.19-acpi-toshiba_acpi/MAINTAINERS Mon Sep 9 18:25:59 2002
@@ -1563,6 +1563,12 @@
W: http://www.linuxtr.net
S: Maintained
+TOSHIBA ACPI EXTRAS DRIVER
+P: John Belmonte
+M: toshiba_acpi-7wiBuN1tZDdg9hUCZPvPmw@public.gmane.org
+W: http://memebeam.org/toys/ToshibaAcpiDriver
+S: Maintained
+
TOSHIBA SMM DRIVER
P: Jonathan Buzzard
M: jonathan-kE54VaY6i3ADXYZnReoRVg@public.gmane.org
diff -urN linux-2.4.19-acpi/drivers/acpi/Config.in linux-2.4.19-acpi-toshiba_acpi/drivers/acpi/Config.in
--- linux-2.4.19-acpi/drivers/acpi/Config.in Mon Sep 9 18:14:55 2002
+++ linux-2.4.19-acpi-toshiba_acpi/drivers/acpi/Config.in Mon Sep 9 18:20:05 2002
@@ -31,6 +31,7 @@
tristate ' Fan' CONFIG_ACPI_FAN
tristate ' Processor' CONFIG_ACPI_PROCESSOR
dep_tristate ' Thermal Zone' CONFIG_ACPI_THERMAL $CONFIG_ACPI_PROCESSOR
+ tristate ' Toshiba Laptop Extras' CONFIG_ACPI_TOSHIBA
bool ' Debug Statements' CONFIG_ACPI_DEBUG
fi
fi
diff -urN linux-2.4.19-acpi/drivers/acpi/Makefile linux-2.4.19-acpi-toshiba_acpi/drivers/acpi/Makefile
--- linux-2.4.19-acpi/drivers/acpi/Makefile Mon Sep 9 18:14:55 2002
+++ linux-2.4.19-acpi-toshiba_acpi/drivers/acpi/Makefile Mon Sep 9 18:20:05 2002
@@ -50,6 +50,7 @@
obj-$(CONFIG_ACPI_PROCESSOR) += processor.o
obj-$(CONFIG_ACPI_THERMAL) += thermal.o
obj-$(CONFIG_ACPI_SYSTEM) += system.o
+ obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
endif
include $(TOPDIR)/Rules.make
diff -urN linux-2.4.19-acpi/drivers/acpi/toshiba_acpi.c linux-2.4.19-acpi-toshiba_acpi/drivers/acpi/toshiba_acpi.c
--- linux-2.4.19-acpi/drivers/acpi/toshiba_acpi.c Thu Jan 1 09:00:00 1970
+++ linux-2.4.19-acpi-toshiba_acpi/drivers/acpi/toshiba_acpi.c Mon Sep 9 18:20:05 2002
@@ -0,0 +1,570 @@
+/*
+ * toshiba_acpi.c - Toshiba Laptop ACPI Extras
+ *
+ *
+ * Copyright (C) 2002 John Belmonte
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ *
+ * The devolpment page for this driver is located at
+ * http://memebeam.org/toys/ToshibaAcpiDriver.
+ *
+ * Credits:
+ * Jonathan A. Buzzard - Toshiba HCI info, and critical tips on reverse
+ * engineering the Windows drivers
+ * Yasushi Nagato - changes for linux kernel 2.4 -> 2.5
+ * Rob Miller - TV out and hotkeys help
+ *
+ *
+ * TODO
+ *
+ */
+
+#define TOSHIBA_ACPI_VERSION "0.13"
+#define PROC_INTERFACE_VERSION 1
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <linux/version.h>
+
+#include <acconfig.h>
+#define OLD_ACPI_INTERFACE (ACPI_CA_VERSION < 0x20020000)
+
+#if OLD_ACPI_INTERFACE
+#include <acpi.h>
+extern struct proc_dir_entry* bm_proc_root;
+#define acpi_root_dir bm_proc_root
+#else
+#include "acpi_drivers.h"
+#endif
+
+MODULE_AUTHOR("John Belmonte");
+MODULE_DESCRIPTION("Toshiba Laptop ACPI Extras Driver");
+MODULE_LICENSE("GPL");
+
+/* Toshiba ACPI method paths */
+#define METHOD_LCD_BRIGHTNESS "\\_SB_.PCI0.VGA_.LCD_._BCM"
+#define METHOD_HCI "\\_SB_.VALD.GHCI"
+#define METHOD_VIDEO_OUT "\\_SB_.VALX.DSSX"
+
+/* Toshiba HCI interface definitions
+ *
+ * HCI is Toshiba's "Hardware Control Interface" which is supposed to
+ * be uniform across all their models. Ideally we would just call
+ * dedicated ACPI methods instead of using this primitive interface.
+ * However the ACPI methods seem to be incomplete in some areas (for
+ * example they allow setting, but not reading, the LCD brightness value),
+ * so this is still useful.
+ */
+
+#define HCI_WORDS 6
+
+/* operations */
+#define HCI_SET 0xff00
+#define HCI_GET 0xfe00
+
+/* return codes */
+#define HCI_SUCCESS 0x0000
+#define HCI_FAILURE 0x1000
+#define HCI_NOT_SUPPORTED 0x8000
+#define HCI_EMPTY 0x8c00
+
+/* registers */
+#define HCI_FAN 0x0004
+#define HCI_SYSTEM_EVENT 0x0016
+#define HCI_VIDEO_OUT 0x001c
+#define HCI_HOTKEY_EVENT 0x001e
+#define HCI_LCD_BRIGHTNESS 0x002a
+
+/* field definitions */
+#define HCI_LCD_BRIGHTNESS_BITS 3
+#define HCI_LCD_BRIGHTNESS_SHIFT (16-HCI_LCD_BRIGHTNESS_BITS)
+#define HCI_LCD_BRIGHTNESS_LEVELS (1 << HCI_LCD_BRIGHTNESS_BITS)
+#define HCI_VIDEO_OUT_LCD 0x1
+#define HCI_VIDEO_OUT_CRT 0x2
+#define HCI_VIDEO_OUT_TV 0x4
+
+/* utility
+ */
+
+static __inline__ void
+_set_bit(u32* word, u32 mask, int value)
+{
+ *word = (*word & ~mask) | (mask * value);
+}
+
+/* an sscanf that takes explicit string length */
+static int
+snscanf(const char* str, int n, const char* format, ...)
+{
+ va_list args;
+ int result;
+ char* str2 = kmalloc(n + 1, GFP_KERNEL);
+ if (str2 == 0) return 0;
+ strncpy(str2, str, n);
+ str2[n] = 0;
+ va_start(args, format);
+ result = vsscanf(str2, format, args);
+ va_end(args);
+ kfree(str2);
+ return result;
+}
+
+/* This is the common code at the end of every proc read handler. I don't
+ * understand it yet.
+ */
+static int
+end_proc_read(const char* p, char* page, off_t off, int count,
+ char** start, int* eof)
+{
+ int len = (p - page);
+ if (len <= off+count) *eof = 1;
+ *start = page + off;
+ len -= off;
+ if (len>count) len = count;
+ if (len<0) len = 0;
+ return len;
+}
+
+/* acpi interface wrappers
+ */
+
+static int
+write_acpi_int(const char* methodName, int val)
+{
+ acpi_object_list params;
+ acpi_object in_objs[1];
+ acpi_status status;
+
+ params.count = sizeof(in_objs)/sizeof(in_objs[0]);
+ params.pointer = in_objs;
+ in_objs[0].type = ACPI_TYPE_INTEGER;
+ in_objs[0].integer.value = val;
+
+ status = acpi_evaluate_object(0, (char*)methodName, ¶ms, 0);
+ return (status == AE_OK);
+}
+
+#if 0
+static int
+read_acpi_int(const char* methodName, int* pVal)
+{
+ acpi_buffer results;
+ acpi_object out_objs[1];
+ acpi_status status;
+
+ results.length = sizeof(out_objs);
+ results.pointer = out_objs;
+
+ status = acpi_evaluate_object(0, (char*)methodName, 0, &results);
+ *pVal = out_objs[0].integer.value;
+
+ return (status == AE_OK) && (out_objs[0].type == ACPI_TYPE_INTEGER);
+}
+#endif
+
+/* Perform a raw HCI call. Here we don't care about input or output buffer
+ * format.
+ */
+static acpi_status
+hci_raw(const u32 in[HCI_WORDS], u32 out[HCI_WORDS])
+{
+ acpi_object_list params;
+ acpi_object in_objs[HCI_WORDS];
+ acpi_buffer results;
+ acpi_object out_objs[HCI_WORDS+1];
+ acpi_status status;
+ int i;
+
+ params.count = HCI_WORDS;
+ params.pointer = in_objs;
+ for (i = 0; i < HCI_WORDS; ++i) {
+ in_objs[i].type = ACPI_TYPE_INTEGER;
+ in_objs[i].integer.value = in[i];
+ /*printk("%04x ", in[i]);*/
+ }
+ /*printk("\n");*/
+
+ results.length = sizeof(out_objs);
+ results.pointer = out_objs;
+
+ status = acpi_evaluate_object(0, METHOD_HCI, ¶ms,
+ &results);
+ if ((status == AE_OK) && (out_objs->package.count <= HCI_WORDS)) {
+ for (i = 0; i < out_objs->package.count; ++i) {
+ out[i] = out_objs->package.elements[i].integer.value;
+ /*printk("%04x ", out[i]);*/
+ }
+ /*printk("\n");*/
+ }
+
+ return status;
+}
+
+/* common hci tasks (get or set one value)
+ *
+ * In addition to the ACPI status, the HCI system returns a result which
+ * may be useful (such as "not supported").
+ */
+
+static acpi_status
+hci_write1(u32 reg, u32 in1, u32* result)
+{
+ u32 in[HCI_WORDS] = { HCI_SET, reg, in1, 0, 0, 0 };
+ u32 out[HCI_WORDS];
+ acpi_status status = hci_raw(in, out);
+ *result = (status == AE_OK) ? out[0] : HCI_FAILURE;
+ return status;
+}
+
+static acpi_status
+hci_read1(u32 reg, u32* out1, u32* result)
+{
+ u32 in[HCI_WORDS] = { HCI_GET, reg, 0, 0, 0, 0 };
+ u32 out[HCI_WORDS];
+ acpi_status status = hci_raw(in, out);
+ *out1 = out[2];
+ *result = (status == AE_OK) ? out[0] : HCI_FAILURE;
+ return status;
+}
+
+#define PROC_TOSHIBA "toshiba"
+#define PROC_LCD "lcd"
+#define PROC_VIDEO "video"
+#define PROC_FAN "fan"
+#define PROC_KEYS "keys"
+#define PROC_VERSION "version"
+
+static struct proc_dir_entry* toshiba_proc_dir = NULL;
+static int force_fan;
+static int last_key_event;
+static int key_event_valid;
+
+/* proc file handlers
+ */
+
+static int
+proc_read_lcd(char* page, char** start, off_t off, int count, int* eof,
+ void* context)
+{
+ char* p = page;
+ u32 hci_result;
+ u32 value;
+
+ if (off != 0) goto end;
+
+ hci_read1(HCI_LCD_BRIGHTNESS, &value, &hci_result);
+ if (hci_result == HCI_SUCCESS) {
+ value = value >> HCI_LCD_BRIGHTNESS_SHIFT;
+ p += sprintf(p, "brightness: %d\n", value);
+ p += sprintf(p, "brightness_levels: %d\n",
+ HCI_LCD_BRIGHTNESS_LEVELS);
+ } else {
+ p += sprintf(p, "ERROR\n");
+ goto end;
+ }
+
+end:
+ return end_proc_read(p, page, off, count, start, eof);
+}
+
+static int
+proc_write_lcd(struct file* file, const char* buffer, unsigned long count,
+ void* data)
+{
+ int value;
+ /*int byte_count;*/
+ u32 hci_result;
+
+ /* ISSUE: %i doesn't work with hex values as advertised */
+ if (snscanf(buffer, count, " brightness : %i", &value) == 1 &&
+ value >= 0 && value < HCI_LCD_BRIGHTNESS_LEVELS) {
+ value = value << HCI_LCD_BRIGHTNESS_SHIFT;
+ hci_write1(HCI_LCD_BRIGHTNESS, value, &hci_result);
+ if (hci_result != HCI_SUCCESS)
+ return -EFAULT;
+ } else {
+ return -EINVAL;
+ }
+
+ return count;
+}
+
+static int
+proc_read_video(char* page, char** start, off_t off, int count, int* eof,
+ void* context)
+{
+ char* p = page;
+ u32 hci_result;
+ u32 value;
+
+ if (off != 0) goto end;
+
+ hci_read1(HCI_VIDEO_OUT, &value, &hci_result);
+ if (hci_result == HCI_SUCCESS) {
+ int is_lcd = (value & HCI_VIDEO_OUT_LCD) ? 1 : 0;
+ int is_crt = (value & HCI_VIDEO_OUT_CRT) ? 1 : 0;
+ int is_tv = (value & HCI_VIDEO_OUT_TV ) ? 1 : 0;
+ p += sprintf(p, "lcd_out: %d\n", is_lcd);
+ p += sprintf(p, "crt_out: %d\n", is_crt);
+ p += sprintf(p, "tv_out: %d\n", is_tv);
+ } else {
+ p += sprintf(p, "ERROR\n");
+ goto end;
+ }
+
+end:
+ return end_proc_read(p, page, off, count, start, eof);
+}
+
+static int
+proc_write_video(struct file* file, const char* buffer, unsigned long count,
+ void* data)
+{
+ int value;
+ const char* buffer_end = buffer + count;
+ int lcd_out = -1;
+ int crt_out = -1;
+ int tv_out = -1;
+ u32 hci_result;
+ int video_out;
+
+ /* scan expression. Multiple expressions may be delimited with ; */
+ do {
+ if (snscanf(buffer, count, " lcd_out : %i", &value) == 1)
+ lcd_out = value & 1;
+ else if (snscanf(buffer, count, " crt_out : %i", &value) == 1)
+ crt_out = value & 1;
+ else if (snscanf(buffer, count, " tv_out : %i", &value) == 1)
+ tv_out = value & 1;
+ /* advance to one character past the next ; */
+ do ++buffer;
+ while ((buffer < buffer_end) && (*(buffer-1) != ';'));
+ } while (buffer < buffer_end);
+
+ hci_read1(HCI_VIDEO_OUT, &video_out, &hci_result);
+ if (hci_result == HCI_SUCCESS) {
+ int new_video_out = video_out;
+ if (lcd_out != -1)
+ _set_bit(&new_video_out, HCI_VIDEO_OUT_LCD, lcd_out);
+ if (crt_out != -1)
+ _set_bit(&new_video_out, HCI_VIDEO_OUT_CRT, crt_out);
+ if (tv_out != -1)
+ _set_bit(&new_video_out, HCI_VIDEO_OUT_TV, tv_out);
+ /* To avoid unnecessary video disruption, only write the new
+ * video setting if something changed. */
+ if (new_video_out != video_out)
+ write_acpi_int(METHOD_VIDEO_OUT, new_video_out);
+ }
+
+ return count;
+}
+
+static int
+proc_read_fan(char* page, char** start, off_t off, int count, int* eof,
+ void* context)
+{
+ char* p = page;
+ u32 hci_result;
+ u32 value;
+
+ if (off != 0) goto end;
+
+ hci_read1(HCI_FAN, &value, &hci_result);
+ if (hci_result == HCI_SUCCESS) {
+ p += sprintf(p, "running: %d\n", (value > 0));
+ p += sprintf(p, "force_on: %d\n", force_fan);
+ } else {
+ p += sprintf(p, "ERROR\n");
+ goto end;
+ }
+
+end:
+ return end_proc_read(p, page, off, count, start, eof);
+}
+
+static int
+proc_write_fan(struct file* file, const char* buffer, unsigned long count,
+ void* data)
+{
+ int value;
+ u32 hci_result;
+
+ if (snscanf(buffer, count, " force_on : %i", &value) == 1 &&
+ value >= 0 && value <= 1) {
+ hci_write1(HCI_FAN, value, &hci_result);
+ if (hci_result != HCI_SUCCESS)
+ return -EFAULT;
+ else
+ force_fan = value;
+ } else {
+ return -EINVAL;
+ }
+
+ return count;
+}
+
+static int
+proc_read_keys(char* page, char** start, off_t off, int count, int* eof,
+ void* context)
+{
+ char* p = page;
+ u32 hci_result;
+ u32 value;
+
+ if (off != 0) goto end;
+
+ if (!key_event_valid) {
+ hci_read1(HCI_SYSTEM_EVENT, &value, &hci_result);
+ if (hci_result == HCI_SUCCESS) {
+ key_event_valid = 1;
+ last_key_event = value;
+ } else if (hci_result == HCI_EMPTY) {
+ /* better luck next time */
+ } else {
+ p += sprintf(p, "ERROR\n");
+ goto end;
+ }
+ }
+
+ p += sprintf(p, "hotkey_ready: %d\n", key_event_valid);
+ p += sprintf(p, "hotkey: 0x%04x\n", last_key_event);
+
+end:
+ return end_proc_read(p, page, off, count, start, eof);
+}
+
+static int
+proc_write_keys(struct file* file, const char* buffer, unsigned long count,
+ void* data)
+{
+ int value;
+
+ if (snscanf(buffer, count, " hotkey_ready : %i", &value) == 1 &&
+ value == 0) {
+ key_event_valid = 0;
+ } else {
+ return -EINVAL;
+ }
+
+ return count;
+}
+
+static int
+proc_read_version(char* page, char** start, off_t off, int count, int* eof,
+ void* context)
+{
+ char* p = page;
+
+ if (off != 0) goto end;
+
+ p += sprintf(p, "driver: %s\n", TOSHIBA_ACPI_VERSION);
+ p += sprintf(p, "proc_interface: %d\n",
+ PROC_INTERFACE_VERSION);
+
+end:
+ return end_proc_read(p, page, off, count, start, eof);
+}
+
+/* proc and module init
+ */
+
+static acpi_status
+add_device(void)
+{
+ struct proc_dir_entry* proc;
+
+ proc = create_proc_read_entry(PROC_LCD, S_IFREG | S_IRUGO | S_IWUSR,
+ toshiba_proc_dir, proc_read_lcd, 0);
+ if (proc) proc->write_proc = proc_write_lcd;
+
+ proc = create_proc_read_entry(PROC_VIDEO, S_IFREG | S_IRUGO | S_IWUSR,
+ toshiba_proc_dir, proc_read_video, 0);
+ if (proc) proc->write_proc = proc_write_video;
+
+ proc = create_proc_read_entry(PROC_FAN, S_IFREG | S_IRUGO | S_IWUSR,
+ toshiba_proc_dir, proc_read_fan, 0);
+ if (proc) proc->write_proc = proc_write_fan;
+
+ proc = create_proc_read_entry(PROC_KEYS, S_IFREG | S_IRUGO | S_IWUSR,
+ toshiba_proc_dir, proc_read_keys, 0);
+ if (proc) proc->write_proc = proc_write_keys;
+
+ proc = create_proc_read_entry(PROC_VERSION, S_IFREG | S_IRUGO | S_IWUSR,
+ toshiba_proc_dir, proc_read_version, 0);
+
+ return(AE_OK);
+}
+
+static acpi_status
+remove_device(void)
+{
+ remove_proc_entry(PROC_LCD, toshiba_proc_dir);
+ remove_proc_entry(PROC_VIDEO, toshiba_proc_dir);
+ remove_proc_entry(PROC_FAN, toshiba_proc_dir);
+ remove_proc_entry(PROC_KEYS, toshiba_proc_dir);
+ remove_proc_entry(PROC_VERSION, toshiba_proc_dir);
+ return(AE_OK);
+}
+
+static int __init
+toshiba_acpi_init(void)
+{
+ acpi_status status = AE_OK;
+ int value;
+ u32 hci_result;
+
+ /* simple device detection: try reading an HCI register */
+ hci_read1(HCI_LCD_BRIGHTNESS, &value, &hci_result);
+ if (hci_result != HCI_SUCCESS)
+ return -ENODEV;
+
+ printk("Toshiba Laptop ACPI Extras version %s\n", TOSHIBA_ACPI_VERSION);
+
+ force_fan = 0;
+ key_event_valid = 0;
+
+ /* enable event fifo */
+ hci_write1(HCI_SYSTEM_EVENT, 1, &hci_result);
+
+ toshiba_proc_dir = proc_mkdir(PROC_TOSHIBA, acpi_root_dir);
+ if (!toshiba_proc_dir) {
+ status = AE_ERROR;
+ } else {
+ status = add_device();
+ if (ACPI_FAILURE(status))
+ remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
+ }
+
+ return (ACPI_SUCCESS(status)) ? 0 : -ENODEV;
+}
+
+static void __exit
+toshiba_acpi_exit(void)
+{
+ remove_device();
+
+ if (toshiba_proc_dir)
+ remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
+
+ return;
+}
+
+module_init(toshiba_acpi_init);
+module_exit(toshiba_acpi_exit);
prev parent reply other threads:[~2002-09-09 14:19 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2002-09-03 20:56 [PATCH] Toshiba Laptop Extras v0.13 Grover, Andrew
2002-09-09 14:19 ` John Belmonte [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=3D7CADEF.8010904@prairienet.org \
--to=jvb-zfksivp1bgvoqu1ulcgdha@public.gmane.org \
--cc=acpi-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f@public.gmane.org \
--cc=andrew.grover-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox