6b3f4dc157
This commit separates the low-level keyboard driver from TTY, putting it in a separate driver (PCKBD). The commit also separates management of raw input devices from TTY, and puts it in a separate server (INPUT). All keyboard and mouse input from hardware is sent by drivers to the INPUT server, which either sends it to a process that has opened a raw input device, or otherwise forwards it to TTY for standard processing. Design by Dirk Vogt. Prototype by Uli Kastlunger. Additional changes made to the prototype: - the event communication is now based on USB HID codes; all input drivers have to use USB codes to describe events; - all TTY keymaps have been converted to USB format, with the effect that a single keymap covers all keys; there is no (static) escaped keymap anymore; - further keymap tweaks now allow remapping of literally all keys; - input device renumbering and protocol rewrite; - INPUT server rewrite, with added support for cancel and select; - PCKBD reimplementation, including PC/AT-to-USB translation; - support for manipulating keyboard LEDs has been added; - keyboard and mouse multiplexer devices have been added to INPUT, primarily so that an X server need only open two devices; - a new "libinputdriver" library abstracts away protocol details from input drivers, and should be used by all future input drivers; - both INPUT and PCKBD can be restarted; - TTY is now scheduled by KERNEL, so that it won't be punished for running a lot; without this, simply running "yes" on the console kills the system; - the KIOCBELL IOCTL has been moved to /dev/console; - support for the SCANCODES termios setting has been removed; - obsolete keymap compression has been removed; - the obsolete Olivetti M24 keymap has been removed. Change-Id: I3a672fb8c4fd566734e4b46d3994b4b7fc96d578
212 lines
4.7 KiB
C
212 lines
4.7 KiB
C
|
|
#define _SYSTEM 1
|
|
|
|
#include <minix/callnr.h>
|
|
#include <minix/com.h>
|
|
#include <minix/config.h>
|
|
#include <minix/const.h>
|
|
#include <minix/ds.h>
|
|
#include <minix/endpoint.h>
|
|
#include <minix/minlib.h>
|
|
#include <minix/type.h>
|
|
#include <minix/ipc.h>
|
|
#include <minix/sysutil.h>
|
|
#include <minix/syslib.h>
|
|
#include <minix/safecopies.h>
|
|
#include <minix/bitmap.h>
|
|
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <env.h>
|
|
#include <stdio.h>
|
|
#include <assert.h>
|
|
|
|
#include "glo.h"
|
|
#include "proto.h"
|
|
#include "util.h"
|
|
#include "region.h"
|
|
|
|
/*===========================================================================*
|
|
* do_rs_set_priv *
|
|
*===========================================================================*/
|
|
int do_rs_set_priv(message *m)
|
|
{
|
|
int r, n, nr;
|
|
struct vmproc *vmp;
|
|
bitchunk_t call_mask[VM_CALL_MASK_SIZE], *call_mask_p;
|
|
|
|
nr = m->VM_RS_NR;
|
|
|
|
if ((r = vm_isokendpt(nr, &n)) != OK) {
|
|
printf("do_rs_set_priv: bad endpoint %d\n", nr);
|
|
return EINVAL;
|
|
}
|
|
|
|
vmp = &vmproc[n];
|
|
|
|
if (m->VM_RS_BUF) {
|
|
r = sys_datacopy(m->m_source, (vir_bytes) m->VM_RS_BUF, SELF,
|
|
(vir_bytes) call_mask, sizeof(call_mask));
|
|
if (r != OK)
|
|
return r;
|
|
call_mask_p = call_mask;
|
|
} else {
|
|
if (m->VM_RS_SYS) {
|
|
printf("VM: do_rs_set_priv: sys procs don't share!\n");
|
|
return EINVAL;
|
|
}
|
|
call_mask_p = NULL;
|
|
}
|
|
|
|
acl_set(vmp, call_mask_p, m->VM_RS_SYS);
|
|
|
|
return OK;
|
|
}
|
|
|
|
/*===========================================================================*
|
|
* do_rs_update *
|
|
*===========================================================================*/
|
|
int do_rs_update(message *m_ptr)
|
|
{
|
|
endpoint_t src_e, dst_e, reply_e;
|
|
int src_p, dst_p;
|
|
struct vmproc *src_vmp, *dst_vmp;
|
|
int r;
|
|
|
|
src_e = m_ptr->VM_RS_SRC_ENDPT;
|
|
dst_e = m_ptr->VM_RS_DST_ENDPT;
|
|
|
|
/* Lookup slots for source and destination process. */
|
|
if(vm_isokendpt(src_e, &src_p) != OK) {
|
|
printf("do_rs_update: bad src endpoint %d\n", src_e);
|
|
return EINVAL;
|
|
}
|
|
src_vmp = &vmproc[src_p];
|
|
if(vm_isokendpt(dst_e, &dst_p) != OK) {
|
|
printf("do_rs_update: bad dst endpoint %d\n", dst_e);
|
|
return EINVAL;
|
|
}
|
|
dst_vmp = &vmproc[dst_p];
|
|
|
|
/* Let the kernel do the update first. */
|
|
r = sys_update(src_e, dst_e);
|
|
if(r != OK) {
|
|
return r;
|
|
}
|
|
|
|
/* Do the update in VM now. */
|
|
r = swap_proc_slot(src_vmp, dst_vmp);
|
|
if(r != OK) {
|
|
return r;
|
|
}
|
|
r = swap_proc_dyn_data(src_vmp, dst_vmp);
|
|
if(r != OK) {
|
|
return r;
|
|
}
|
|
pt_bind(&src_vmp->vm_pt, src_vmp);
|
|
pt_bind(&dst_vmp->vm_pt, dst_vmp);
|
|
|
|
/* Reply, update-aware. */
|
|
reply_e = m_ptr->m_source;
|
|
if(reply_e == src_e) reply_e = dst_e;
|
|
else if(reply_e == dst_e) reply_e = src_e;
|
|
m_ptr->m_type = OK;
|
|
r = send(reply_e, m_ptr);
|
|
if(r != OK) {
|
|
panic("send() error");
|
|
}
|
|
|
|
return SUSPEND;
|
|
}
|
|
|
|
/*===========================================================================*
|
|
* rs_memctl_make_vm_instance *
|
|
*===========================================================================*/
|
|
static int rs_memctl_make_vm_instance(struct vmproc *new_vm_vmp)
|
|
{
|
|
int r;
|
|
u32_t flags;
|
|
int verify;
|
|
struct vmproc *this_vm_vmp;
|
|
|
|
this_vm_vmp = &vmproc[VM_PROC_NR];
|
|
|
|
/* Pin memory for the new VM instance. */
|
|
r = map_pin_memory(new_vm_vmp);
|
|
if(r != OK) {
|
|
return r;
|
|
}
|
|
|
|
/* Preallocate page tables for the entire address space for both
|
|
* VM and the new VM instance.
|
|
*/
|
|
flags = 0;
|
|
verify = FALSE;
|
|
r = pt_ptalloc_in_range(&this_vm_vmp->vm_pt, 0, 0, flags, verify);
|
|
if(r != OK) {
|
|
return r;
|
|
}
|
|
r = pt_ptalloc_in_range(&new_vm_vmp->vm_pt, 0, 0, flags, verify);
|
|
if(r != OK) {
|
|
return r;
|
|
}
|
|
|
|
/* Let the new VM instance map VM's page tables and its own. */
|
|
r = pt_ptmap(this_vm_vmp, new_vm_vmp);
|
|
if(r != OK) {
|
|
return r;
|
|
}
|
|
r = pt_ptmap(new_vm_vmp, new_vm_vmp);
|
|
if(r != OK) {
|
|
return r;
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|
|
/*===========================================================================*
|
|
* do_rs_memctl *
|
|
*===========================================================================*/
|
|
int do_rs_memctl(message *m_ptr)
|
|
{
|
|
endpoint_t ep;
|
|
int req, r, proc_nr;
|
|
struct vmproc *vmp;
|
|
|
|
ep = m_ptr->VM_RS_CTL_ENDPT;
|
|
req = m_ptr->VM_RS_CTL_REQ;
|
|
|
|
/* Lookup endpoint. */
|
|
if ((r = vm_isokendpt(ep, &proc_nr)) != OK) {
|
|
printf("do_rs_memctl: bad endpoint %d\n", ep);
|
|
return EINVAL;
|
|
}
|
|
vmp = &vmproc[proc_nr];
|
|
|
|
/* Process request. */
|
|
switch(req)
|
|
{
|
|
case VM_RS_MEM_PIN:
|
|
|
|
/* Do not perform VM_RS_MEM_PIN yet - it costs the full
|
|
* size of the RS stack (64MB by default) in memory,
|
|
* and it's needed for functionality that isn't complete /
|
|
* merged in current Minix (surviving VM crashes).
|
|
*/
|
|
|
|
#if 0
|
|
r = map_pin_memory(vmp);
|
|
return r;
|
|
#else
|
|
return OK;
|
|
#endif
|
|
|
|
case VM_RS_MEM_MAKE_VM:
|
|
r = rs_memctl_make_vm_instance(vmp);
|
|
return r;
|
|
default:
|
|
printf("do_rs_memctl: bad request %d\n", req);
|
|
return EINVAL;
|
|
}
|
|
}
|
|
|