diff --git a/drivers/platform/x86/toshiba_acpi.c b/drivers/platform/x86/toshiba_acpi.c
index dcdc1f4..9beb427 100644
--- a/drivers/platform/x86/toshiba_acpi.c
+++ b/drivers/platform/x86/toshiba_acpi.c
@@ -30,6 +30,20 @@
  *	Yasushi Nagato - changes for linux kernel 2.4 -> 2.5
  *	Rob Miller - TV out and hotkeys help
  *
+ *  PLEASE NOTE
+ *
+ *  This is an experimental version of toshiba_acpi which includes emulation
+ *  of the original toshiba driver's /proc/toshiba and /dev/toshiba,
+ *  allowing Toshiba userspace utilities to work.  The relevant code was
+ *  based on toshiba.c (copyright 1996-2001 Jonathan A. Buzzard) and
+ *  incorporated into this driver with help from Gintautas Miliauskas,
+ *  Charles Schwieters, and Christoph Burger-Scheidlin.
+ *
+ *  Caveats:
+ *      * hotkey status in /proc/toshiba is not implemented
+ *      * to make accesses to /dev/toshiba load this driver instead of
+ *          the original driver, you will have to modify your module
+ *          auto-loading configuration
  *
  *  TODO
  *
@@ -37,7 +51,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-#define TOSHIBA_ACPI_VERSION	"0.20"
+#define TOSHIBA_ACPI_VERSION	"experimental-dev-toshiba-test-6"
 #define PROC_INTERFACE_VERSION	1
 
 #include <linux/kernel.h>
@@ -46,6 +61,9 @@
 #include <linux/types.h>
 #include <linux/proc_fs.h>
 #include <linux/seq_file.h>
+#include <linux/miscdevice.h>
+#include <linux/toshiba.h>
+#include <asm/io.h>
 #include <linux/backlight.h>
 #include <linux/rfkill.h>
 #include <linux/input.h>
@@ -126,6 +144,8 @@ struct toshiba_acpi_dev {
 	struct mutex mutex;
 };
 
