From owner-freebsd-current Wed Aug 5 16:44:20 1998 Return-Path: Received: (from majordom@localhost) by hub.freebsd.org (8.8.8/8.8.8) id QAA17335 for freebsd-current-outgoing; Wed, 5 Aug 1998 16:44:20 -0700 (PDT) (envelope-from owner-freebsd-current@FreeBSD.ORG) Received: from alpo.whistle.com (alpo.whistle.com [207.76.204.38]) by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id QAA17314 for ; Wed, 5 Aug 1998 16:44:14 -0700 (PDT) (envelope-from julian@whistle.com) Received: (from daemon@localhost) by alpo.whistle.com (8.8.5/8.8.5) id QAA23122; Wed, 5 Aug 1998 16:41:09 -0700 (PDT) Received: from current1.whistle.com(207.76.205.22) via SMTP by alpo.whistle.com, id smtpdV23117; Wed Aug 5 23:41:03 1998 Date: Wed, 5 Aug 1998 16:40:59 -0700 (PDT) From: Julian Elischer To: current@FreeBSD.ORG cc: Kelly Yancey Subject: syscons update Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG 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