Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 5 Aug 1998 16:40:59 -0700 (PDT)
From:      Julian Elischer <julian@whistle.com>
To:        current@FreeBSD.ORG
Cc:        Kelly Yancey <kbyanc@freedomnet.com>
Subject:   syscons update
Message-ID:  <Pine.BSF.3.95.980805163541.19956A-100000@current1.whistle.com>

next in thread | raw e-mail | index | archive | help
here is the outcome from the discussion on this in 93

I seem to remember it stalled at this point.

contributors at that time were:
dawes@physics.su.OZ.AU
Holger.Veit@gmd.de.
terry@icarus.weber.edu
mycroft@gnu.ai.mit.edu
bsdealwi@undergrad.math.uwaterloo.ca
ache@astral.msk.su
hm@hcshh.hcs.de
rgrimes@cdrom.com
joerg_wunsch@uriah.sax.de
sos@kmd-ac.dk
vak@zebub.msk.su
kojima@kuis.kyoto-u.ac.jp
ukai@kuamp.kyoto-u.ac.jp
rich@lamprey.utmb.edu
---------------------------------------------
BASIC CONSOLE ARCHITECTURE: $Date: 93/07/30 23:42:04 $  $Revision: 1.6 $
Foreword:

The basic model that I propose has drawn heavily from the comments by all
the members of the group.
I have decided that I will use some concepts from Object Oriented techniques
in this, defining a number of "classes" that can be loaded at will, or in
the absense of loadable modules, could be compiled in.

-----------------------------------------------------------------------
Definitions:

A CLASS defines a set of INSTANCES that have the same external interfaces,
e.g. all terminal emulators must have the same interface. Two terminal
emulators, (e.g. vt10 and wyse60) must have the same interface, however they
have different code associated with them. They are still of the same CLASS.

A DERIVED CLASS is the set of all INSTANCES that are both in the same class
and also have the same code associated with them. (e.g. the set of all
INSTANCES with the terminal emulator interface and running the vt100 code)
The DERIVED CLASS supplies a table of methods, referenced by the INSTANCES
of that DERIVED CLASS

An INSTANCE is a specific instance of a CLASS and DERIVED CLASS,
that contains it's own STATE. There is no state held in a CLASS or
DERIVED CLASS. An INSTANCE is based around a structure which is
defined by the CLASS, and which has a pointer to a table of pointers
to methods (supplied by a particular DERIVED CLASS) and values,
(defined in meaning by the CLASS, but representative of state for
that INSTANCE only).. The structure defined for the INSTANCE by the
CLASS has also a (void *) pointer to a structure that is only
defined for each DERIVED CLASS and which code external to the
DERIVED CLASS cannot interpret. This structure is used to hold the
PRIVATE STATE of the INSTANCE, and can only be interretted by the
METHODS supplied by that DERIVED CLASS.

Each DERIVED CLASS supplies a single init routine, which when run
will link the DERIVED CLASS into any needed global structures.
e.g. "List of available terminal emulators". It also supplies
a CONSTRUCTOR routine that when called (from the list above)
will produce an INSTANCE of the required DERIVED CLASS.
I imagine the list being of the form: (for example);

TEs----->[name        ]-->"vt100"      /-->[name        ]-->"wyse50"
         [constructor ]-->0xFE200016   |   [constructor ]-->0xFE201542
         [next        ]----------------/   [next        ]-->0


The various INSTANCES include both private data, private methods, public
data and public methods. All DERIVED CLASSES put themselves
into ASCII identified lists, so that a list of available (loaded) TE
DERIVED CLASSES may look like, "vt100","adm3a","wyse60".

VC's inherit all their INSTANCE DERIVED CLASSES from the base VC (or
possibly the VC running at the time of creation), but can
substitute an INSTANCE which is a member of a different DERIVED CLASS.
e.g. replace an adm3a with a vt100.

