%%%%%%%%%%%%%%%% Experimental chapter
%  bugs by rubini@ipvvis.unipv.it
%
% ==> check lateck marks
%

\def\parprobe#1{\smallskip\parbox[t]{4 in}{\small\noindent\baselineskip=2pt #1}\smallskip}


\def\parversion#1{\smallskip\parbox[c]{4 in}{\small\noindent\baselineskip=2pt #1}\smallskip}
\def\last_ker{1.0.9 -- 1.1.76}

\chapter{Tour of the \linux\ kernel source}\label{tour}

{\bf [This is an alpha release of a chapter written by Alessandro
Rubini, {\tt rubini@ipvvis.unipv.it}.  I'm including it here as it
gets worked on for comments.]}

This chapter tries to explain the \linux\ source code in an orderly
manner, trying to help the reader to achieve a good understanding of
how the source code is laid out and how the most relevant unix
features are implemented. The target is to help the experienced C
programmer who is not accustomed to \linux\ in getting familiar with
the overall \linux\ design. That's why the chosen entry point for the
kernel tour is the kernel own entry point: system boot.

A good understanding of C language is
required to understand this material, as well as some familiarity with
both \unix\ concepts and the PC architecture. However, no C code will 
appear in this chapter, but rather pointers to the actual code. The 
finest issues of kernel design are explained in other chapters of this guide,
while this chapter tends to remain an informal overview.

Any pathname for files referenced in this chapter is referred to the main
source-tree directory, usually {\tt /usr/src/linux}.

%The latest versions at the time of writing are 1.0.9 and 1.1.24.

\parversion{Most of the information reported here is taken from the
	source code of \linux\ release 1.0. Nonetheless, references to
	later versions are provided at times. Any paragraph within the
	tour shaped like this one is meant to underline changes the
	kernel has undergone after the 1.0 release. If no such paragraph is
	present, then no changes occurred up to release \last_ker.}

\parprobe{Sometimes a paragraph like this occurs in the text. It is
	a pointer to the right sources to get more information on
	the subject just covered. Needless to say, {\it the source} is
	the primary source.}


% whatabout an overview?

\section{Booting the system} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

When the PC is powered up, the 80x86 processor finds itself in real
mode and executes the code at address 0xFFFF0, which corresponds
to a ROM-BIOS address. The PC BIOS performs some tests on the system
and initializes the interrupt vector at physical address 0. After that
it loads the first sector of a bootable device to 0x7C00, and jumps to it.
The device is usually the floppy or the hard drive. The preceding
description is quite a simplified one, but it's all that's needed to
understand the kernel initial workings.

The very first part of the \linux\ kernel is written in 8086 assembly
language ({\tt boot/bootsect.S}). When run, it moves itself to
absolute address 0x90000, loads the next 2 kBytes of code from the
boot device to address 0x90200, and the rest of the kernel to address
0x10000. The message ``{\tt Loading...}'' is displayed during system
load. Control is then passed to the code in {\tt boot/Setup.S}, another real-mode
assembly source.

The setup portion identifies some features of the host system and the
type of
vga board. If requested to, it asks the user to choose the video mode for the
console. It then moves the whole system from address 0x10000 to address 0x1000,
enters protected mode and jumps to the rest of the system (at 0x1000).

The next step is kernel decompression. The code at 0x1000 comes from
{\tt zBoot/head.S} which initializes registers and invokes
{\tt decompress\_kernel()}, which in turn is made up of {\tt zBoot/inflate.c},
{\tt zBoot/unzip.c} and {\tt zBoot/misc.c}. The decompressed data goes to
address 0x100000 (1 Meg), and this is the main reason why \linux\ can't run
with less than 2 megs ram.

\parprobe{Encapsulation of the kernel in a gzip file is accomplished by
	{\tt Makefile} and utilities in the {\tt zBoot} directory. They are
	interesting files to look at.}

