diff -urN -X dontdiff linux-2.5.67/drivers/char/Kconfig linux-2.5.67-vm86/drivers/char/Kconfig --- linux-2.5.67/drivers/char/Kconfig 2003-03-21 18:23:31.000000000 +0100 +++ linux-2.5.67-vm86/drivers/char/Kconfig 2003-04-14 19:25:52.000000000 +0200 +config VM86 + bool "VM86 Interface" + depends on X86 + help + The VM86 interface is an interface between the kernel and + a user-mode daemon (vm86d) that provides 16-bit BIOS services. + At the moment, this is only used for the VESA framebuffer + driver as a way to change refresh-rates and get information + from the monitor and the card. You also need the user-mode + daemon at http://i810fb.sourceforge.net, + endmenu diff -urN -X dontdiff linux-2.5.67/drivers/char/Makefile linux-2.5.67-vm86/drivers/char/Makefile --- linux-2.5.67/drivers/char/Makefile 2003-04-07 19:55:37.000000000 +0200 +++ linux-2.5.67-vm86/drivers/char/Makefile 2003-04-12 08:27:33.000000000 +0200 @@ -78,6 +78,7 @@ obj-$(CONFIG_IPMI_HANDLER) += ipmi/ obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o +obj-$(CONFIG_VM86) += vm86.o # Files generated that shall be removed upon make clean clean-files := consolemap_deftbl.c defkeymap.c qtronixmap.c diff -urN -X dontdiff linux-2.5.67/drivers/char/vm86.c linux-2.5.67-vm86/drivers/char/vm86.c --- linux-2.5.67/drivers/char/vm86.c 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.5.67-vm86/drivers/char/vm86.c 2003-04-12 17:28:52.000000000 +0200 @@ -0,0 +1,271 @@ +/* + * VM86 Kernel-User interface + * + * Copyright (C) 2003 Antonino Daplas + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file COPYING in the main directory of this archive for + * more details. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct vm86_info { + struct vm86_request request; + struct fasync_struct *async_queue; + int event; + int enabled; + int count; + int error; + int poll_mask; + void *buffer; +} *info = NULL; + +static DECLARE_WAIT_QUEUE_HEAD(vm86_wait); +static DECLARE_WAIT_QUEUE_HEAD(vm86_exec_wait); +static DECLARE_MUTEX(vm86_sem); + +/* File operations */ +static int vm86_fasync(int fd, struct file *file, int on) +{ + return fasync_helper(fd, file, on, &info->async_queue); +} + +static int vm86_open(struct inode *inode, struct file *file) +{ + if (info->count) + return -EINVAL; + info->count++; + info->enabled = 1; + return 0; +} + +static int vm86_release(struct inode *inode, struct file *file) +{ + if (!info->count) + return -EINVAL; + info->count--; + if (file->f_flags & FASYNC) + vm86_fasync(-1, file, 0); + memset(info, 0, sizeof(struct vm86_info)); + return 0; +} + +static ssize_t vm86_read(struct file *file, char *buf, size_t count, + loff_t *ppos) +{ + int retval = 0, c = sizeof(struct vm86_request); + DECLARE_WAITQUEUE(wait, current); + + if (!info->enabled) + return 0; + + add_wait_queue(&vm86_wait, &wait); + while (info->poll_mask != (POLLIN | POLLRDNORM)) { + set_current_state(TASK_INTERRUPTIBLE); + + retval = -EWOULDBLOCK; + if (file->f_flags & O_NDELAY) { + break; + } + retval = -ERESTARTSYS; + if (signal_pending(current)) { + break; + } + schedule(); + retval = 0; + } + info->poll_mask = 0; + remove_wait_queue(&vm86_wait, &wait); + current->state = TASK_RUNNING; + if (retval) { + info->event = 0; + info->error = 1; + return 0; + } + if (count) { + int i; + + if (copy_to_user(buf, &info->request, + sizeof(struct vm86_request))) { + info->event = 0; + info->error = 1; + return 0; + } + if (info->request.buf_len) { + i = copy_to_user(buf + sizeof(struct vm86_request), + info->buffer, + info->request.buf_len); + if (i) { + info->event = 0; + info->error = 1; + return 0; + } + c += info->request.buf_len; + } + } + info->poll_mask = POLLOUT | POLLRDNORM; + return c; +} + +static ssize_t vm86_write(struct file *file, const char *buf, + size_t count, loff_t *ppos) +{ + int retval, c = 0; + DECLARE_WAITQUEUE(wait, current); + + if (info->poll_mask != (POLLOUT | POLLRDNORM) || + !info->enabled) { + info->event = 0; + info->error = 1; + return 0; + } + + if (!info->enabled) + return 0; + + add_wait_queue(&vm86_wait, &wait); + while (info->poll_mask != (POLLOUT | POLLRDNORM)) { + set_current_state(TASK_INTERRUPTIBLE); + + retval = -EWOULDBLOCK; + if (file->f_flags & O_NDELAY) { + break; + } + retval = -ERESTARTSYS; + if (signal_pending(current)) { + break; + } + schedule(); + retval = 0; + } + info->poll_mask = 0; + remove_wait_queue(&vm86_wait, &wait); + current->state = TASK_RUNNING; + + if (count) { + info->error = copy_from_user(&info->request, buf, + sizeof(struct vm86_request)); + if (!info->error) { + c = sizeof(struct vm86_request); + if (info->request.buf_len) { + info->error = + copy_from_user(info->buffer, buf + c, + info->request.buf_len); + if (!info->error) + c += info->request.buf_len; + } + } + } + info->event = 0; + return c; +} + + +static unsigned int vm86_poll(struct file *file, poll_table *wait) +{ + poll_wait(file, &vm86_wait, wait); + + return info->poll_mask; +} + +static struct file_operations vm86_ops = { + .owner = THIS_MODULE, + .read = vm86_read, + .write = vm86_write, + .open = vm86_open, + .release = vm86_release, + .fasync = vm86_fasync, + .poll = vm86_poll, +}; + +static struct miscdevice vm86_dev = { + VM86_MINOR, + "vm86", + &vm86_ops +}; + +/** + * vm86_exec - execute instructions + * @request: pointer to instruction request data + * @buffer: 1024-byte min sized buffer for extra data + * + * ON ENTRY: @buffer must point to a valid buffer (1024 bytes). + * ON EXIT: @request contains results of x86 instructions. @request->buffer + * may contain additional data, depending on the code. Check + * @request->buf_len. + * WARNING: + * Will sleep + */ +int vm86_exec(struct vm86_request *request, void *buffer) +{ + int len; + unsigned long timeout; + static int next_tick = 3 * HZ; + + if (!info || !info->enabled) + return -ENODEV; + + if (request->flags & VM86_TEST) + return 0; + + len = sizeof(struct vm86_request) + request->buf_len; + if (len > 1024) + return -EINVAL; + + down(&vm86_sem); + + info->request = *request; + info->buffer = buffer; + info->error = 0; + info->event = 1; + info->poll_mask = POLLIN | POLLRDNORM; + kill_fasync(&info->async_queue, SIGIO, POLL_IN); /* send signal */ + + wake_up(&vm86_wait); + + while (info->event) + yield(); + + info->request.flags = (info->error) ? + VM86_FAILED : VM86_SUCCESS; + *request = info->request; + + up(&vm86_sem); + + return 0; +} + +static int __init vm86_init(void) +{ + + info = kmalloc(sizeof(struct vm86_info), GFP_KERNEL); + if (info == NULL) + return -ENOMEM; + memset(info, 0, sizeof(struct vm86_info)); + + if (misc_register(&vm86_dev)) { + kfree(info); + return -ENODEV; + } + return 0; +} + +static void __exit vm86_exit(void) +{ + misc_deregister(&vm86_dev); + kfree(info); +} + +module_init(vm86_init); +module_exit(vm86_exit); + +EXPORT_SYMBOL(vm86_exec); diff -urN -X dontdiff linux-2.5.67/include/linux/miscdevice.h linux-2.5.67-vm86/include/linux/miscdevice.h --- linux-2.5.67/include/linux/miscdevice.h 2003-01-18 06:35:12.000000000 +0100 +++ linux-2.5.67-vm86/include/linux/miscdevice.h 2003-04-12 08:27:33.000000000 +0200 @@ -35,6 +35,7 @@ #define SGI_USEMACLONE 151 #define TUN_MINOR 200 +#define VM86_MINOR 201 extern int misc_init(void); diff -urN -X dontdiff linux-2.5.67/include/linux/vm86.h linux-2.5.67-vm86/include/linux/vm86.h --- linux-2.5.67/include/linux/vm86.h 1970-01-01 01:00:00.000000000 +0100 +++ linux-2.5.67-vm86/include/linux/vm86.h 2003-04-12 08:27:33.000000000 +0200 @@ -0,0 +1,47 @@ +#ifndef __VM86_H__ +#define __VM86_H__ + +/* Based on LRMI */ +struct user_vm86_regs { + unsigned int edi; + unsigned int esi; + unsigned int ebp; + unsigned int reserved; + unsigned int ebx; + unsigned int edx; + unsigned int ecx; + unsigned int eax; + unsigned short int flags; + unsigned short int es; + unsigned short int ds; + unsigned short int fs; + unsigned short int gs; + unsigned short int ip; + unsigned short int cs; + unsigned short int sp; + unsigned short int ss; +}; + +/* flags after vm86_exec() */ +#define VM86_SUCCESS 0 +#define VM86_UNDEFINED 1 +#define VM86_FAILED 2 +#define VM86_TEST 4 + +struct vm86_request { + struct user_vm86_regs regs; + unsigned int flags; /* flags */ + unsigned int type; /* code type */ + unsigned int interrupt; /* interrupt service */ + unsigned int buf_len; /* extra buffers, if any */ + unsigned short bus; /* bus, device, function no. */ +}; + +#ifdef __KERNEL__ +#if defined(CONFIG_VM86) +extern int vm86_exec(struct vm86_request *request, void *buffer); +#else +#define vm86_exec(x, y) ( -EINVAL ) +#endif +#endif /* __KERNEL__ */ +#endif /* __VM86_H_ */