Whether the VC INSTANCE actually exists for  each VC or is 'virtual'
depends on whether we want a special body of code to call the other
modules (INSTANCES) or whether they call each other, so that no explicitly
written VC layer exists. In either case a VC STRUCTURE certainly
exists for each VC. Each INSTANCE in the console system contains a backpointer
to the VC structure with which it is associated, to allow it to identify
state from the VC and also find other INSTANCES associated with that VC.
It may be that the central VC code calls methods
from each INSTANCE PLUS they might call methods from each other,
(e.g. the VS 'refresh' method might call the renderer's
methods directly in order to refresh the screen to the state it requires.


The classes I have defined (so far) are:
Terminal_emulator		All terminal emulators are members of this
				class, though differnt VCs may use different
				instantiations of the same emulator DERIVED
				CLASS they may use differnt DERIVED CLASSES
				(e.g. a vt100 or a adm31a DERIVED CLASS
				of the TE class).
				i.e. they have the same public interfaces.
				The TE only talks to the VS (virtual screen)
				code when 'rendering'. The VS methods pass
				these calls on to the actual RENDERER methods
				only if that VC is actually ON-SCREEN.
				While this implies that a person COULD change
				TEs on the fly, it's more intended that a new
				VC could be created using a different TE to
				the TE that was running when it ws created.
				(a 3274 TE and a normal TE on differnt VC's).
				Changing TE's on the fly would require very
				careful state management and would probably
				not work (in initial versions,  at least though 
				I don't see this as being a needed feature).
				The state of each TE is internally held
				and considered private in scope.

virt_screen			The virt_screen CLASS defines a set of methods
				that the external world (e.g. the TE) can
				use to draw on the screen. It draws however on
				a 'virtual screen' regardless of what hardware
				is present and whether that VC is presently
				being shown on the real screen. When that
				VC is selected for display, it uses it's 
				internal virtual screen to refresh the real
				screen, using the renderer methods form the
				VC's renderer INSTANCE. Requests to the methods
				that arrive while it is "on screen" are passed 
				down to the annalogous renderer method.
				because virt_screen and renderer classes are
				so closely related they might even both be 
				implimented as DERIVED CLASSES of the same
				RENDERER CLASS. (e.g. if VC's were not
				being supported, the renderer INSTANCE might be
				placed into the VS slot?). The virt_screen
				INSTANCE can store it's virtual screen in any way
				it likes, as that's private to the DERIVED
				CLASS, however, it will be handed characters
				in the 'internal' character set. I can imagine
				needing upto 32 bits per character position.
				(including attributes). The VS has NO IDEA
				what the characters look like. It has only
				the SYMBOLS.

				It is possible the the TE should
				hold the VS map and should redraw
				the screen through calls directly
				to the renderer when asked by the
				refresh() entrypoint. In that scenario
				there would be no VS objects.


renderer			The renderer supplies methods similar to the
				virtual screen, however they result in changes
				on the physical display. The VS INSTANCE talks
				to the renderer, and might instruct it to 
				refresh the entire display or just write a
				single character and attribute to a fixed
				place. The renderer is hardware specific
				and could alternatively be called the
				"frame-buffer" driver, or "display driver".
				Terry points out that a hard-copy renderer 
				might be of interest to allow screen dumps etc.
				The renderer might work in graphics mode,
				but the virtual screen INSTANCES and renderer
				methods are basically character oriented,
				using whatever means it can to render the
				internal character set elements, using
				information taken from the 'FONT' INSTANCE
				associated with that VC. It has also been
				pointed out that there could be such a thing
				as a 'serial line terminal' renderer. 8-)

exter_intern_mapper		For each external coding used by the 
				user, there is a different DERIVED CLASS.
				The default DERIVED CLASS would simply deliver
				the bottom 8 bits of the internal
				representation the user and visa versa.
				(if we decide to use unicode as the internal
				representation then the default 8-bit code
				presented to the user would be ISO 8859-1).
				A VC that was using a JIS 208/212 external
				mapping would use an INSTANCE that did the
				appropriate (more complex) mapping. 
				(Assuming that one was loaded).

Keyboard_mapper			Different DERIVED CLASSES would be used to
				map different national keyboards. The keyboard
				INSTANCE for each VT may be of different 
				keyboard DERIVED CLASSES. NOTE: this is not the 
				keyboard driver, which is responsible for
				handling different types of keyboards.
				There are two levels of keyboard handling.
				One of them knows what scancodes respond to
				what keys and produces a standard scancode
				set..(PS2?) and the other knows
				what internal code should be generated
				from each of those scancodes, for the
				language(s) presently being used.(and
				taking account of language 'SHIFT' effects).
				The present X interface would not use this 
				INSTANCE, except when loading the default map.
				(I know this is not what Terry wants, but
				It fits in better with what X needs at
				the moment)

Font				A Font INSTANCE can return font information 
				for any internally represented character,
				as well as information about the font.
				(including 'not supported.. use "BLOB"')
				This includes font size, ligature information
				etc. The font INSTANCE is used almost
				exclusively by the renderer,
				to impliment requests from the VS. It also
				has an interaction with the mode control code.
				There would probably be a method associated
				with enabling the rendering agent
				to efficiently and quickly load fonts into
				hardware. I can imagine a font INSTANCE that
				returns a particular version of a character
				depending on the surrounding characters..
				e.g. arabic or indian linking of word-parts.
				This would be of little use for character based
				hardware, however graphics based hardware
				could make use of this in non-western 
				languages.


Other modules that could be defined in object form (but not neccesarily)
include the VC control module and the Keyboard driver itself, though
one might not necessarily want multiple instances of either.

the overall picture looks as follows:
(This is the connection and flow for a Single VC, another VC would
talk to other instances of the 'CLASSES').

      +-----------------------------------------+
      |     | TTY IN  |       | other | TTY OUT |
      | RAW |  I/F    |VC I/F |RAW I/F|   I/F   |
      | KBD |         |       |       |         |
      | I/F |----^----|-------|-------|---v-----|
      |     | INT/EXT |               | EXT/INT |
      |     |  CONV   |               |  CONV   |
      |     < (int/ext|               |(int/ext |
      |     | object) |   VC CODE     |  object)|
      |     |----^----|               |---v-----|
      |     |         |               |         |
      |     | TE IN   |               | TE OUT  |
      |     | ( TE    |               | ( TE    |
      |     | object) |               | object) |
      |     |----^----|        +------|---v-----|
      |     |         |        | Font |         |
      |     < KBD MAP |        |(Font | VS CODE | <-- The VS may become
      |     |(kbd obj)|        | obj) |         | 	part of the TE
      |--^-------^-------^--^v----v------^v-----|
      |  Keyboard driver   |     Renderer       |
      |                    | and Mode control   |
      |                    |                    |
      +-----------------------------------------+

The TE ,TTY, and EXT/INT modules are shown as separate in and out modules,
however they would be in fact not split. That's just for clarity.

Each VC has pointers to the following tables/INSTANCES in it's local table:
font INSTANCE
ext/int INSTANCE
keyboard obj
TE obj
VS storage pointer (an INSTANCE?)
renderer private info.(an INSTANCE?)
TTY interface to use.

The VS code you are probably wondering about is the Virtual Screen.
each VC has a VS associated with which it talks in character oriented
primatives. (at least the basic version would).
If the VC is presently on screen, these calls are
passed on to the renderer, otherwise, only the VS is updated.
The VS is used to update the screen when a VC is 'exposed'.
The VS code is not likely to need differnt versions of itself
co-existing, so it is unlikely that it need be implimented as
an 'object'. the same goes for the VC code. It may be worthwhile
considering the VS code as an object, just so we get the
encapsulation and to make it similar to the other modules.
Possibly an enhansed VS could be written to support graphics actions.

The present state of the art regarding X servers requires some support
in the renderer, for Process notification on VC switch, but I don't
think that the raw graphics interfaces can be expected to go through
the VS layer. This would be a good 'project' for someone, and we should
not consider that it will never happen.

While the inclusion from the start of VCs may seem to over-specify, I feel
that this is a feature that must be built in from the start. If it were
not, then it would be very hard to retro-fit 'per VC' instances of each
of the INSTANCES.

All INSTANCES would be dynamically allocated, and the act of loading
a new module and running it's "init" routine would be the equivalent
of definign a new available DERIVED CLASS. By this I mean, the 'struct' is
dynamically allocated. (public and private parts) The code will have
to be either loaded using terry's stuff or compiled in.

This need not be large or cumbersome. Properly coded in C this approach
should lead to highly separatable and replacable modules, without
much speed penalty.

I see the implimentation being in C rather than C++ though this is
more for non technical reasons.

I briefly outline below some first sketches
of the implimentation.
--------------------------------------------------------------------
Preliminary example:

Each 'INSTANCE' is based around a structure that 
is always the same. It has a pointer to the DERIVED CLASS (including
methods), and a pointer to the PRIVATE STATE data. It also has a pointer to
the VC with which it is associated.

Control is passed around between the INSTANCES and the VC code
so as to achieve the desired result. (and between the INSTANCES)
All methods have as their first argument, the address of the INSTANCE they
were called from ('this' in C++).
Below is a quick sketch of how they would look. they are not complete,
and the methods and variables needed for each INSTANCE are open to discussion.
Each INSTANCE has a few items in common.
A pointer back to the VC of which it is a part.
A pointer (type void*) to that INSTANCE's private data (that could be
	differently defined for different DERIVED CLASSES (e.g. vt100 would
	keep different private data to wy50).
A pointer to the DERIVED CLASS's methods.

Each DERIVED CLASS in turn has:

A name pointer (e.g. "vt100" or "ISO-8859-1")
A pointer to a 'delete operation to delete all the resources used
	by this INSTANCE if that VC is destroyed,
	(or an alternate INSTANCE is swapped in)
As well as these there are entry points to methods to allow the INSTANCE to
do it's work.


typedef	long int	externalchar;
typedef	long int	internalchar;
typedef	long int	attributes;
typedef	unsigned char	scancode;	/* short? */
typedef int		status;

/* Each VC has one of these that identifies each INSTANCE that makes it up */
struct virt_cons
{
	struct	virt_cons	*next;
	struct	c_baseobj	*ext_int;
	struct	c_baseobj	*term;
	struct	c_baseobj	*kbd_map
	struct	c_baseobj	*font;
	struct	c_baseobj	*vs;
	struct	c_baseobj	*renderer;
};

All the INSTANCES point to DERIVED CLASSES
ALL the DERIVED CLASS structures contain the following information:
These are the STANDARD ENTRIES and in C++ would be inherrited from the BASE
CLASS

	char		*name;
	status		(print*)(struct c_baseobj *); /* print out  an instance */
	status		(delete*)(struct c_baseobj *); /* delete an instance */
	status		(create*)(struct c_baseobj **); /* delete an instance */
as well as specialist methods (shown below)
/* 
 * the central struct for the translation module that translates the
 * internal code to whatever charater set the user wants to recieve data in.
 * Defines methods to translate incoming and outgoing data.
 */
struct	extern_intern /* may need changing to suport multi-length codes */
{
	STANDARD ENTRIES plus:

	internalchar	(fromuser*)(struct extern_intern *,externalchar);
	externalchar	(fromte*)(struct extern_intern *,internalchar);
};
	
/*
 * Methods and data for the terminal emulator, including:
 * a method to call with data from the user,
 * a method to call with data from the keyboard,
 */
struct	term_emul 
{
	STANDARD ENTRIES plus:

	status	(fromuser*)(struct term_emul *,internalchar);
	status	(fromkbd*)(struct term_emul *,internalchar);
};

/*
 * Methods and data for an object that translates scancode type data
 * from the keyboard, into internalchar form.
 * (Handles shift, meta, cntrl, alt etc.)
 */
struct	kbd_map
{
	STANDARD ENTRIES plus:

	internalchar	(fromkbd*)(struct kbd_map *,scancode);
};
	
/*
 * Methods and data for a particular font,
 * Including methods that return a pointer to a bitmap given an internalchar,
 * or given a font position, returns the internalchar it represents.
 */
struct	font_type
{
	STANDARD ENTRIES plus:

	int		(mapchar*)(struct font_type *,internalchar);
	status		(mapglyph*(struct font_type *,int,internalchar *);
	int		height,width,number;/* what if 'variable' sized? */
};

/*
 * Methods and data for the hardware independent virtual screens
 */
struct	virt_screen
{
	STANDARD ENTRIES plus:

	status		(drawchar*)(struct virt_screen *,internalchar,
					attributes,int,int);
	status		(drawmany*)(struct virt_screen *,internalchar *,
					attributes *,int x,int y,int n);
	status		(setsize*)(struct virt_screen *,int x,int y);   /* x,y */
	internalchar	(returnchar)(struct virt_screen *,int x,int y,attribute *);
	/* the scrolls start at the {row/column} in the 2nd arg */
	status		(scrollup*)(struct virt_screen *,int);
	status		(scrolldown*)(struct virt_screen *,int);
	status		(scrollleft*)(struct virt_screen *,int);
	status		(scrollright*)(struct virt_screen *,int);
	status		(refresh*)(struct virt_screen *);   /* tell VS */
			/* to redraw entire screen, using renderer commands*/
};

/*
 * Methods and data for the hardware specific 'driver'
 */

struct	renderer
{
	STANDARD ENTRIES plus:

	status		(drawchar*)(struct renderer *, internalchar,
			attributes,int x,int y);
	status		(drawmany*)(struct renderer *, internalchar *,
			attributes *,int x,int y,int n);
	/* the scrolls start at the {row/column} in the 2nd arg */
	status		(scrollup*)(struct renderer *,int);
	status		(scrolldown*)(struct renderer *,int);
	status		(scrollleft*)(struct renderer *,int);
	status		(scrollright*)(struct renderer *,int);
	status		(setmode*)(struct renderer *);/* on VC switch to us */
	char		*modename;	/* e.g. "80x25x9x15" or "640x480x256"*/
	status		(setnewmode*)(struct renderer *,mode);
	char		*(listmodes*)(struct renderer *);
	status		(addmode*)(struct renderer *,script);
	status		(loadfont*)(struct renderer *);
};




To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.3.95.980805163541.19956A-100000>