\parversion{Kernel release 1.1.75 moved the {\tt boot} and {\tt zBoot}
	directories down to {\tt arch/i386/boot}. This change is meant to allow
	true kernel builds for different architectures. Nonetheless, I'll
	stick to i386-specific information.}

Decompressed code is executed at address 0x1010000 {\bf [Maybe I've
lost track of physical addresses, here, as I don't know very well gas
source code]}, where all the 32-bit setup is accomplished: IDT, GDT
and LDT are loaded, the processor and coprocessor are identified, and
paging is setup; eventually, the routine {\tt start\_kernel} is
invoked. The source for the above operations is in {\tt boot/head.S}. It is
probably the trickiest code in the whole kernel.

Note that if an error occurs during any of the preceding steps, the
computer will lockup. The OS can't deal with errors when it isn't yet
fully operative.

{\tt start\_kernel()} resides in {\tt init/main.c}, and never
returns. Anything from now on is coded in C language, left aside
interrupt management and system call enter/leave (well, most of the
macros embed assembly code, too).


\section{Spinning the wheel} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

After dealing with all the tricky questions, {\tt start\_kernel()} 
initializes all the parts of the kernel, specifically:
\begin{itemize}
\item Sets the memory bounds and calls {\tt paging\_init()}.
\item Initializes the traps, IRQ channels and scheduling.
\item Parses the command line.
\item If requested to, allocates a profiling buffer.
\item Initializes all the device drivers and disk buffering,
	as well as other minor parts.
\item Calibrates the delay loop (computes the ``BogoMips'' number).
\item Checks if interrupt 16 works with the coprocessor.
\end{itemize}

Finally, the kernel is ready to {\tt move\_to\_user\_mode()}, in order to
fork the {\tt init} process, whose code is in the same source file.
Process number 0 then, the so-called idle task,
keeps running in an infinite idle loop.

The {\tt init} process tries to execute {\tt /etc/init}, or
{\tt /bin/init}, or {\tt /sbin/init}.

If none of them succeeds, code is provided to execute ``{\tt /bin/sh
/etc/rc}'' and fork a root shell on the first terminal.  This
code dates back to \linux\ 0.01, when the OS was made by the kernel
alone, and no {\tt login} process was available.

