diff options
Diffstat (limited to 'drivers/sgi/char/streamable.c')
-rw-r--r-- | drivers/sgi/char/streamable.c | 363 |
1 files changed, 363 insertions, 0 deletions
diff --git a/drivers/sgi/char/streamable.c b/drivers/sgi/char/streamable.c index f26aad0e2..02e40cf05 100644 --- a/drivers/sgi/char/streamable.c +++ b/drivers/sgi/char/streamable.c @@ -361,3 +361,366 @@ streamable_init (void) misc_register (&dev_input_keyboard); misc_register (&dev_input_mouse); } +/* + * streamable.c: streamable devices. /dev/gfx + * (C) 1997 Miguel de Icaza (miguel@nuclecu.unam.mx) + * + * Major 10 is the streams clone device. The IRIX Xsgi server just + * opens /dev/gfx and closes it inmediately. + * + */ + +#include <linux/fs.h> +#include <linux/miscdevice.h> +#include <linux/sched.h> +#include <linux/kbd_kern.h> +#include <linux/vt_kern.h> +#include <asm/uaccess.h> +#include <asm/shmiq.h> +#include <asm/keyboard.h> +#include "graphics.h" + + +extern struct kbd_struct kbd_table [MAX_NR_CONSOLES]; + +/* console number where forwarding is enabled */ +int forward_chars; + +/* To which shmiq this keyboard is assigned */ +int kbd_assigned_device; + +/* previous kbd_mode for the forward_chars terminal */ +int kbd_prev_mode; + +/* Fetchs the strioctl information from user space for I_STR ioctls */ +int +get_sioc (struct strioctl *sioc, unsigned long arg) +{ + int v; + + v = verify_area (VERIFY_WRITE, (void *) arg, sizeof (struct strioctl)); + if (v) + return v; + if (copy_from_user (sioc, (void *) arg, sizeof (struct strioctl))) + return -EFAULT; + + v = verify_area (VERIFY_WRITE, (void *) sioc->ic_dp, sioc->ic_len); + if (v) + return v; + return 0; +} + +/* /dev/gfx device */ +static int +sgi_gfx_open (struct inode *inode, struct file *file) +{ + printk ("GFX: Opened by %d\n", current->pid); + return 0; +} + +static int +sgi_gfx_close (struct inode *inode, struct file *file) +{ + printk ("GFX: Closed by %d\n", current->pid); + return 0; +} + +static int +sgi_gfx_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + printk ("GFX: ioctl 0x%x %ld called\n", cmd, arg); + return 0; + return -EINVAL; +} + +struct file_operations sgi_gfx_fops = { + NULL, /* llseek */ + NULL, /* read */ + NULL, /* write */ + NULL, /* readdir */ + NULL, /* poll */ + sgi_gfx_ioctl, /* ioctl */ + NULL, /* mmap */ + sgi_gfx_open, /* open */ + sgi_gfx_close, /* release */ + NULL, /* fsync */ + NULL, /* check_media_change */ + NULL, /* revalidate */ + NULL /* lock */ +}; + +static struct miscdevice dev_gfx = { + SGI_GFX_MINOR, "sgi-gfx", &sgi_gfx_fops +}; + +/* /dev/input/keyboard streams device */ +static idevDesc sgi_kbd_desc = { + "keyboard", /* devName */ + "KEYBOARD", /* devType */ + 240, /* nButtons */ + 0, /* nValuators */ + 0, /* nLEDs */ + 0, /* nStrDpys */ + 0, /* nIntDpys */ + 0, /* nBells */ + IDEV_HAS_KEYMAP | IDEV_HAS_PCKBD +}; + +static int +sgi_kbd_sioc (idevInfo *dinfo, int cmd, int size, char *data, int *found) +{ + *found = 1; + + switch (cmd){ + + case IDEVINITDEVICE: + return 0; + + case IDEVGETDEVICEDESC: + if (size >= sizeof (idevDesc)){ + if (copy_to_user (data, &sgi_kbd_desc, sizeof (sgi_kbd_desc))) + return -EFAULT; + return 0; + } + return -EINVAL; + + case IDEVGETKEYMAPDESC: + if (size >= sizeof (idevKeymapDesc)){ + if (copy_to_user (data, "US", 3)) + return -EFAULT; + return 0; + } + return -EINVAL; + } + *found = 0; + return -EINVAL; +} + +static int +sgi_keyb_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + struct strioctl sioc; + int f, v; + + /* IRIX calls I_PUSH on the opened device, go figure */ + if (cmd == I_PUSH) + return 0; + + if (cmd == I_STR){ + v = get_sioc (&sioc, arg); + if (v) + return v; + + /* Why like this? Because this is a sample piece of code + * that can be copied into other drivers and shows how to + * call a stock IRIX xxx_wioctl routine + * + * The NULL is supposed to be a idevInfo, right now we + * do not support this in our kernel. + */ + return sgi_kbd_sioc (NULL, sioc.ic_cmd, sioc.ic_len, sioc.ic_dp, &f); + } + + if (cmd == SHMIQ_ON){ + kbd_assigned_device = arg; + forward_chars = fg_console + 1; + kbd_prev_mode = kbd_table [fg_console].kbdmode; + + kbd_table [fg_console].kbdmode = VC_RAW; + } else if (cmd == SHMIQ_OFF && forward_chars){ + kbd_table [forward_chars-1].kbdmode = kbd_prev_mode; + forward_chars = 0; + } else + return -EINVAL; + return 0; +} + +void +kbd_forward_char (int ch) +{ + static struct shmqevent ev; + + ev.data.flags = (ch & 0200) ? 0 : 1; + ev.data.which = ch; + ev.data.device = kbd_assigned_device + 0x11; + shmiq_push_event (&ev); +} + +static int +sgi_keyb_open (struct inode *inode, struct file *file) +{ + /* Nothing, but required by the misc driver */ + return 0; +} + +struct file_operations sgi_keyb_fops = { + NULL, /* llseek */ + NULL, /* read */ + NULL, /* write */ + NULL, /* readdir */ + NULL, /* poll */ + sgi_keyb_ioctl, /* ioctl */ + NULL, /* mmap */ + sgi_keyb_open, /* open */ + NULL, /* release */ + NULL, /* fsync */ + NULL, /* check_media_change */ + NULL, /* revalidate */ + NULL /* lock */ +}; + +static struct miscdevice dev_input_keyboard = { + SGI_STREAMS_KEYBOARD, "streams-keyboard", &sgi_keyb_fops +}; + +/* /dev/input/mouse streams device */ +#define MOUSE_VALUATORS 2 +static idevDesc sgi_mouse_desc = { + "mouse", /* devName */ + "MOUSE", /* devType */ + 3, /* nButtons */ + MOUSE_VALUATORS, /* nValuators */ + 0, /* nLEDs */ + 0, /* nStrDpys */ + 0, /* nIntDpys */ + 0, /* nBells */ + 0 /* flags */ +}; + +static idevValuatorDesc mouse_default_valuator = { + 200, /* hwMinRes */ + 200, /* hwMaxRes */ + 0, /* hwMinVal */ + 65000, /* hwMaxVal */ + IDEV_EITHER, /* possibleModes */ + IDEV_ABSOLUTE, /* default mode */ + 200, /* resolution */ + 0, /* minVal */ + 65000 /* maxVal */ +}; + +static int mouse_opened; +static idevValuatorDesc mouse_valuators [MOUSE_VALUATORS]; + +int +sgi_mouse_open (struct inode *inode, struct file *file) +{ + int i; + + if (mouse_opened) + return -EBUSY; + + mouse_opened = 1; + for (i = 0; i < MOUSE_VALUATORS; i++) + mouse_valuators [i] = mouse_default_valuator; + return 0; +} + +static int +sgi_mouse_close (struct inode *inode, struct file *filp) +{ + mouse_opened = 0; + return 0; +} + +static int +sgi_mouse_sioc (idevInfo *dinfo, int cmd, int size, char *data, int *found) +{ + *found = 1; + + switch (cmd){ + case IDEVINITDEVICE: + return 0; + + case IDEVGETDEVICEDESC: + if (size >= sizeof (idevDesc)){ + if (copy_to_user (data, &sgi_mouse_desc, sizeof (sgi_mouse_desc))) + return -EFAULT; + return 0; + } + return -EINVAL; + + case IDEVGETVALUATORDESC: { + idevGetSetValDesc request, *ureq = (idevGetSetValDesc *) data; + + if (size < sizeof (idevGetSetValDesc)) + return -EINVAL; + + if (copy_from_user (&request, data, sizeof (request))) + return -EFAULT; + if (request.valNum >= MOUSE_VALUATORS) + return -EINVAL; + if (copy_to_user ((void *)&ureq->desc, + (void *)&mouse_valuators [request.valNum], + sizeof (idevValuatorDesc))) + return -EFAULT; + return 0; + } + } + *found = 0; + return -EINVAL; +} + +static int +sgi_mouse_ioctl (struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) +{ + struct strioctl sioc; + int f, v; + + /* IRIX calls I_PUSH on the opened device, go figure */ + switch (cmd){ + case I_PUSH: + return 0; + + case I_STR: + v = get_sioc (&sioc, arg); + if (v) + return v; + + /* Why like this? Because this is a sample piece of code + * that can be copied into other drivers and shows how to + * call a stock IRIX xxx_wioctl routine + * + * The NULL is supposed to be a idevInfo, right now we + * do not support this in our kernel. + */ + return sgi_mouse_sioc (NULL, sioc.ic_cmd, sioc.ic_len, sioc.ic_dp, &f); + + case SHMIQ_ON: + case SHMIQ_OFF: + return 0; + } + return 0; +} + +struct file_operations sgi_mouse_fops = { + NULL, /* llseek */ + NULL, /* read */ + NULL, /* write */ + NULL, /* readdir */ + NULL, /* poll */ + sgi_mouse_ioctl, /* ioctl */ + NULL, /* mmap */ + sgi_mouse_open, /* open */ + sgi_mouse_close, /* release */ + NULL, /* fsync */ + NULL, /* check_media_change */ + NULL, /* revalidate */ + NULL /* lock */ +}; + +/* /dev/input/mouse */ +static struct miscdevice dev_input_mouse = { + SGI_STREAMS_KEYBOARD, "streams-mouse", &sgi_mouse_fops +}; + +void +streamable_init (void) +{ + printk ("streamable misc devices registered (keyb:%d, gfx:%d)\n", + SGI_STREAMS_KEYBOARD, SGI_GFX_MINOR); + + misc_register (&dev_gfx); + misc_register (&dev_input_keyboard); + misc_register (&dev_input_mouse); +} |