+struct toshiba_acpi_dev* global_dev;
+
 static const struct acpi_device_id toshiba_device_ids[] = {
 	{"TOS6200", 0},
 	{"TOS6208", 0},
@@ -805,6 +825,207 @@ static const struct file_operations version_proc_fops = {
 	.release	= single_release,
 };
 
+/* /dev/toshiba and /proc/toshiba handlers {{{
+ *
+ * ISSUE: lots of magic numbers and mysterious code
+ */
+
+#define TOSH_MINOR_DEV		181
+#define OLD_PROC_TOSHIBA	"toshiba"
+
+static int
+tosh_acpi_bridge(struct toshiba_acpi_dev *dev, SMMRegisters* regs)
+{
+	acpi_status status;
+
+	/* assert(sizeof(SMMRegisters) == sizeof(u32)*HCI_WORDS); */
+	status = hci_raw(dev, (u32*)regs, (u32*)regs);
+	if (status == AE_OK && (regs->eax & 0xff00) == HCI_SUCCESS)
+		return 0;
+
+	return -EINVAL;
+}
+
+static long
+tosh_ioctl(struct file* fp, unsigned int cmd,
+	   unsigned long arg)
+{
+	SMMRegisters regs;
+	unsigned short ax,bx;
+	int err;
+	//FIX:
+	//struct toshiba_acpi_dev *dev = PDE(fp->f_path.dentry->d_inode)->data;
+	if ((!arg) || (cmd != TOSH_SMM))
+		return -EINVAL;
+
+	if (copy_from_user(&regs, (SMMRegisters*)arg, sizeof(SMMRegisters)))
+		return -EFAULT;
+
+	ax = regs.eax & 0xff00;
+	bx = regs.ebx & 0xffff;
+
+	/* block HCI calls to read/write memory & PCI devices */
+	if (((ax==HCI_SET) || (ax==HCI_GET)) && (bx>0x0069))
+		return -EINVAL;
+
+	err = tosh_acpi_bridge(global_dev,&regs);
+
+	if (copy_to_user((SMMRegisters*)arg, &regs, sizeof(SMMRegisters)))
+		return -EFAULT;
+
+	return err;
+}
+
+static int
+tosh_get_machine_id(void __iomem *bios)
+{
+	int id;
+	unsigned short bx,cx;
+	unsigned long address;
+
+	id = (0x100*(int) readb(bios+0xfffe))+((int) readb(bios+0xfffa));
+
+	/* do we have a SCTTable machine identication number on our hands */
+	if (id==0xfc2f) {
+		bx = 0xe6f5; /* cheat */
+		/* now twiddle with our pointer a bit */
+		address = 0x00000000 + bx;
+		cx = readw(bios + address);
+		address = 0x00000009 + bx + cx;
+		cx = readw(bios + address);
+		address = 0x0000000a + cx;
+		cx = readw(bios + address);
+		/* now construct our machine identification number */
+		id = ((cx & 0xff)<<8)+((cx & 0xff00)>>8);
+	}
+
+	return id;
+}
+
+static int tosh_id;
+static int tosh_bios;
+static int tosh_date;
+static int tosh_sci;
+
+static struct file_operations tosh_fops = {
+	.owner = THIS_MODULE,
+	.unlocked_ioctl = tosh_ioctl
+};
+
+static struct miscdevice tosh_device = {
+	TOSH_MINOR_DEV,
+	"toshiba",
+	&tosh_fops
+};
+
+static void
+setup_tosh_info(void __iomem *bios)
+{
+	int major, minor;
+	int day, month, year;
+
+	tosh_id = tosh_get_machine_id(bios);
+
+	/* get the BIOS version */
+	major = readb(bios + 0xe009)-'0';
+	minor = ((readb(bios + 0xe00b)-'0')*10)+(readb(bios + 0xe00c)-'0');
+	tosh_bios = (major*0x100)+minor;
+
+	/* get the BIOS date */
+	day = ((readb(bios + 0xfff5)-'0')*10)+(readb(bios + 0xfff6)-'0');
+	month = ((readb(bios + 0xfff8)-'0')*10)+(readb(bios + 0xfff9)-'0');
+	year = ((readb(bios + 0xfffb)-'0')*10)+(readb(bios + 0xfffc)-'0');
+	tosh_date = (((year-90) & 0x1f)<<10) | ((month & 0xf)<<6)
+		| ((day & 0x1f)<<1);
+}
+
+/* /proc/toshiba read handler */
+static int
+tosh_proc_show(struct seq_file *m, void *v)
+{
+	/* TODO: tosh_fn_status() */
+	int key = 0;
+
+	/* Format:
+	 *    0) Linux driver version (this will change if format changes)
+	 *    1) Machine ID
+	 *    2) SCI version
+	 *    3) BIOS version (major, minor)
+	 *    4) BIOS date (in SCI date format)
+	 *    5) Fn Key status
+	 */
+
+	seq_printf(m, "1.1 0x%04x %d.%d %d.%d 0x%04x 0x%02x\n",
+		tosh_id,
+		(tosh_sci & 0xff00)>>8,
+		tosh_sci & 0xff,
+		(tosh_bios & 0xff00)>>8,
+		tosh_bios & 0xff,
+		tosh_date,
+		key);
+
+	return 0;
+}
+
+static int tosh_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, tosh_proc_show, NULL);
+}
+
+static const struct file_operations tosh_proc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= tosh_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int __init
+old_driver_emulation_init(void)
+{
+	int status;
+	void __iomem *bios = ioremap(0xf0000, 0x10000);
+	if (!bios)
+		return -ENOMEM;
+
+	if ((status = misc_register(&tosh_device))) {
+		pr_err("failed to register misc device %d (\"%s\")\n",
+			tosh_device.minor, tosh_device.name);
+		return status;
+	}
+
+	setup_tosh_info(bios);
+	proc_create(OLD_PROC_TOSHIBA, 0, NULL, &tosh_proc_fops);
+
+	iounmap(bios);
+
+	return 0;
+}
+
+static void __exit
+old_driver_emulation_exit(void)
+{
+	remove_proc_entry(OLD_PROC_TOSHIBA, NULL);
+	misc_deregister(&tosh_device);
+}
+
+/* }}} end of /dev/toshiba and /proc/toshiba handlers */
+
+/* /dev/toshiba and /proc/toshiba handlers {{{
+ *
+ * ISSUE: lots of magic numbers and mysterious code
+ */
+
+#define TOSH_MINOR_DEV		181
+#define OLD_PROC_TOSHIBA	"toshiba"
+
+static int tosh_id;
+static int tosh_bios;
+static int tosh_date;
+static int tosh_sci;
+
+/* }}} end of /dev/toshiba and /proc/toshiba handlers */
+
 /* proc and module init
  */
 
@@ -939,6 +1160,7 @@ static int __devinit toshiba_acpi_add(struct acpi_device *acpi_dev)
 	u32 hci_result;
 	u32 dummy;
 	bool bt_present;
+	//  	int status2;
 	int ret = 0;
 	struct backlight_properties props;
 
@@ -952,6 +1174,7 @@ static int __devinit toshiba_acpi_add(struct acpi_device *acpi_dev)
 	}
 
 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	global_dev = dev;
 	if (!dev)
 		return -ENOMEM;
 	dev->acpi_dev = acpi_dev;
@@ -1086,6 +1309,8 @@ static struct acpi_driver toshiba_acpi_driver = {
 static int __init toshiba_acpi_init(void)
 {
 	int ret;
+	int status2;
+	
 
 	toshiba_proc_dir = proc_mkdir(PROC_TOSHIBA, acpi_root_dir);
 	if (!toshiba_proc_dir) {
@@ -1099,12 +1324,17 @@ static int __init toshiba_acpi_init(void)
 		remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
 	}
 
+	if ((status2 = old_driver_emulation_init()))
+		return status2;
 	return ret;
 }
 
 static void __exit toshiba_acpi_exit(void)
 {
 	acpi_bus_unregister_driver(&toshiba_acpi_driver);
+
+	old_driver_emulation_exit();
+
 	if (toshiba_proc_dir)
 		remove_proc_entry(PROC_TOSHIBA, acpi_root_dir);
 }