\medskip
After {\tt exec()}ing the {\tt init} program from one of the standard places
(let's assume we have one of them), the kernel has no direct control
on the program flow. Its role, from now on is to provide processes with system
calls, as well as servicing asynchronous events (such as hardware interrupts).
Multitasking has been setup,
and it is now {\tt init} who manages multiuser access by {\tt fork()}ing
system daemons and {\tt login} processes.

Being the kernel in charge of providing services, the tour will proceed
by looking at those services (the ``system calls''), as well as by
providing general ideas about the underlying data structures and code
organization.

\section{How the kernel sees a process} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

>From the kernel point of view, a process is an entry in the process
table. Nothing more.

The process table, then, is one of the most important data structures within
the system, together with the memory-management tables and the buffer cache.
The individual item in the process table is the {\tt task\_struct} structure,
quite a huge one, defined in {\tt include/linux/sched.h}. Within the 
{\tt task\_struct} both low-level and high-level information is kept---
ranging from the copy of some hardware registers to the inode of the
working directory for the process.

The process table is both an array and a double-linked list, as well as a tree.
The physical implementation is a static array of pointers, whose length is
{\tt NR\_TASKS}, a constant defined in {\tt include/linux/tasks.h}, and each
structure resides in a reserved memory page. The list structure is achieved
through the pointers {\tt next\_task} and {\tt prev\_task}, while the tree
structure is quite complex and will not be described here. You may
wish to change {\tt NR\_TASKS} from the default vaue of 128, but be sure to
have proper dependency files to force recompilation of all the source files
involved.

After booting is over, the kernel is always
working on behalf of one of the processes, and the global variable
{\tt current}, a pointer to a {\tt task\_struct} item, is used to record
the running one. {\tt current} is only changed by the scheduler, in
{\tt kernel/sched.c}. When, however, all procecces must be looked at,
the macro {\tt for\_each\_task} is used. 
It is conderably faster than a sequential scan of the array,
when the system is lightly loaded.

A process is always running in either ``user mode'' or ``kernel mode''.
The main body
of a user program is executed in user mode and system calls are
executed in kernel mode. The stack used by the process in the two
execution modes is different---a conventional stack segment is used
for user mode, while a fixed-size stack (one page, owned by the
process) is used in kernel mode.  The kernel stack page is never
swapped out, because it must be available whenever a system call is entered.

System calls, within the kernel, exist as C language functions, their
`official' name being prefixed by `{\tt sys\_}'. A system call named, for
example, {\it burnout} invokes the kernel function {\tt sys\_\it
burnout\/\tt ()}.

\parprobe{The system call mechanism is described in
	chapter 3 of this guide. Looking at {\tt for\_each\_task} and
	{\tt SET\_LINKS}, in {\tt include/linux/sched.h} can help understanding
	the list and tree structures in the process table.}


\section{Creating and destroying processes} %%%%%%%%%%%%%%%%%%%%%%%%%%

A unix system creates a process though the {\tt fork()} system call, and
process termination is performed either by {\tt exit()} or by receiving
a signal. The \linux\ implementation for them resides in
{\tt kernel/fork.c} and {\tt kernel/exit.c}.

Forking is easy, and {\tt fork.c} is short and ready understandable. Its
main task is filling the data structure for the new process. Relevant
steps, apart from filling fields, are
\begin{itemize}
\item getting a free page to hold the {\tt task\_struct}
\item finding an empty process slot ({\tt find\_empty\_process()})
\item getting another free page for the {\tt kernel\_stack\_page}
\item copying the father's LDT to the child
\item duplicating {\tt mmap} information of the father
\end{itemize}
\noindent{\tt sys\_fork()} also manages file descriptors and inodes.

\parversion{The 1.0 kernel offers some vestigial support to threading,
	and the {\tt fork()} system call shows some hints to
	that. Kernel threads is work-in-progress outside the mainstream
	kernel.}

\smallskip
Exiting from a process is trickier, because the parent process
must be notified about any child who exits. Moreover, a process can exit
by being {\tt kill()}ed by another process (these are \unix\ features).
The file {\tt exit.c} is therefore the home of {\tt sys\_kill()} and the
vairious flavours of {\tt sys\_wait()}, in addition to {\tt sys\_exit()}.

The code belonging to {\tt exit.c} is not described here---it is not that
interesting. It deals with a lot of details in order to
leave the system in a consistent state. The POSIX standard,
then, is quite demanding about signals, and it must be dealt with.

\section{Executing programs} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

After {\tt fork()}ing, two copies of the same program are running. One
of them usually {\tt exec()}s another program. The {\tt exec()} system
call must locate the binary image of the executable file, load and run
it. The word `load' doesn't necessarily mean ``copy in memory the binary
image'', as \linux\ supports demand loading.

The \linux\ implementation of {\tt exec()} supports different binary formats.
This is accomplished through the {\tt linux\_binfmt} structure, which embeds
two pointers to functions---one to load the executable and the other to
load the library, each binary format representing both the executable
and the library. Loading of shared libraries is implemented in the
same source file as {\tt exec()} is, but let's stick to {\tt exec()} itself.

The \unix\ systems provide the programmer with six flavours of the
{\tt exec()} function. All but one of them can be implemented as
library functions, and the\linux\  kernel implements {\tt sys\_execve()}
alone. It performs quite a simple task: loading the head of the executable,
and trying to execute it. If the first two bytes are ``{\tt \#!}'', then
the first line is parsed and an interpreter is invoked, otherwise
the registered binary formats are sequentially tried.

The native \linux\ format is supported directly within {\tt fs/exec.c},
and the relevant functions are {\tt load\_aout\_binary} and
{\tt load\_aout\_library}.  As for the binaries, the function loading
an {\it a.out\/} executable ends up either in {\tt mmap()}ing the
disk file, or in calling {\tt read\_exec()}.  The former way uses the \linux\ demand
loading mechanism to fault-in program pages when they're accessed,
while the latter way is used when memory mapping is not supported by
the host filesystem (for example the ``msdos'' filesystem).

\parversion{Late 1.1 kernels embed a revised msdos filesystem, which
	supports {\tt mmap()}. Moreover, the {\tt struct linux\_binfmt} is
	a linked list rather than an array, to allow loading a new binary
	format as a kernel module. Finally, the structure itself has been
	extended to access format-related core-dump routines.}

\section{Accessing filesystems} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

It is well known that the filesystem is the most basic resource in a
\unix\ system, so basic and ubiquitous that it needs a more handy name ---
I'll stick to the standard practice of calling it simply ``fs''.

I'll assume the reader already knows the basic \unix\ fs ideas ---
access permissions, inodes, the superblock, {\tt mount\/}ing and
{\tt umount\/}ing. Those concepts are well explained
by smarter authors than me within the standard \unix\ literature, so I
won't duplicate their efforts and I'll stick to \linux\ specific issues.

% Fs code takes from 20 to 25\% of the kernel source tree.
% Actually, a \unix\ OS can't live without a filesystem,
% because any hardware access occurrs through a device driver, which in turn
% is identified by a filename within the filesystem. 

While the first Unices used to support a single fs type, 
whose structure was widespread in the whole kernel, today's practice
is to use a standardized interface between the kernel and the fs, in order
to ease data interchange across architectures. \linux\ itself provides
a standardized layer to pass information between the kernel and each fs
module. This interface layer is called VFS, for ``virtual filesystem''.

Filesystem code is therefore split into two layers: the upper layer is
concerned with the management of kernel tables and data structures,
while the lower layer is made up of the set of fs-dependent functions,
and is invoked through the VFS data structures.

All the fs-independent material resides in the {\tt fs/*.c} files.
They address the following issues:
\begin{itemize}
\item Managing the buffer chache ({\tt buffer.c});
\item Responding to the {\tt fcntl()} and {\tt ioctl()} system calls
	({\tt fcntl.c} and {\tt ioctl.c});
\item Mapping pipes and fifos on inodes and buffers
	({\tt fifo.c}, {\tt pipe.c});
\item Managing file- and inode-tables ({\tt file\_table.c}, {\tt inode.c});
\item Locking and unlocking files and records ({\tt locks.c});
\item Mapping names to inodes ({\tt namei.c}, {\tt open.c});
\item Implementing the tricky {\tt select()} function ({\tt select.c});
\item Providing information ({\tt stat.c});
\item {\tt mount\/}ing and {\tt umount\/}ing filesystems ({\tt super.c});
\item {\tt exec()}ing executables and dumping cores ({\tt exec.c});
\item Loading the various binary formats ({\tt bin\_fmt*.c},
	as outlined above).
\end{itemize}

The VFS interface, then, consists of a set of relatively high-level
operations which are invoked from the fs-independent code and are
actually performed by each filesystem type. The most relevant structures are
{\tt inode\_operations} and {\tt file\_operations}, though they're not alone: other
structures exist as well.
All of them are defined within {\tt include/linux/fs.h}.

The kernel entry point to the actual file system is
the structure {\tt file\_system\_type}. An array of {\tt file\_system\_type}s is
embodied within {\tt fs/filesystems.c} and it is referenced whenever a
{\tt mount} is issued. The function {\tt read\_super} for the relevant fs type
is then in charge of filling a {\tt struct super\_block} item, which in turn
embeds a {\tt struct super\_operations} and a {\tt struct {\it type\/}\_sb\_info}.
The former provides pointers to generic fs operations for the
current fs-type, the latter embeds specific information for the fs-type.

\parversion{The array of filesystem types has been turned in a linked list,
	to allow loading new fs types as kernel modules. The function
	({\tt un}-){\tt register\_filesystem} is coded within {\tt fs/super.c}.}

\section{Quick Anatomy of a Filesystem Type}

The role of a filesystem type is to perform the low-level tasks used
to map the relatively high level VFS operations on the physical media
(disks, network or whatever). The VFS interface is flexible enough to allow
support for both conventional \unix\ filesystems and exotic situations
such as the {\tt msdos} and {\tt umsdos} types.

Each fs-type is made up of the following items, in
addition to its own directory:
\begin{itemize}
\item An entry in the {\tt file\_systems[]} array ({\tt fs/filesystems.c});
\item The superblock include file
	({\tt include/linux/{\it type\/}\_fs\_sb.h});
\item The inode include file ({\tt include/linux/{\it type\/}\_fs\_i.h});
\item The generic own include file
	({\tt include/linux/{\it type\/}\_fs.h});
\item Two {\tt \#include} lines within {\tt include/linux/fs.h}, as well
	as the entries in {\tt struct su\-per\_block} and {\tt struct inode}.
\end{itemize}

The own directory for the fs type contains all the real code, responsible of
inode and data management.

\parprobe{The chapter about {\tt procfs} in this guide uncovers all the details
	about low-level code and VFS interface for that fs
	type. Source code in {\tt fs/procfs} is quite understandable
	after reading the chapter.}

We'll now look at the internal workings of the VFS mechanism, and
the {\tt minix} filesystem source is used as a working example. I chose
the {\tt minix} type because it is small but complete; moreover, any other
fs type in \linux\ derives from the {\tt minix} one. The {\tt ext2}
type, the de-facto standard in recent \linux\ installations, is much more
complex than that and its exploration is left as an exercise for the smart
reader.

When a minix-fs is mounted, {\tt minix\_read\_super} fills the {\tt super\_block}
structure with data read from the mounted device. The {\tt s\_op} field
of the structure will then hold a pointer to {\tt minix\_sops}, which is used
by the generic filesystem code to dispatch superblock operations. 

Chaining the newly mounted fs in the global system tree relies on the
following data items (assuming {\tt sb} is the {\tt super\_block} structure
and {\tt dir\_i} points to the inode for the mount point):

\begin{itemize}
\item {\tt sb->s\_mounted} points to the root-dir inode
	of the mounted filesystem ({\tt MINIX\_ROOT\_INO});
\item {\tt dir\_i->i\_mount} holds {\tt sb->s\_mounted};
\item {\tt sb->s\_covered} holds {\tt dir\_i}
\end{itemize}

Umounting will eventually be performed by {\tt do\_umount}, which in turn
invokes {\tt minix\_put\_super}. 

Whenever a file is accessed, {\tt minix\_read\_inode} comes into play; it
fills the system-wide {\tt inode} structure with fields coming form
{\tt minix\_inode}. The {\tt inode->i\_op} field is filled according to
{\tt inode->i\_mode} and it is responsible for any further operation on
the file. The source for the minix functions just described are to be found in
{\tt fs/minix/inode.c}.

The {\tt inode\_operations} structure is used to dispatch inode operations
(you guessed it) to the fs-type specific kernel functions; the first
entry in the structure is a pointer to a {\tt file\_operations} item, which is
the data-management equivalent of {\tt i\_op}. The minix fs-type allows
three instances of inode-operation sets (for direcotries, for files and
for symbolic links) and two instances of file-operation sets (symlinks
don't need one).

Directory operations ({\tt minix\_readdir} alone) are to be found in
{\tt fs/minix/dir.c}; file operations (read and write) appear within
{\tt fs/minix/file.c} and symlink operations (reading and following the link) in
{\tt fs/minix/symlink.c}.

The rest of the minix directory implements the following tasks:

\begin{itemize}
\item {\tt bitmap.c} manages allocation and freeing of inodes and blocks
	(the {\tt ext2} fs, otherwise, has two different source files);
\item {\tt fsynk.c} is responsible for the {\tt fsync()} system calls ---
	it manages direct, indirect and double indirect blocks (I assume
	you know about them, it's common \unix\ knowledge);
\item {\tt namei.c} embeds all the name-related inode operations,
	such as creating and destroying nodes, renaming and linking;
\item {\tt truncate.c} performs truncation of files.
\end{itemize}

%\section{The {\tt ext2} and {\tt msdos} filesystems} %%%%%%%%%%%%%%%
%\section{Pipes} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%\section{The buffer cache} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\section{The console driver} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

Being the main I/O device on most \linux\ boxes, the console driver deserves
some attention. The source code related to the console, as well as the other
character drivers, is to be found in {\tt drivers/char}, and we'll use this
very directory as our referenece point when naming files.

Console initialization is performed by the function {\tt tty\_init()},
in {\tt tty\_io.c}. This function is only concerned in getting major
device numbers and calling the init function for each device set.
{\tt con\_init()}, then is the one related to the console, and resides
in {\tt console.c}.

\parversion{Initialization of the console has changed quite a lot
	during 1.1 evolution. {\tt console\_init()} has been detatched from
	{\tt tty\_init()}, and is called directly
	by {\tt ../../main.c}. The virtual
	consoles are now dynamically allocated, and quite a good deal of code
	has changed. So, I'll skip the details of initialization, allocation and
	such.}

\subsection{How file operations are dispatched to the console} %-----

This paragraph is quite low-level, and can be happily skipped over.

Needless to say, a \unix\ device is accessed though the filesystem.
This paragraph details all steps from the device file to the actual
console functions. Moreover, the following information is extracted
from the 1.1.73 source code, and it may be slightly different from the
1.0 source.

When a device inode is opened, the function {\tt chrdev\_open()}
(or {\tt blkdev\_open()}, but we'll stich to character devices)
in {../../fs/devices.c} gets executed. This function is reached
by means of the structure {\tt def\_chr\_fops}, which in turn is referenced by
{\tt chrdev\_inode\_operations}, used by all the filesystem
types (see the previous section about filesystems).

{\tt chrdev\_open} takes care of specifying the device operations by
substituting the device specific {\tt file\_operations} table in the
current {\tt filp} and calls the specific {\tt open()}.
Device specific tables are kept in the array 
{\tt chrdevs[]}, indexed by the majour device number,
and filled by the same {\tt ../../fs/devices.c}.

If the device is a tty one (aren't we aiming at the console?),
we come to the tty drivers, whose functions are in {\tt tty\_io.c},
indexed by {\tt tty\_fops}. Thus, {\tt tty\_open()} calls
{\tt init\_dev()}, which allocates any data structure needed by the device,
based on the minor device number.

The minor number is also used to retrieve the actual driver for the
device, which has been registered through {\tt
tty\_register\_driver()}. The driver, then, is still another structure used to
dispatch computation, just like {\tt file\_ops}; it is concerned with
writing and controlling the device.  The last data structure used in
managing a tty is the line discipline, described later. The line
discipline for the console (and any other tty device) is set by
{\tt initialize\_tty\_struct()}, invoked by {\tt init\_dev}.

Everything we touched in this paragraph is device-independent. The only
console-specific particular is that {\tt console.c},
has registered its own driver during {\tt con\_init()}. The line discipline,
on the contrary, in independent of the device.

\parprobe{The {\tt tty\_driver} structure is fully explained within
{\tt <linux/tty\_driver.h>}}.

\parversion{The above information has been extracted from 1.1.73 source
	code. It isn't unlikely for your kernel to be somewhat different
	(``This information is subject to change without notice'').}

\subsection{Writing to the console} %---------------------------------

When a console device is written to, the function {\tt con\_write}
gets invoked. This function manages all the control characters and escape
sequences used to provide applications with complete screen management.
The escape sequences implemented are those of the {\tt vt102} terminal;
This means that your environment should say {\tt TERM=vt102} when you
are {\tt telnet}ting to a non-\linux\ host; the best choice for local
activities, however, is {\tt TERM=console} because the \linux\ console
offers a superset of {\tt vt102} functionality.

{\tt con\_write()}, thus, is mostly made up of nested switch
statements, used to handle a finite state automaton interpreting
escape sequences one character at a time. When in normal mode, the
character being printed is written directly to the video memory, using the
current {\tt attr}-ibute. Within {\tt console.c}, all the fields
of {\tt struct vc} are made accessible through macros, so any reference to
(for example) {\tt attr}, does actually refer to the field in the
structure {\tt vc\_cons[currcons]}, as long as {\tt currcons} is the
number of the console being referred to.

\parversion{Actually, {\tt vc\_cons} in newer kernels is no longer
	an array of structures , it now is an array of pointers whose
	contents are {\tt kmalloc()}ed. The use of macros greatly
	simplified changing the approach, because much of the code didn't
	need to be rewritten.}
 
Actual mapping and unmapping of the console memory to screen is
performed by the functions {\tt set\_scrmem()} (which copies data from
the console buffer to video memory) and {\tt get\_scrmem} (which copies
back data to the console buffer). The private buffer of the current
console is physically mapped on the actual video RAM, in order to
minimize the number of data transfers. This means that {\tt get}- and
{\tt set}- -{\_scrmem()} are {\tt static} to {\tt console.c} and are
called only during a console switch.

\subsection{Reading the console} %------------------------------------

Reading the console is accomplished through the line-discipline.  The
default (and unique) line discipline in \linux\ is called {\tt
tty\_ldisc\_N\_TTY}. The line discipline is what ``disciplines input
through a line''. It is another function table (we're used to the
approach, aren't we?), which is concerned with reading the
device. With the help of {\tt termios} flags, the line discipline is
what controls input from the tty: raw, cbreak and cooked mode; {\tt select()};
{\tt ioctl()} and so on.

The read function in the line discipline is called {\tt read\_chan()},
which reads the tty buffer independently of whence it came from. The
reason is that character arrival through a tty is managed by asynchronous
hardware interrupts.

\parprobe{The line discipline {\tt N\_TTY} is to be found in the
	same {\tt tty\_io.c}, though later kernels use a different
	{\tt n\_tty.c} source file.}

The lowest level of console input is part of keyboard management, and
thus it is handled within {\tt keyboard.c}, in the function {\tt
keyboard\_interrupt()}.

\subsection{Keyboard management} %------------------------------------

Keyboard management is quite a nightmare. It is confined to the file
{\tt keyboard.c}, which is full of hexadecimal numbers to represent the
various keycodes appearing in keyboards of different manifacturers.

I won't dig in {\t keyboard.c}, because no relevant information
is there to the kernel hacker.

\parprobe{For those readers who are really interested in the \linux\ keyboard,
	the best approach to {\tt keyboard.c} is from the last line
	upward. Lowest level details occur mainly in the first half of the
	file.}

\subsection{Switching the current console} %--------------------------

The current console is switched through invocation of the function {\tt
change\_console()}, which resides in {\tt tty\_io.c} and is invoked
by both {\tt keyboard.c} and {\tt vt.c} (the former switches console in
response to keypresses, the latter when a program requests it by invoking
an {\tt ioctl()} call).

The actual switching process is performed in two steps, and the function
{\tt complete\_change\_console()} takes care of the second part of it.
Splitting the switch is meant to complete the task after a possible
handshake with the process controlling the tty we're leaving. If the
console is not under process control, {\tt change\_console()}
calls {\tt complete\_change\_console()} by itself. Process intervertion is
needed to successfully switch from a graphic console to a text one and
viceversa, and the X server (for example) is the controlling process of
its own graphic console.

\subsection{The selection mechanism} %--------------------------------

``{\tt selection}'' is the cut and paste facility for the \linux\ text
consoles. The mechanism is mainly handled by a user-level process,
which can be instantiated by either {\tt selection} or {\tt gpm}.
The user-level program uses {\tt ioctl()} on the console to tell the kernel to
highlight a region of the screen. The selected text, then, is copied
to a selection buffer. The buffer is a static entity in {\tt
console.c}. Pasting text is accomplished by `manually' pushing
characters in the tty input queue. The whole selection mechanism is
protected by {\tt \#ifdef} so users can disable it during kernel
configuration to save a few kilobytes of ram.

Selection is a very-low-level facility, and its workings are hidden
from any other kernel activity. This means that most {\tt \#ifdef}'s
simply deals with removing the highlight before the screen is modified
in any way. 

\parversion{Newer kernels feature improved code for selection, and
	the mouse pointer can be highlighted independently of the selected
	text (1.1.32 and later).  Moreover, from 1.1.73 onward a dynamic
	buffer is used for selected text rather than a static one, making
	the kernel 4kB smaller.}

\subsection{{\tt ioctl()}ling the device} %---------------------------

The {\tt ioctl()} system call is the entry point for user processes to
control the behaviour of device files. Ioctl management is spawned by
{\tt ../../fs/ioctl.c}, where the real {\tt sys\_ioctl()} resides.
The standard {\tt ioctl} requests are performed right there, other
file-related requests are processed by {\tt file\_ioctl()} (same source
file), while any other request is dispatches to the device-specific
{\tt ioctl()} function.

The {\tt ioctl} material for console devices resides in {\tt vt.c},
because the console driver dispatches ioctl requests to {\tt vt\_ioctl()}.

\parversion{The information above refer to 1.1.7x. The 1.0 kernel doesn't
	have the ``driver'' table, and {\tt vt\_ioctl()} is pointed to directly
	by the {\tt file\_operations()} table.}

Ioctl material is quite confused, indeed. Some requests are related to the
device, and some are related to the line discipline. I'll try to summarize
things for the 1.0 and the 1.1.7x kernels. Anything happened in between.

The 1.1.7x series features the following approach: {\tt tty\_ioctl.c}
implements only line discipline requests (namely {\tt
n\_tty\_ioctl()}, which is the only n\_tty function outside of {\tt
n\_tty.c}), while the {\tt file\_operations} field points to {\tt
tty\_ioctl()} in {\tt tty\_io.c}. If the request number is not
resolved by {\tt tty\_ioctl()}, it is passed along to {\tt
tty->driver.ioctl} or, if it fails, to {\tt
tty->ldisc.ioctl}. Driver-related stuff for the console it to be found
in {\tt vt.c}, while line discipline material is in {\tt tty\_ioctl.c}.

In the 1.0 kernel, {\tt tty\_ioctl()} is in {\tt tty\_ioctl.c} and
is pointed to by generic tty {\tt file\_operations}. Unresolved requests
are passed along to the specific ioctl function or to the line-discipline code,
in a way similar to 1.1.7x.

Note that in both cases, the {\tt TIOCLINUX} request is in the
device-independent code. This implies that the console selection can
be set by {\tt ioctl}ling any tty ({\tt set\_selection()} always operates
on the foreground console), and this is a security hole. It is also a good
reason to switch to a newer kernel, where the problem is fixed by
only allowing the superuser to handle the selection.

% Well, I'm telling Linus about the problem right now...

A variety of requests can be issued to the console device, and the
best way to know about them is to browse the source file {\tt vt.c}.

%\section{Other character drivers} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%
% Here I should talk about serial lines and mouse types. More about
% the latter because I'm more competent about them.

%   maybe....
%\section{How the kernel is configured} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%		but kernel cfg is due to change, hopefully

