diff options
Diffstat (limited to 'drivers/char/toshiba.c')
| -rw-r--r-- | drivers/char/toshiba.c | 92 |
1 files changed, 59 insertions, 33 deletions
diff --git a/drivers/char/toshiba.c b/drivers/char/toshiba.c index 0c6f521abd0..014c9d90d29 100644 --- a/drivers/char/toshiba.c +++ b/drivers/char/toshiba.c @@ -58,7 +58,6 @@ #include <linux/module.h> #include <linux/kernel.h> -#include <linux/sched.h> #include <linux/types.h> #include <linux/fcntl.h> #include <linux/miscdevice.h> @@ -68,7 +67,8 @@ #include <linux/init.h> #include <linux/stat.h> #include <linux/proc_fs.h> - +#include <linux/seq_file.h> +#include <linux/mutex.h> #include <linux/toshiba.h> #define TOSH_MINOR_DEV 181 @@ -78,6 +78,7 @@ MODULE_AUTHOR("Jonathan Buzzard <jonathan@buzzard.org.uk>"); MODULE_DESCRIPTION("Toshiba laptop SMM driver"); MODULE_SUPPORTED_DEVICE("toshiba"); +static DEFINE_MUTEX(tosh_mutex); static int tosh_fn; module_param_named(fn, tosh_fn, int, 0); MODULE_PARM_DESC(fn, "User specified Fn key detection port"); @@ -88,13 +89,14 @@ static int tosh_date; static int tosh_sci; static int tosh_fan; -static int tosh_ioctl(struct inode *, struct file *, unsigned int, +static long tosh_ioctl(struct file *, unsigned int, unsigned long); -static struct file_operations tosh_fops = { +static const struct file_operations tosh_fops = { .owner = THIS_MODULE, - .ioctl = tosh_ioctl, + .unlocked_ioctl = tosh_ioctl, + .llseek = noop_llseek, }; static struct miscdevice tosh_device = { @@ -249,10 +251,10 @@ int tosh_smm(SMMRegisters *regs) return eax; } +EXPORT_SYMBOL(tosh_smm); -static int tosh_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, - unsigned long arg) +static long tosh_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) { SMMRegisters regs; SMMRegisters __user *argp = (SMMRegisters __user *)arg; @@ -274,13 +276,16 @@ static int tosh_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, return -EINVAL; /* do we need to emulate the fan ? */ + mutex_lock(&tosh_mutex); if (tosh_fan==1) { if (((ax==0xf300) || (ax==0xf400)) && (bx==0x0004)) { err = tosh_emulate_fan(®s); + mutex_unlock(&tosh_mutex); break; } } err = tosh_smm(®s); + mutex_unlock(&tosh_mutex); break; default: return -EINVAL; @@ -297,12 +302,10 @@ static int tosh_ioctl(struct inode *ip, struct file *fp, unsigned int cmd, * Print the information for /proc/toshiba */ #ifdef CONFIG_PROC_FS -static int tosh_get_info(char *buffer, char **start, off_t fpos, int length) +static int proc_toshiba_show(struct seq_file *m, void *v) { - char *temp; int key; - temp = buffer; key = tosh_fn_status(); /* Arguments @@ -313,8 +316,7 @@ static int tosh_get_info(char *buffer, char **start, off_t fpos, int length) 4) BIOS date (in SCI date format) 5) Fn Key status */ - - temp += sprintf(temp, "1.1 0x%04x %d.%d %d.%d 0x%04x 0x%02x\n", + 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, @@ -322,9 +324,21 @@ static int tosh_get_info(char *buffer, char **start, off_t fpos, int length) tosh_bios & 0xff, tosh_date, key); + return 0; +} - return temp-buffer; +static int proc_toshiba_open(struct inode *inode, struct file *file) +{ + return single_open(file, proc_toshiba_show, NULL); } + +static const struct file_operations proc_toshiba_fops = { + .owner = THIS_MODULE, + .open = proc_toshiba_open, + .read = seq_read, + .llseek = seq_lseek, + .release = single_release, +}; #endif @@ -355,14 +369,14 @@ static void tosh_set_fn_port(void) /* * Get the machine identification number of the current model */ -static int tosh_get_machine_id(void) +static int tosh_get_machine_id(void __iomem *bios) { int id; SMMRegisters regs; unsigned short bx,cx; unsigned long address; - id = (0x100*(int) isa_readb(0xffffe))+((int) isa_readb(0xffffa)); + id = (0x100*(int) readb(bios+0xfffe))+((int) readb(bios+0xfffa)); /* do we have a SCTTable machine identication number on our hands */ @@ -388,12 +402,12 @@ static int tosh_get_machine_id(void) /* now twiddle with our pointer a bit */ - address = 0x000f0000+bx; - cx = isa_readw(address); - address = 0x000f0009+bx+cx; - cx = isa_readw(address); - address = 0x000f000a+cx; - cx = isa_readw(address); + address = bx; + cx = readw(bios + address); + address = 9+bx+cx; + cx = readw(bios + address); + address = 0xa+cx; + cx = readw(bios + address); /* now construct our machine identification number */ @@ -416,13 +430,18 @@ static int tosh_probe(void) int i,major,minor,day,year,month,flag; unsigned char signature[7] = { 0x54,0x4f,0x53,0x48,0x49,0x42,0x41 }; SMMRegisters regs; + void __iomem *bios = ioremap_cache(0xf0000, 0x10000); + + if (!bios) + return -ENOMEM; /* extra sanity check for the string "TOSHIBA" in the BIOS because some machines that are not Toshiba's pass the next test */ for (i=0;i<7;i++) { - if (isa_readb(0xfe010+i)!=signature[i]) { + if (readb(bios+0xe010+i)!=signature[i]) { printk("toshiba: not a supported Toshiba laptop\n"); + iounmap(bios); return -ENODEV; } } @@ -438,6 +457,7 @@ static int tosh_probe(void) if ((flag==1) || ((regs.eax & 0xff00)==0x8600)) { printk("toshiba: not a supported Toshiba laptop\n"); + iounmap(bios); return -ENODEV; } @@ -447,19 +467,19 @@ static int tosh_probe(void) /* next get the machine ID of the current laptop */ - tosh_id = tosh_get_machine_id(); + tosh_id = tosh_get_machine_id(bios); /* get the BIOS version */ - major = isa_readb(0xfe009)-'0'; - minor = ((isa_readb(0xfe00b)-'0')*10)+(isa_readb(0xfe00c)-'0'); + 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 = ((isa_readb(0xffff5)-'0')*10)+(isa_readb(0xffff6)-'0'); - month = ((isa_readb(0xffff8)-'0')*10)+(isa_readb(0xffff9)-'0'); - year = ((isa_readb(0xffffb)-'0')*10)+(isa_readb(0xffffc)-'0'); + 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); @@ -476,6 +496,8 @@ static int tosh_probe(void) if ((tosh_id==0xfccb) || (tosh_id==0xfccc)) tosh_fan = 1; + iounmap(bios); + return 0; } @@ -487,7 +509,7 @@ static int __init toshiba_init(void) if (tosh_probe()) return -ENODEV; - printk(KERN_INFO "Toshiba System Managment Mode driver v" TOSH_VERSION "\n"); + printk(KERN_INFO "Toshiba System Management Mode driver v" TOSH_VERSION "\n"); /* set the port to use for Fn status if not specified as a parameter */ if (tosh_fn==0x00) @@ -499,10 +521,14 @@ static int __init toshiba_init(void) return retval; #ifdef CONFIG_PROC_FS - /* register the proc entry */ - if (create_proc_info_entry("toshiba", 0, NULL, tosh_get_info) == NULL) { - misc_deregister(&tosh_device); - return -ENOMEM; + { + struct proc_dir_entry *pde; + + pde = proc_create("toshiba", 0, NULL, &proc_toshiba_fops); + if (!pde) { + misc_deregister(&tosh_device); + return -ENOMEM; + } } #endif |
