--- /dev/null
+Process Management
+==================
+
+Each task in Fuzix consists of two structures. The first is the process
+table entry (struct p_tab, ptptr). This holds the elements of the
+process information that are required all of the time. The remaining
+data is stored in a per process structure called udata structure (struct
+u_data). This is assumed to be mapped at a fixed address in memory
+although this can be changed (see advanced topics). The udata fields are
+only required when this process is being executed. This allows them to
+be swapped or banked out of the address space when the process is not
+running. The udata also usually holds the kernel and any interrupt
+stacks for the process. This allows them to be swapped out or banked
+out. Note that this means references to objects on the kernel stacks of
+a process must never be used from another process or interrupt.
+
+The fixed address mapping of udata allows the compilers to generate much
+better code on most 8bit processors than would be the case if pointer
+indirections where used.
+
+In the normal mode of operation the kernel multi-tasks by switching
+between processes when they block, when they exceed their available CPU
+time when running application code, or at the end of a system call which
+has exceeded the available time. Tasks are not pre-empted during a
+system call unless they block, nor is any real time scheduling system
+implemented.
+
+Scheduling
+----------
+
+Fuzix implements a fairly simple task scheduler designed to work
+efficiently with a small number of processes while using the minimum
+amount of memory. Runnable tasks execute in strict FIFO order with lower
+priority tasks being given less CPU time. The scheduler does not
+currently punish CPU heavy tasks. There is no idle task, instead the
+kernel repeatedly invokes platform_idle() when there is no work to be
+done. This function can execute platform specific device polling or CPU
+idle and halt instructions as appropriate.
+
+If the kernel is compiled in single tasking mode only the most recent
+task is ever scheduled. When a fork() occurs the child runs to
+completion before the parent is woken.
+
+Task States
+-----------
+
+The Fuzix task states roughly match those of most Unix like systems.
+They implement the expected Unix semantics of zombie processes and
+wait().
+
++-----------------------------------+-----------------------------------+
+| P_EMPTY | A slot in the task array that is |
+| | not being used |
++-----------------------------------+-----------------------------------+
+| P_RUNNING | The current executing task |
++-----------------------------------+-----------------------------------+
+| P_READY | A task which can be run but is |
+| | not assigned the CPU |
++-----------------------------------+-----------------------------------+
+| P_SLEEP | A task which is waiting for an |
+| | event or a signal |
++-----------------------------------+-----------------------------------+
+| P_IOWAIT | A task which is waiting for an |
+| | event, but will not be woken by a |
+| | signal |
++-----------------------------------+-----------------------------------+
+| P_STOPPED | A task that is suspended and not |
+| | runnable until it receives a |
+| | waking signal (SIGCONT) |
++-----------------------------------+-----------------------------------+
+| P_FORKING | A task that is currently being |
+| | forked |
++-----------------------------------+-----------------------------------+
+| P_ZOMBIE | A task that has exited. Only the |
+| | process table entry remains |
+| | waiting for wait() to reap the |
+| | process |
++-----------------------------------+-----------------------------------+
+| P_NOSLEEP | An internal state where sleeping |
+| | is forbidden. |
++-----------------------------------+-----------------------------------+
+
+Sleeping And Waking
+-------------------
+
+Processes sleep by calling psleep() and passing a cookie which is the
+address of an object. In general you should choose a representative
+address such as the pointer to the object being waited upon, or a field
+within it. Waiting on NULL is a wait which will not be woken by an
+event.
+
+Processes waiting for an event will be woken by a called to wakeup()
+with the same event cookie. It is important to note that a wakeup wakes
+all processes that are waiting on the event. On a small machine with
+little memory it is very important to wake only those processes which
+need to be woken. Decisions about which task to wake should be made by
+the waker not by the processes being woken.
+
+Where it is necessary to explicitly wake a specific process because the
+wake queues are not sufficient to implement the desired precise wake
+semantics it is also possible to call pwake() to wake a process
+explicitly.
+
+Kernel Facilities
+-----------------
+
+This documents only those facilities intended to be used by driver and
+platform code. There are many more process manipulation functions but
+they should not be needed by platform or drivers.
+
+**void psleep(void \*event)**
+
+Move the running process from P_RUNNING into P_SLEEP if an event cookie
+is passed, or into P_PAUSE if not. Execution will continue with another
+task or the platform_idle code, until the task is woken, whereupon it
+will return from psleep.
+
+Take particular care when testing an event that is set in an interrupt.
+You should disable interrupts before testing and calling psleep and then
+restore interrupts on return. The kernel core will deal with re-enabling
+interrupts on the task switch.
+
+**void wakeup(void \*event)**
+
+Wake all processes that are sleeping on the passed event cookie. The
+current process will remain P_RUNNING, while those woken will move to
+P_READY and will be scheduled when the waking task pre-empts them. This
+function may also be called from an interrupt, in which case the same
+will occur, or if the system is executing platform_idle it will begin
+running a task.
+
+**void pwake(ptptr p)**
+
+Explicitly wake a task. The task will enter P_READY state if not already
+ready or running. Tasks in P_FORKING or P_ZOMBIE will not be
+affected. This function can be called from interrupts but care must be
+taken that the interrupt wake is disabled before the process exits.
+Where possible use wakeup and events.
+
+**int need_resched(void)**
+
+Returns true if the current process has exceeded its time allocation.
+This is useful in busy waiting or bitbanging applications where the
+driver needs to know when to sleep and when to poll.
+
+**p->p_timeout**
+
+This field holds a timeout. If this is set to 1 plus the number of
+centiseconds to wait then the process will be woken after the timeout.
+The process can then check if this value is 1 indicating a timeout. Each
+system call this field is cleared.
+
+Signals
+-------
+
+Fuzix implements all of the classic V7 signals and a subset of the newer
+ones. The kernel provides signal handling functionality based upon the
+System 5 API rather than the BSD interface. This is because the kernel
+parts of the System 5 interface are smaller and cleaner, whilst a C
+library can implement the POSIX API on either.
+
+The following signals are provided
+
++-----------------------+-----------------------+-----------------------+
+| SIGHUP | Yes | Sent to a process |
+| | | whose controlling tty |
+| | | hangs up. |
++-----------------------+-----------------------+-----------------------+
+| SIGINT | Yes | Sent when the user |
+| | | types the interrupt |
+| | | character (usually |
+| | | ^C). |
++-----------------------+-----------------------+-----------------------+
+| SIGQUIT | Yes | Sent when the user |
+| | | types the quit |
+| | | character (usually |
+| | | ^\\). |
++-----------------------+-----------------------+-----------------------+
+| SIGILL | Platform | Sent when an illegal |
+| | | instruction is |
+| | | executed. Most 8bit |
+| | | platforms do not |
+| | | support illegal |
+| | | instruction |
+| | | reporting. |
++-----------------------+-----------------------+-----------------------+
+| SIGTRAP | Platform | Sent when a trap |
+| | | occurs if the |
+| | | platform implements |
+| | | traps. |
++-----------------------+-----------------------+-----------------------+
+| SIGABORT | Yes | Sent from userspace |
+| | | when the abort() |
+| | | library function is |
+| | | called. |
++-----------------------+-----------------------+-----------------------+
+| SIGIOT | Platform | I/O trap. Not |
+| | | implemented by |
+| | | current platforms. |
++-----------------------+-----------------------+-----------------------+
+| SIGBUS | Platform | Sent when the |
+| | | platform receives a |
+| | | bus error. |
++-----------------------+-----------------------+-----------------------+
+| SIGFPE | Platform | Sent when a platform |
+| | | receives a floating |
+| | | point exception. In |
+| | | some cases also sent |
+| | | when division by zero |
+| | | is attempted. |
++-----------------------+-----------------------+-----------------------+
+| SIGKILL | Yes | Sent by one process |
+| | | to another to kill a |
+| | | process. Cannot be |
+| | | blocked or deferred. |
++-----------------------+-----------------------+-----------------------+
+| SIGUSR1 | Yes | Reserved for user. |
++-----------------------+-----------------------+-----------------------+
+| SIGSEGV | Platform | A segmentation fault |
+| | | trap was taken by the |
+| | | hardware. |
++-----------------------+-----------------------+-----------------------+
+| SIGUSR2 | Yes | Reserved for user. |
++-----------------------+-----------------------+-----------------------+
+| SIGPIPE | Yes | A write was attempted |
+| | | to a pipe with no |
+| | | readers. |
++-----------------------+-----------------------+-----------------------+
+| SIGALRM | Yes | An alarm timed out. |
++-----------------------+-----------------------+-----------------------+
+| SIGTERM | Yes | Sent by one process |
+| | | to another to request |
+| | | termination. Can be |
+| | | blocked or caught. |
++-----------------------+-----------------------+-----------------------+
+| SIGSTKFLT | Platform | Sent when the |
+| | | platform detects a |
+| | | stack fault. |
++-----------------------+-----------------------+-----------------------+
+| SIGCHLD | Yes | Sent to the parent |
+| | | when the child exits. |
++-----------------------+-----------------------+-----------------------+
+| SIGCONT | Yes | Continue a process |
+| | | stopped with SIGSTOP |
+| | | or SIGTSTP. |
++-----------------------+-----------------------+-----------------------+
+| SIGSTOP | Yes | Freeze a process and |
+| | | prevent further |
+| | | execution until |
+| | | continued. Cannot be |
+| | | blocked or deferred. |
++-----------------------+-----------------------+-----------------------+
+| SIGTSTP | No | Sent when the stop |
+| | | character is used to |
+| | | halt a process. |
++-----------------------+-----------------------+-----------------------+
+| SIGTTIN | No | Job control. |
++-----------------------+-----------------------+-----------------------+
+| SIGTTOU | No | Job control. |
++-----------------------+-----------------------+-----------------------+
+| SIGURG | No | Sent when an urgent |
+| | | event occurs. |
+| | | Normally used for |
+| | | networking. Available |
+| | | for platform specific |
+| | | uses. |
++-----------------------+-----------------------+-----------------------+
+| SIGXCPU | No | CPU ulimit exceeded. |
++-----------------------+-----------------------+-----------------------+
+| SIGXFSZ | Yes | File size exceeded. |
++-----------------------+-----------------------+-----------------------+
+| SIGVTALRM | No | Virtual alarm timed |
+| | | out. |
++-----------------------+-----------------------+-----------------------+
+| SIGPROF | No | Used for profiling. |
++-----------------------+-----------------------+-----------------------+
+| SIGWINCH | Platform | The console window |
+| | | has changed size. No |
+| | | current console |
+| | | supports window size |
+| | | changes. |
++-----------------------+-----------------------+-----------------------+
+| SIGIO/SIGPOLL | No | Used for asynchronous |
+| | | I/O notifications. |
++-----------------------+-----------------------+-----------------------+
+| SIGPWR | Platform | Sent when power is |
+| | | restored so that |
+| | | processes may refresh |
+| | | their display. |
++-----------------------+-----------------------+-----------------------+
+| SIGSYS | No | Sent when an invalid |
+| | | system call is made. |
++-----------------------+-----------------------+-----------------------+
+
+Signals may be sent either to processes or to process groups. The kernel
+implements kill(), signal() and a private sigdisp() function which is
+used by the C library to provide sighold() and sigrelse(). The SIG_IGN
+and SIG_DFL behaviours are implemented.
+
+The kernel provides signal helper methods to platform and driver code.
+These include methods for delivering signals and for implementing the
+platform or CPU specific signal processing logic.
+
+**void ssig(ptrptr p, uint_fast8_t sig)**
+
+Sends a signal to the specified process. A signal delivered to the
+current process will be handled asynchronously when the task returns to
+user space. For synchronous delivery see the Advanced Topics section.
+
+**void sgrpsig(uint16_t pgrp, uint_fast8_t sig)**
+
+Sends a signal to the specified process group. The signal will be
+delivered and handled asynchronously in the same way as ssig().
+
+**uint_fast8_t chksigs(void)**
+
+Recompute the pending signals for the process and place the next signal
+to be delivered into udata.u_cursig. This is used by the CPU and
+platform specific syscall exit paths in order to identify signal
+delivery events.
+
+Platform and CPU Provided Methods
+---------------------------------
+
+The required methods for each platform are provided by the platform
+layer, but may well be included from library code, or in most cases will
+be similar for systems. Most implementations are based upon the existing
+examples. As some methods such as switchout are very tricky it is
+strongly recommended any new implementation is closely based upon an
+existing one or uses the library implementations when possible.
+
+The defines for process management are as follows
+
+**PTABSIZE**
+
+This gives the maximum number of processes that can exist at a time. It
+defaults to 15 which is actually plenty for a small single user micro.
+
+The methods that are required for process management are as follows
+
+**void platform_switchout(void)**
+
+Save the current state of the process onto the process kernel stack or
+into udata then call getproc and switchin in order to execute a new
+task. Switchin() and switchout() co-operate such that the task appears
+to return from switchout() when and if it resumes execution. This
+function may be called with interrupts disabled. Do not assume a process
+that calls switchout() will ever switchin() again. Process exit is
+implemented by doing a switchin() of the next task and later freeing the
+process table resources of the exiting task.
+
+**int switchin(ptptr p)**
+
+Resume execution of the process p as if it had returned from
+switchout(). Upon return interrupts should either be re-enabled or
+restored to the state at the time of switchout().
+
+**int dofork(ptptr new)**
+
+Fork the current process into the proces new. At the point of entry new
+is not fully set up. The dofork function is expected to copy the udata,
+copy the process memory image, set up the stack such that both the
+parent and child will seem to return from the dofork() call, the parent
+with the child pid, the child with pid 0, call newproc with the new
+ptptr and then return in the context of the child process.
+
+**void map_init(void)**
+
+The init process is special as it is created out of thin air rather than
+forked from an existing process. The map_init function allows the
+platform to set up data for init. At the point of entry init_process is
+a ptptr to the init task, and udata is the udata of the newly created
+task. The kernel is effectively running as if it was executing system
+call for init. It then completes startup by executing an execve system
+call on behalf of the new init process. On most platforms map_init()
+will either be an empty function, or set up some memory management
+fields.
+
+Advanced Topics
+---------------
+
+The udata is normally a fixed address object. For some processors such
+as the 68000 this does not really make sense. On these platforms udata
+can be defined to be (&udata_ptr) and udata_ptr maintained by the
+platform code to point to the current udata, either as a static variable
+or a register global. If udata is defined then a udata_ptr is made
+available for the platform/CPU code in each process structure.
+
+The fixed location udata poses a problem in some situations because it
+needs to be mapped in whenever the kernel is executing code for this
+process, but also needs to be banked with the process. In some cases it
+may be necessary to implement udata copying in preference to a udata
+pointer. Z80 platforms do this as the cost of udata being indirectly
+referenced exceeds the pain of copying.
+
+In some situations a signal needs to be delivered synchronously, e.g. an
+unrecoverable alignment error. In this case it is sufficient to call
+ssig() as the process will take the signal handler when the code
+prepares to return to user space. The library code may also wish to
+stack a call to \_exit on the user stack before the signal is takem so
+that a signal handler that returns exits the process.
+
+When an exception requires an immediate exit of the process to avoid
+further harm a SIGKILL should be delivered. This will always exit the
+process.
+
+Future Directions
+-----------------
+
+More of the signals will become available and implemented. In particular
+SIGCHLD and SIGSTOP behaviour. Other areas such as job control are
+probably too complex to fit in a small 8bit system, but will be more
+relevant to a 16/32bit system.
+
+Many of the current processors do not have a trap
+interface or a clear kernel and user mode. As a result their current
+lowlevel-$(cpu) implementations are a bit fuzzy about kernel and user
+space divides when delivering signals and do not deliver any kind of
+signal information frame on the stack with the signal call.
+
+There may be a need for a sigreturn system call and path on bigger
+machines to get the semantics right.
+
+Process And Udata Fields And Meaning
+------------------------------------
+
+Process Table
+~~~~~~~~~~~~~
+
++-----------------------------------+-----------------------------------+
+| p_status | Execution state of the process |
+| | (see Task States) |
++-----------------------------------+-----------------------------------+
+| p_tty | The minor number of the |
+| | controlling tty for this process |
++-----------------------------------+-----------------------------------+
+| p_pid | The process identifier |
++-----------------------------------+-----------------------------------+
+| p_uid | The real uid for this process |
++-----------------------------------+-----------------------------------+
+| p_pptr | Pointer to our parent process. |
++-----------------------------------+-----------------------------------+
+| p_alarm | Centiseconds until alarm occurs |
++-----------------------------------+-----------------------------------+
+| p_exitval | Exit code for the process (set |
+| | when it terminates) |
++-----------------------------------+-----------------------------------+
+| p_wait | Cookie used in psleep/pwait |
++-----------------------------------+-----------------------------------+
+| p_page | If zero no memory is allocated to |
+| | this process and p_page2 is swap |
+| | data, otherwise platform specific |
+| | memory management information |
++-----------------------------------+-----------------------------------+
+| p_page2 | Either swap location, or if in |
+| | memory further platform specific |
+| | memory data |
++-----------------------------------+-----------------------------------+
+| p_udata | Pointer to the process udata (not |
+| | present for fixed address udata) |
++-----------------------------------+-----------------------------------+
+| p_priority | Process priority |
++-----------------------------------+-----------------------------------+
+| p_sig | Signal structures |
++-----------------------------------+-----------------------------------+
+| p_waitno | Wait counter value, used to work |
+| | out what to swap |
++-----------------------------------+-----------------------------------+
+| p_timeout | 0 – no timeout, 1 – timed out, 2+ |
+| | number of centiseconds -1 left |
+| | before timeout |
++-----------------------------------+-----------------------------------+
+| p_name | First 8 bytes of the executable |
+| | name |
++-----------------------------------+-----------------------------------+
+| p_time | Time used by this process |
++-----------------------------------+-----------------------------------+
+| p_utime | User time used by this process |
++-----------------------------------+-----------------------------------+
+| p_stime | System time used by this process |
++-----------------------------------+-----------------------------------+
+| p_cutime | User time used by this process |
+| | and completed children |
++-----------------------------------+-----------------------------------+
+| p_cstime | System time used by this process |
+| | and completed children |
++-----------------------------------+-----------------------------------+
+| p_pgrp | The process group this process |
+| | belongs to |
++-----------------------------------+-----------------------------------+
+| p_nice | The nice value for this process |
++-----------------------------------+-----------------------------------+
+| p_event | Process events (for job control) |
++-----------------------------------+-----------------------------------+
+| p_top | Copy of u_top for swapping |
++-----------------------------------+-----------------------------------+
+| p_flags | Process bit flags |
++-----------------------------------+-----------------------------------+
+| p_session | Job control session (level 2) |
++-----------------------------------+-----------------------------------+
+| p_profscale | Profiling scaling shift |
++-----------------------------------+-----------------------------------+
+| p_profbuf | Profiling buffer base |
++-----------------------------------+-----------------------------------+
+| p_profsize | Profiling size |
++-----------------------------------+-----------------------------------+
+| p_profoff | Offset of memory to profile |
++-----------------------------------+-----------------------------------+
+
+When a process enters P_ZOMBIE state prior to exiting the values from
+p_priority down are overlaid with the exit state and data
+
+User Data Structure
+~~~~~~~~~~~~~~~~~~~
+
++-----------------------------------+-----------------------------------+
+| u_ptab | Pointer to the process table |
+| | entry for this process |
++-----------------------------------+-----------------------------------+
+| u_page | Copy of p_page, during fork the |
+| | two may differ temporarily |
++-----------------------------------+-----------------------------------+
+| u_page2 | Copy of p_page2, during fork the |
+| | two may differ temporarily |
++-----------------------------------+-----------------------------------+
+| u_insys | True if in the kernel |
++-----------------------------------+-----------------------------------+
+| u_callno | Current system call number being |
+| | executed |
++-----------------------------------+-----------------------------------+
+| u_syscall_sp | User stack point when syscall |
+| | occurred |
++-----------------------------------+-----------------------------------+
+| u_retval | Return value from syscall |
++-----------------------------------+-----------------------------------+
+| u_error | Last error code from syscall |
++-----------------------------------+-----------------------------------+
+| u_sp | Stack pointer saved when task |
+| | switching |
++-----------------------------------+-----------------------------------+
+| u_ininterrupt | True if running on our interrupt |
+| | stack |
++-----------------------------------+-----------------------------------+
+| u_cursig | Current signal to deliver |
+| | (computed by chksigs()) |
++-----------------------------------+-----------------------------------+
+| u_argn | System call argument |
++-----------------------------------+-----------------------------------+
+| u_argn1 | Second system call argument |
++-----------------------------------+-----------------------------------+
+| u_argn2 | Third system call argument |
++-----------------------------------+-----------------------------------+
+| u_argn3 | Fourth system call argument |
++-----------------------------------+-----------------------------------+
+| u_isp | Initial stack pointer to use |
+| | during doexec() when entering |
+| | user space |
++-----------------------------------+-----------------------------------+
+| u_top | Top of memory for this task (will |
+| | be moving to process table) |
++-----------------------------------+-----------------------------------+
+| u_break | Top of data for this task |
++-----------------------------------+-----------------------------------+
+| u_codebase | Load address of binary (32bit) |
++-----------------------------------+-----------------------------------+
+| u_sigvec | Array of 32 user mode function |
+| | pointers for signal handlers |
++-----------------------------------+-----------------------------------+
+| u_base | Source or destination for |
+| | character style I/O |
++-----------------------------------+-----------------------------------+
+| u_count | Number of bytes for character |
+| | style I/O |
++-----------------------------------+-----------------------------------+
+| u_offset | Offset for I/O |
++-----------------------------------+-----------------------------------+
+| u_buf | Pointer to the buffer to use for |
+| | block I/O |
++-----------------------------------+-----------------------------------+
+| u_sysio | True if the character I/O is to |
+| | system space (special case for |
+| | tty) |
++-----------------------------------+-----------------------------------+
+| u_mask | Umask of the process |
++-----------------------------------+-----------------------------------+
+| u_guid | Group id of the process |
++-----------------------------------+-----------------------------------+
+| u_euid | Effective uid of the process |
++-----------------------------------+-----------------------------------+
+| u_egid | Effective gid of the process |
++-----------------------------------+-----------------------------------+
+| u_name | Copy of p_name |
++-----------------------------------+-----------------------------------+
+| u_files | Array of indexes into the file |
+| | handle table for each file that |
+| | is open |
++-----------------------------------+-----------------------------------+
+| u_cloexec | Bit mask of files to close on |
+| | execv (may change to allow more |
+| | open files) |
++-----------------------------------+-----------------------------------+
+| u_cwd | Inode of the current working |
+| | directory of the process |
++-----------------------------------+-----------------------------------+
+| u_root | Inode of the current root |
+| | directory of the process |
++-----------------------------------+-----------------------------------+
+| u_rename | Inode to match during rename |
+| | processing |
++-----------------------------------+-----------------------------------+
+| u_ctty | Minor number of controlling |
+| | terminal |
++-----------------------------------+-----------------------------------+
+| u_block | Block number for disk I/O |
+| | terminal |
++-----------------------------------+-----------------------------------+
+| u_blkoff | Offset into block for disk I/O |
+| | terminal |
++-----------------------------------+-----------------------------------+
+| u_nblock | Number of blocks for disk I/O |
++-----------------------------------+-----------------------------------+
+| u_dptr | Pointer to the data buffer for an |
+| | I/O (can be kernel or user) |
++-----------------------------------+-----------------------------------+
+| u_done | I/O counter for driver methods |
++-----------------------------------+-----------------------------------+
+
+Level 2 systems also have
+
++-----------------------------------+-----------------------------------+
+| u_groups | Supplementary group identifers |
++-----------------------------------+-----------------------------------+
+| u_ngroup | Number of supplementary group |
+| | identifiers present |
++-----------------------------------+-----------------------------------+
+| u_flags | Additional flags |
++-----------------------------------+-----------------------------------+
+| u_rlimit | Resource limits |
++-----------------------------------+-----------------------------------+
--- /dev/null
+Terminal Interface
+==================
+
+Fuzix provides a subset of the standard POSIX termios terminal
+interface.
+
++-----------------------+-----------------------+-----------------------+
+| Speed setting | Y | Not all hardware |
+| | | supports this. |
+| | | Input/output speed |
+| | | must match |
++-----------------------+-----------------------+-----------------------+
+| VMIN | Y | Minimum characters to |
+| | | complete I/O |
++-----------------------+-----------------------+-----------------------+
+| VEOF | Y | Configurable EOF |
+| | | character |
++-----------------------+-----------------------+-----------------------+
+| VTIME | Y | Timeout on input |
++-----------------------+-----------------------+-----------------------+
+| VEOL | Partial | Configurable end of |
+| | | line character |
++-----------------------+-----------------------+-----------------------+
+| VERASE | Y | Configurable erase |
+| | | character |
++-----------------------+-----------------------+-----------------------+
+| VINTR | Y | Configurable |
+| | | interrupt character |
+| | | delivering SIGINT |
++-----------------------+-----------------------+-----------------------+
+| VKILL | Y | Configurable clear |
+| | | input character |
++-----------------------+-----------------------+-----------------------+
+| VQUIT | Y | Configurable |
+| | | interrupt character |
+| | | delivering SIGQUIT |
++-----------------------+-----------------------+-----------------------+
+| VSTART | Y | Configurable flow |
+| | | control characters |
++-----------------------+-----------------------+-----------------------+
+| VSTOP | Y | Configurable flow |
+| | | control characters |
++-----------------------+-----------------------+-----------------------+
+| VSUSP | N | No job control |
++-----------------------+-----------------------+-----------------------+
+| VDSUSP | N | No job control |
++-----------------------+-----------------------+-----------------------+
+| VLNEXT | N | |
++-----------------------+-----------------------+-----------------------+
+| VDISCARD | Y | Discard output |
++-----------------------+-----------------------+-----------------------+
+| BRKINT | N | No break support |
++-----------------------+-----------------------+-----------------------+
+| ICRNL | Y | Map carriage return |
+| | | to newline on input |
++-----------------------+-----------------------+-----------------------+
+| IGNBRK | N | No break support |
++-----------------------+-----------------------+-----------------------+
+| IGNCR | Y | Ignore carriage |
+| | | return on input |
++-----------------------+-----------------------+-----------------------+
+| INLCR | Y | Map newline to |
+| | | carriage return on |
+| | | input |
++-----------------------+-----------------------+-----------------------+
+| INPCK | N | No parity support |
++-----------------------+-----------------------+-----------------------+
+| ISTRIP | Y | Strip parity bit |
++-----------------------+-----------------------+-----------------------+
+| IUCLC | N | Remap upper/lower |
+| | | case |
++-----------------------+-----------------------+-----------------------+
+| IXANY | N | XON/XOFF flow control |
+| | | not supported |
++-----------------------+-----------------------+-----------------------+
+| IXOFF | N | XON/XOFF flow control |
+| | | not supported |
++-----------------------+-----------------------+-----------------------+
+| PARMRK | N | No parity support |
++-----------------------+-----------------------+-----------------------+
+| IXON | N | XON/OFF flow control |
+| | | not supported |
++-----------------------+-----------------------+-----------------------+
+| OPOST | Y | Output post |
+| | | processing |
++-----------------------+-----------------------+-----------------------+
+| OLCUC | N | Map upper/lower case |
++-----------------------+-----------------------+-----------------------+
+| ONLCR | Y | Map newline to |
+| | | carriage return on |
+| | | output |
++-----------------------+-----------------------+-----------------------+
+| OCRNL | Y | Map carriage return |
+| | | to newline on output |
++-----------------------+-----------------------+-----------------------+
+| ONLRET | N | |
++-----------------------+-----------------------+-----------------------+
+| OFILL | N | Delays not supported |
++-----------------------+-----------------------+-----------------------+
+| NLDLY | N | Delays not supported |
++-----------------------+-----------------------+-----------------------+
+| CRDLY | N | Delays not supported |
++-----------------------+-----------------------+-----------------------+
+| TABDLY | N | Delays not supported |
++-----------------------+-----------------------+-----------------------+
+| BSDLY | N | Delays not supported |
++-----------------------+-----------------------+-----------------------+
+| VTDLY | N | Delays not supported |
++-----------------------+-----------------------+-----------------------+
+| FFDLY | N | Delays not supported |
++-----------------------+-----------------------+-----------------------+
+| CSIZE | Y | Hardware dependent |
++-----------------------+-----------------------+-----------------------+
+| CSTOPB | Y | Hardware dependent |
++-----------------------+-----------------------+-----------------------+
+| CREAD | N | |
++-----------------------+-----------------------+-----------------------+
+| PARENB | Some | No general support, |
+| | | some hardware support |
++-----------------------+-----------------------+-----------------------+
+| PARODD | Some | No general support, |
+| | | some hardware |
+| | | supported |
++-----------------------+-----------------------+-----------------------+
+| HUPCL | Y | Needs extensive |
+| | | testing |
++-----------------------+-----------------------+-----------------------+
+| CLOCAL | Y | |
++-----------------------+-----------------------+-----------------------+
+| CRTSCTS | Y | No general support, |
+| | | some hardware support |
++-----------------------+-----------------------+-----------------------+
+| CBAUD | Y | Baud rate setting |
+| | | supported |
++-----------------------+-----------------------+-----------------------+
+| ECHO | Y | Echo characters as |
+| | | typed |
++-----------------------+-----------------------+-----------------------+
+| ECHOE | Y | Echo erase characters |
++-----------------------+-----------------------+-----------------------+
+| ECHOK | Y | Echo kill line |
++-----------------------+-----------------------+-----------------------+
+| ECHONL | N | |
++-----------------------+-----------------------+-----------------------+
+| ICANON | Y | Canonical model |
+| | | supported (but not |
+| | | always 256 bytes as |
+| | | specified by POSIX) |
++-----------------------+-----------------------+-----------------------+
+| IEXTEN | N | |
++-----------------------+-----------------------+-----------------------+
+| ISIG | Y | Signal delivery from |
+| | | keyboard events |
++-----------------------+-----------------------+-----------------------+
+| NOFLSH | N | |
++-----------------------+-----------------------+-----------------------+
+| TOSTOP | N | |
++-----------------------+-----------------------+-----------------------+
+| XCASE | N | |
++-----------------------+-----------------------+-----------------------+
+
+The following ioctls are supported
+
+TCGETS, TCSETS, TCSETSW, TCSETSF: Implement the posix termios
+tcgetattr/tcsetattr interfaces at kernel level.
+
+TIOCINQ: read the number of pending characters of input
+
+TIOCFLUSH: implements the POSIX tcflush() interfaces
+
+TIOCHANGUP: implements the user level vhangup() interface
+
+TIOCOSTOP, TIOCOSTART: implement the POSIX tcflow interface.
+
+Kernel Interface
+----------------
+
+**int tty_open(uint_fast8_t minor, uint16_t flag)**
+
+This method handles the opening of a tty device. On success it will call
+into tty_setup as provided by the platform and then wait for the carrier
+if appropriate. tty_setup can be used to handle things like power
+management of level shifters.
+
+**int tty_read(uint_fast8_t minor, uint_fast8_t rawflag, uint_fast8_t flag)**
+
+This method implements the normal read behaviour for a terminal device
+and is generally called directly as the device driver method. It will
+call into the platform code in order to implement the low level
+behaviour.
+
+**int tty_write(uint_fast8_t minor, uint_fast8_t rawflag, uint_fast8_t flag)**
+
+This method implements the normal write behaviour for a terminal device
+and is generally called directly as the device driver method. It will
+call into the platform code in order to implement the low level
+behaviour.
+
+**int tty_ioctl(uint_fast8_t minor, uarg_t request, char \*data)**
+
+Implements the standard tty and line discipline ioctls. This can be
+wrapped by platform specific code to provide additional ioctl
+interfaces, or by other higher layers (see Virtual Terminal) for the
+same purpose.
+
+**tty_close(uint_fast8_t minor)**
+
+Called on the last close of the open tty file handle. This can be
+wrapped by drivers that need to reverse some action taken in tty_setup.
+
+Driver Helper Functions
+-----------------------
+
+**int tty_inproc(uint_fast8_t minor, unsigned char c)**
+
+Queue a character to the tty interface indicated. This method is
+interrupt safe. This may call back into the platform tty output code in
+order to implement echoing of characters.
+
+**void tty_outproc(uint_fast8_t minor)**
+
+When implementing asynchronous output indicates that more data may be
+queued to the hardware interface. May be called from an interrupt
+handler. Any output restarted will restart fom a non interrupt context
+after the IRQ completes.
+
+**tty_putc_wait(uint_fast8_t minor, unsigned char c)**
+
+Write a character to the output device, waiting if necessary. Not
+interrupt safe.
+
+**tty_carrier_drop(uint_fast8_t minor)**
+
+Indicate that the carrier line on this port has been dropped. Can be
+called from an interrupt.
+
+**tty_carrier_raise(uint_fast8_t minor)**
+
+Indicate that the carrier line on this port has been raised. Can be
+called from an interrupt.
+
+Defines Provided By The Platform
+------------------------------------
+
+**NUM_DEV_TTY:** The number of actual tty device ports (one based not zero based)
+
+**TTYDEV:** The device used for the initial init process and for boot prompts
+
+Structures Provided By The Platform
+-----------------------------------
+
+**unsigned char [TTYSIZ]**
+
+One buffer per tty instance.
+
+**struct s_queue[NUM_DEV_TTY+1]**
+
+One queue per tty plus queue 0 which is not used. The structure is set
+up as
+
+{ buffer, buffer, buffer, TTYSIZE, 0, TTYSIZE / 2 }
+
+Methods Provided By The Platform
+------------------------------------
+
+**void tty_putc(uint_fast8_t minor, unsigned char c)**
+
+Write a character to the tty device. Non-blocking. If the device is busy
+drop the byte. When handling echo on a particularly primitive port it
+may be advantageous to implement a one byte buffer in the driver code.
+
+**int tty_writeready(uint_fast8_t minor)**
+
+Report whether the device can accept a byte of data. This should return
+either TTY_READY_NOW (you may write), TTY_READY_SOON (polling may be
+used) or TTY_READY_LATER (there is no point polling). The use of
+TTY_READY_SOON allows slow platforms to avoid the continuous overhead of
+terminal interrupts, or deferring writes until the next timer tick. The
+kernel will poll until the process would naturally be pre-empted. On
+fast devices it may be worth always returning TTY_READY_LATER. When the
+port is blocked due to a long standing condition such as flow control
+TTY_READY_LATER should be returned.
+
+**void tty_sleeping(uint_fast8_t minor)**
+
+This method is called just before the kernel exits polling of a tty
+port. This allows the driver to selectively enable transmit complete
+interrupts in order to reduce CPU loading. For other platforms this may
+be a null function.
+
+**int tty_carrier(uint_fast8_t minor)**
+
+Report the carrier status of the port. If the port has no carrier
+control then simply return 1 (carrier present).
+
+void tty_setup(uint_fast8_t minor)
+
+Perform any hardware set up necessary to open this port. If none is
+required then this can be a blank function.
+
+**void kputchar(char c)**
+
+Writes a character from the kernel to a suitable console or debug port.
+This is usually implemented in terms of tty_putc. As it may be called
+from an interrupt it cannot use tty_putc_wait(). On platforms with queued
+interrupt driven output this routine should ideally not return until the
+character is visible to the user.
+
+Implementation Models
+---------------------
+
+Generally speaking the terminal interfaces found on 8bit systems split
+into three categories beside built in display and keyboard: bit banged
+ports, polled serial ports and interrupt driven serial ports. Bit banged
+ports pose a particularly difficult set of problems with a multitasking
+operating system.
+
+If the platform has polled serial ports then the port should be polled
+for input and carrier changes on the timer tick. To get the best
+responsiveness it is strongly recommended that the port is also polled
+from platform_idle(). As the timer tick can occur during platform_idle()
+care must be taken to lock out any re-entrancy of the polling logic. Any
+FIFOs should be emptied in the poll so that the chance of overruns
+before the next read is minimised.
+
+Interrupt driven ports can queue characters directly from the events as
+they occur. This provides a much better experience. Transmit complete
+interrupts can also be used but are much less effective on low speed
+devices as the time taken to complete interrupt handling, wake and begin
+queueing a further byte will exceed the time taken to actually send a
+byte of output. Whether they are beneficial depends upon the platform. The
+kernel tty layer is deliberately designed to be unaware of whatever low
+level interrupt driven queued I/O or polled I/O is happening.
+
+Bit-bang ports are problematic. Transmit is relatively easy as the
+tty_putc() method can disable interrupts if not already off and simply
+bash out the data. There is a performance impact but this is otherwise
+fairly reliable. Receive is very difficult to arrange as the system will
+be carrying out other tasks. At best it could be polled when the machine
+is idle.
+
+A small number of bitbang interfaces either generate interrupts on
+edges, or timestamp them. These are ultimately much the same as a normal
+interrupt driven port minus the small matter of coding and the need for
+a very fast specialised interrupt handler for the bit banging. This
+probably needs to occur in assembler without calling the standard
+interrupt entry paths.
+
+Bugs And Caveats
+----------------
+
+The tty layer is one of the few parts of the kernel that makes
+active use of interrupts. Driver code therefore needs to be careful that
+the interrupt handling is race free when testing conditions changed by
+the interrupt handlers.
+
+Parity can be handled in hardware but parity checking and generation in
+software are not currently supported, even though they would be very
+cheap to do on Z80 at least.
+
+Carrier handling is very new and not well tested.
+
--- /dev/null
+Virtual Terminal
+================
+
+The vt interface layer provides a generalized VT52 like console for
+systems with a built in display. It is not used when only serial ports
+are present.
+
+Virtual Terminal Codes
+----------------------
+
++-----------------------------------+-----------------------------------+
+| Ctrl-G | Sounds the beeper if a beep |
+| | method is provided |
++-----------------------------------+-----------------------------------+
+| Ctrl-H | Moves the cursor back one |
+| | character |
++-----------------------------------+-----------------------------------+
+| Ctrl-I | Moves forward to the next tab |
+| | stop (8 character fixed stops) |
++-----------------------------------+-----------------------------------+
+| Ctrl-J | Move the cursor down a line, |
+| | scroll the screen if at the |
+| | bottom |
++-----------------------------------+-----------------------------------+
+| Ctrl-M | Move the cursor back to column |
+| | zero on the current line |
++-----------------------------------+-----------------------------------+
+| Escape | Introduce an escape sequence |
++-----------------------------------+-----------------------------------+
+| Escape-A | Move the cursor up a line if not |
+| | on the top line |
++-----------------------------------+-----------------------------------+
+| Escape-B | Move the cursor down a line if |
+| | not on the bottom line |
++-----------------------------------+-----------------------------------+
+| Escape-C | Move the cursor right a character |
+| | if not on the right hand edge |
++-----------------------------------+-----------------------------------+
+| Escape-D | Move the cursor left a character |
+| | if not on the left hand edge |
++-----------------------------------+-----------------------------------+
+| Escape-E | Clear the screen, the cursor |
+| | position is unchanged |
++-----------------------------------+-----------------------------------+
+| Escape-H | Move the cursor to the top left |
++-----------------------------------+-----------------------------------+
+| Escape-I | Move the cursor up, if already at |
+| | the top then reverse scroll the |
+| | screen |
++-----------------------------------+-----------------------------------+
+| Escape-J | Clears from the cursor position |
+| | to the end of screen, the cursor |
+| | position is unchanged |
++-----------------------------------+-----------------------------------+
+| Escape-K | Clears from the cursor position |
+| | to the end of line, the cursor |
+| | position is unchanged |
++-----------------------------------+-----------------------------------+
+| Escape-Y | Introduce a movement sequence. |
+| | The next two bytes are |
+| | interpreted as the X and Y |
+| | position where space (32) is 0. |
+| | An attempt to move off screen on |
+| | one axis causes that axis to |
+| | remain unchanged, but does not |
+| | stop the movement occuring in the |
+| | other axis |
++-----------------------------------+-----------------------------------+
+| Escape-a c | Set the attributes if supported |
++-----------------------------------+-----------------------------------+
+| Escape-b c | Set the ink (foreground) colour |
+| | that is used in rendering the |
+| | text mode display |
++-----------------------------------+-----------------------------------+
+| Escape-c c | Set the paper (background) colour |
+| | that is used in rendering the |
+| | text mode display |
++-----------------------------------+-----------------------------------+
+
+The text mode colour codes are defined as a best match to IRGB colours
+(intense, red, green, blue) with the IRGB forming the lower 4bits of the
+code.
+
+The other bits are used as follows
+
+4: reserved (must be zero if bit 5 is zero)
+
+5: platform specific colour not standard IRGB (colour is then bits 4-0)
+
+6: always 1 to keep the code in the ASCII range
+
+7: always 0 to keep the code in the ASCII range
+
+There is currently no facility to set border colours.
+
+
+Virtual Terminal Ioctls
+-----------------------
+
++-----------------------------------+-----------------------------------+
+| KBMAPSIZE | Reports the keyboard map size. |
+| | The number of rows is in the high |
+| | byte of the return. The number of |
+| | columns in the low byte. Not all |
+| | keyboards are row based so this |
+| | ioctl is not always supported. |
++-----------------------------------+-----------------------------------+
+| KBMAPGET | Returns the current keymap with |
+| | set bits indicating the keys |
+| | currently down, within the limits |
+| | of the hardware. KBMAPSIZE |
+| | determines the size of the map as |
+| | rows are packed into 16bit words |
++-----------------------------------+-----------------------------------+
+| KBSETTRANS | Set the translation table for |
+| | this keyboard. The translation |
+| | tables are machine specific and |
+| | the ioctl data must be in the |
+| | expected format for the system. |
+| | Only root may use this interface |
++-----------------------------------+-----------------------------------+
+| VTSIZE | Reports the height of the |
+| | terminal (in characters) in the |
+| | upper byte and the width in the |
+| | lower byte. |
++-----------------------------------+-----------------------------------+
+
+Kernel Programming Interface
+----------------------------
+
+Most of the VT features are configured in the platform config.h
+
++-----------------------------------+-----------------------------------+
+| CONFIG_VT | Builds the VT layer into the |
+| | kernel |
++-----------------------------------+-----------------------------------+
+| CONFIG_VT_SIMPLE | Builds the supporting code for a |
+| | simple character based memory |
+| | mapped display |
++-----------------------------------+-----------------------------------+
+| CONFIG_UNIKEY | Include support for a few unicode |
+| | symbols on input |
++-----------------------------------+-----------------------------------+
+| VT_WIDTH | Width of the display in |
+| | characters |
++-----------------------------------+-----------------------------------+
+| VT_HEIGHT | Height of the display in |
+| | characters |
++-----------------------------------+-----------------------------------+
+| VT_RIGHT | Usually VT_WIDTH – 1 unless the |
+| | display has a wider stride |
++-----------------------------------+-----------------------------------+
+| VT_BOTTOM | VT_HEIGHT – 1 |
++-----------------------------------+-----------------------------------+
+| VT_BASE | Used with CONFIG_VT_SIMPLE, gives |
+| | the memory address that forms the |
+| | start of the display |
++-----------------------------------+-----------------------------------+
+| VT_MAP_CHAR(x) | Used with CONFIG_VT_SIMPLE to |
+| | remap from ASCII to the platform |
+| | native symbols |
++-----------------------------------+-----------------------------------+
+| VT_INITIAL_LINE | Optional (defaults to zero), |
+| | allows the display to start at |
+| | boot further down the screen. |
+| | This can be useful to preserve |
+| | boot loader messages. |
++-----------------------------------+-----------------------------------+
+
+The core vt services are designed to be used from a tty driver and to
+stack on top of the existing tty interface. The vt layer provides the
+following methods
+
+**void vtoutput(unsigned char \*p, unsigned int len)**
+
+Output one or more characters to the VT52 screen while performing
+terminal emulation
+
+**int vt_ioctl(uint_fast8_t minor, uarg_t request, char \*data)**
+
+Replaces tty_ioctl and implements the vt layer interfaces before calling
+on into tty_ioctl
+
+**void vt_inproc(uint_fast8_t minor, unsigned char c)**
+
+Wraps tty_inproc for vt devices and should be used instead of tty_inproc
+
+**void vtinit(void)**
+
+Initializes the VT interface, should be called before **fuzix_main()** is
+entered, so usually from init_hardware.
+
+.. _methods-provided-by-the-platform-1:
+
+Methods Provided By The Platform
+--------------------------------
+
+When not using CONFIG_VT_SIMPLE the platform must provide a set of
+methods to manipulate the display memory.
+
+The methods required are
+
+**void do_beep(void)**
+
+Make a beep noise, or perform a visual bell (eg inverting the display
+momentarily if the hardware supports it).
+
+**void cursor_disable(void)**
+
+Disable the cursor even if it is a hardware cursor. This is used to indicate
+that the user has specifically disabled the cursor, rather than indicating a
+request to hide the cursor for a display update.
+
+**void cursor_off(void)**
+
+Hide the cursor, whether in hardware or software. If necessary restore any
+characters or attributes changed by cursor_on(). This routine can be a no-op
+if there is a hardware cursor and updating the display does not affect it.
+
+**void cursor_on(int8_t x, int8_t y)**
+
+Turn the cursor back on at x,y. Ensure that any data that is needed to
+restore the display is saved so that cursor_off() can use it.
+
+The following methods will only be invoked between a cursor_off() and a
+cursor_on()
+
+**void clear_across(int8_t y, int8_t x, int16_t num)**
+
+Clear num characters across from y,x. The request will never span more than
+the one line. The normal case is from x to the right hand side of the
+display. A request to clear zero characters should be handled.
+
+**void clear_lines(int8_t y, int8_t num)**
+
+Clear num lines starting at line y. They are cleared for the full width for
+the display. A request to clear zero lines should be handled.
+
+**void scroll_up(void)**
+
+Scroll the screen up (normal scroll). The bottom line does not need to
+be cleared. Hardware scrolling can be used if present.
+
+**void scroll_down(void)**
+
+Scroll the screen down (reverse scroll). The top line does not need to
+be cleared. Hardware scrolling can be used if present.
+
+**void plot_char(int8_t y, int8_t x, uint16_t c)**
+
+Plot a character onto the display at y,x. Currently c is in the range 0-255
+but that may change in future to accomodate non-ascii displays and systems with
+additional graphic ranges.
+
+Fonts
+-----
+
+Bitmap displays usually require a font in the kernel. There are several
+provided fonts that can be compiled into the kernel using config.h
+defines
+
+**CONFIG_FONT_8X8:** A classic 8x8 pixel font for 256 symbols.
+
+**CONFIG_FONT_8X8SMALL:** A 96 symbol version of the 8x8 font for
+tight spaces. Note that this font is character 32 based not character 0
+based.
+
+**CONFIG_FONT_6X8:** A 6x8 pixel font with the bits packed to the right.
+Used to get 40 characters on a 256 pixel wide display.
+
+**CONFIG_FONT_4X6:** A 4x6 pixel font for awkward displays. Each symbol
+is replicated in the high and low nybbles of the data stream in order to
+optimize rendering.
+
+**CONFIG_FONT_4X8** A 4x8 pixel font for narrow displays. Each symbol
+is replicated in the high and low nybbles of the data stream in order to
+optimize rendering.
+
+**CONFIG_FONT_8X8_EXP2** A 16bit wide font where each character has been
+expanded to two adjacent bits. Used for rendering onto 4 colour packed
+bitmap displays such as the Sam Coupe.
+
+All the fonts are linked into the FONT section of the kernel image. This
+is done because on some platforms the rendering code is in common space
+and it is desirable to arrange that the FONT is mapped in a location
+that is accessible when the display is mapped, but not necessarily
+wasting COMMON space. On certain platforms the FONT area may also be
+discardable if the font is loaded into hardware at boot time.
+
+Keyboard
+--------
+
+The second half of the VT driver is the keyboard interface. This is
+mostly platform specific code. The kernel tries to abstract the
+interface to this so that keydown and keyup data is provided in a
+standardized bitmap of 16bit words, with each row mapped to a number of
+words.
+
+To aid standardization a set of standard keyboard codes are defined.
+Those outside of the ASCII set will be translated by the kernel into
+unicode providing **CONFIG_UNIKEY** is defined. The codes given below
+also have their top bit set except for control key codes and delete
+
++-----------------------+-----------------------+-----------------------+
+| 0x7F | KEY_DEL | Delete. Prefer |
+| | | backspace for normal |
+| | | delete |
++-----------------------+-----------------------+-----------------------+
+| Ctrl-H | KEY_BS | Backspace (delete |
+| | | left) |
++-----------------------+-----------------------+-----------------------+
+| Ctrl-[ | KEY_ESC | Escape key |
++-----------------------+-----------------------+-----------------------+
+| Ctrl-I | KEY_TAB | Tab key |
++-----------------------+-----------------------+-----------------------+
+| Ctrl-J | KEY_ENTER | The enter key on a |
+| | | keyboard, or other |
+| | | key serving this |
+| | | purpose |
++-----------------------+-----------------------+-----------------------+
+| Ctrl-L | KEY_CLEAR | Clear button on a |
+| | | keyboard |
++-----------------------+-----------------------+-----------------------+
+| D | KEY_LEFT | Left arrow key (not |
+| | | backspace) |
++-----------------------+-----------------------+-----------------------+
+| C | KEY_RIGHT | Right arrow key (not |
+| | | delete right) |
++-----------------------+-----------------------+-----------------------+
+| A | KEY_UP | Up arrow key |
++-----------------------+-----------------------+-----------------------+
+| B | KEY_DOWN | Down arrow key (not |
+| | | newline/carriage |
+| | | return) |
++-----------------------+-----------------------+-----------------------+
+| H | KEY_HOME | Home button |
++-----------------------+-----------------------+-----------------------+
+| h | KEY_HELP | Help button |
++-----------------------+-----------------------+-----------------------+
+| I | KEY_INSERT | Insert button |
++-----------------------+-----------------------+-----------------------+
+| c | KEY_COPY | Copy button |
++-----------------------+-----------------------+-----------------------+
+| v | KEY_PASTE | Paste button |
++-----------------------+-----------------------+-----------------------+
+| x | KEY_CUT | Cut button |
++-----------------------+-----------------------+-----------------------+
+| a | KEY_CANCEL | Cancel button or |
+| | | similar |
++-----------------------+-----------------------+-----------------------+
+| e | KEY_EXTRA | Extra button |
++-----------------------+-----------------------+-----------------------+
+| ] | KEY_PRINT | Print button |
++-----------------------+-----------------------+-----------------------+
+| Ctrl-C | KEY_STOP | Stop/Halt/Interrupt |
+| | | button (not the |
+| | | normal ^C key map) |
++-----------------------+-----------------------+-----------------------+
+| r | KEY_DELR | Delete right |
++-----------------------+-----------------------+-----------------------+
+| + | KEY_PLUS | Plus button (not |
+| | | normal '+') |
++-----------------------+-----------------------+-----------------------+
+| - | KEY_MINUS | Minus button (not |
+| | | normal '-') |
++-----------------------+-----------------------+-----------------------+
+| q | KEY_EXIT | Exit/Quit button |
++-----------------------+-----------------------+-----------------------+
+| p | KEY_PAUSE | Pause button |
++-----------------------+-----------------------+-----------------------+
+| < | KEY_PGDOWN | Page up |
++-----------------------+-----------------------+-----------------------+
+| > | KEY_PGUP | Page down |
++-----------------------+-----------------------+-----------------------+
+| E | KEY_EDIT | Edit button |
++-----------------------+-----------------------+-----------------------+
+| N | KEY_END | End button (not stop |
+| | | but move to line end) |
++-----------------------+-----------------------+-----------------------+
+| U | KEY_UNDO | Undo button |
++-----------------------+-----------------------+-----------------------+
+| 1 | KEY_F1 | Function key 1 |
++-----------------------+-----------------------+-----------------------+
+| 2 | KEY_F2 | Function key 2 |
++-----------------------+-----------------------+-----------------------+
+| 3 | KEY_F3 | Function key 3 |
++-----------------------+-----------------------+-----------------------+
+| 4 | KEY_F4 | Function key 4 |
++-----------------------+-----------------------+-----------------------+
+| 5 | KEY_F5 | Function key 5 |
++-----------------------+-----------------------+-----------------------+
+| 6 | KEY_F6 | Function key 6 |
++-----------------------+-----------------------+-----------------------+
+| 7 | KEY_F7 | Function key 7 |
++-----------------------+-----------------------+-----------------------+
+| 8 | KEY_F8 | Function key 8 |
++-----------------------+-----------------------+-----------------------+
+| 9 | KEY_F9 | Function key 9 |
++-----------------------+-----------------------+-----------------------+
+| 0 | KEY_F10 | Function key 10 |
++-----------------------+-----------------------+-----------------------+
+| : | KEY_F11 | Function key 11 |
++-----------------------+-----------------------+-----------------------+
+| ; | KEY_F12 | Function key 12 |
++-----------------------+-----------------------+-----------------------+
+| 0x80 | KEY_POUND | Remapped to the |
+| | | unicode for a '£' |
+| | | sign |
++-----------------------+-----------------------+-----------------------+
+| 0x81 | KEY_HALF | Remapped to the |
+| | | unicode for a '½' |
+| | | sign |
++-----------------------+-----------------------+-----------------------+
+| 0x82 | KEY_EURO | Remapped to the |
+| | | unicode for a '€' |
+| | | sign |
++-----------------------+-----------------------+-----------------------+
+| 0x83 | KEY_DOT | Remapped to the |
+| | | unicode for a dot |
+| | | sign |
++-----------------------+-----------------------+-----------------------+
+| 0x84 | KEY_YEN | Remapped to the |
+| | | unicode for a '¥' |
+| | | sign |
++-----------------------+-----------------------+-----------------------+
+| 0x85 | KEY_COPYRIGHT | Remapped to the |
+| | | unicode for a '©' |
+| | | sign |
++-----------------------+-----------------------+-----------------------+
+
+Multiple Console Support
+------------------------
+
+Some platforms either have two or more monitors, or have enough video
+memory to support multiple switchable consoles. In order to keep the
+code size small for the default case the VT switching is handled as a
+special case. If CONFIG_VT_MULTI is defined then two helper methods are
+supplied
+
+**void vt_save(struct vt_switch \*vt)**
+
+Saves the VT layer state for the current active console
+
+**void vt_load(struct vt_switch \*vt)**
+
+Load back the VT layer state for the saved consoles
+
+If the console sizes are the same (for example when implementing virtual
+consoles) the usual defines can be maintained if not then VT_WIDTH and
+the related defines can be defined as array references.
+
+The implementation needs to track a current output tty and a current
+input tty. The tty_putc() method should vt_save the existing tty and
+switch to the new tty (based upon minor) and then load its state with
+vt_load() before calling vtoutput(). Currently this needs to be done
+with interrupts disabled. Fixing that limit is planned for the future.
+
+The output helpers provided by the platform can check curtty in order to
+decide where to render or which methods should be invoked.
+
+Input shifting is in the hands of the platform. It needs to invoke the
+inproc method for the current virtual console. How it decides which
+console to use is up to the kernel. On a system with a single keyboard
+and multiple console this could be done by reserving keys for switching.
+Current platforms use shift-F1 shift-F2 .. for console switching.
+
+For a worked example of multiple console support see the Memotech MTX
+platform.
+
--- /dev/null
+.. Fuzix documentation master file, created by
+ sphinx-quickstart on Mon Apr 8 21:16:10 2019.
+ You can adapt this file completely to your liking, but it should at least
+ contain the root `toctree` directive.
+
+Welcome to Fuzix's documentation!
+=================================
+
+.. toctree::
+ :maxdepth: 2
+ :caption: Contents:
+
+ Platforms
+ DiskFormats
+ build-filesystem-ng
+ MemoryManagement
+ ExternalBuffers
+ Process
+ Tickless
+ TTY
+ VT
+ 65C816
+ M68000
+ BankedZ80
+ Z80Thunked
+
+* :ref:`search`