Main Page

NetBSD pcvt Tutorial

This is a revised and expanded version of the answers to
two questions from my January 1999 Dæmonnews column.
If you have already read those questions, skip to the new stuff.

N.B. All testing was done with NetBSD-1.3.2 and its included XFree86 3.3.2. NetBSD-1.3.3 has just been released with XFree86 3.3.3, and while I fully expect these instructions to apply equally well to them, the AnswerMan policy of due disclosure requires I state here that I don't have a machine running that release and haven't tested it myself.


This tutorial describes how to reconfigure a NetBSD 1.3.2 system to enable the pcvt console driver, which provides enhanced functionality for users of commodity EGA/VGA hardware. The instructions are specific to NetBSD/i386 although they may prove to be of use to NetBSD/bebox users as well. Everyone else running systems that support commodity PCI/ISA video cards should either obtain netbsd-current. or wait for the forthcoming 1.4 release, and help test out the new WSCONS system.

The default console driver for NetBSD/i386 is usually referred to as "pccons". It does not support virtual terminals (multiple text consoles that you can switch between using Control-Alt-Fn sequences) nor does it support font loading (which is necessary to allow greater than 25 line operation). You can get these features by switching your system over to using the "pcvt" (A.K.A. "syscons") driver, but this can easily be a tricky process because the console is a pretty critical part of the system.

WARNING! You will need to build a new kernel and change lines of /etc/ttys to activate pcvt. Make sure you follow the instructions below, and keep a backup kernel on your boot disk that you can get to with "boot wd0a:/netbsd.safe" or something like that. If you do any serious experimenting with pcvt then it is possible to reboot with things configured inconsistently such that you get locked out of your own console. (Laugh if you want, but it did happen to me once the first time I really messed with it.) This is less of a problem if your machine is on a network and allows you to login from somewhere else to fix things.

First off, if you don't already have kernel sources on your machine, get them from a CD-ROM or download them and extract into / so that they get put in /usr/src. While that is extracting, familiarize yourself with the features and settings of the driver by reading the first 30% or so of "man pcvt" and skimming the rest. For the truly adventurous, the original installation instructions do appear in the source tree as /sys/arch/i386/isa/pcvt/Doc/INSTALL.NetBSD-1.0.

Now you're ready to edit your kernel configuration file (for tutorial purposes we'll use GENERIC throughout):

% cd /sys/arch/i386/conf
% vi GENERIC
Search for "pc0" and change these two lines:
pc0	at isa? port 0x60 irq 1		# pccons generic PC console driver
#vt0	at isa? port 0x60 irq 1		# PCVT console driver

to

#pc0	at isa? port 0x60 irq 1		# pccons generic PC console driver
vt0	at isa? port 0x60 irq 1		# PCVT console driver
options PCVT_NETBSD = 132		# enable PCVT for NetBSD 1.3.2

Then configure and rebuild:

% config GENERIC
% cd ../compile/GENERIC
% make depend && make
% mv netbsd /netbsd.pcvt

BEFORE YOU REBOOT WITH THIS KERNEL check to be sure that /dev/ttyvn (where n is 0 through 8) all exist. You can create them with:

% cd /dev
% sh MAKEDEV ttyv0 ttyv1 ttyv2 ttyv3 ttyv4 ttyv5 ttyv6 ttyv7 ttyv8

Also check to make sure /etc/ttys contains at least this line:

ttyv0   "/usr/libexec/getty Pc"         pc3     on secure

Okay, you are now ready to try out pcvt by rebooting and hitting space when you see the BIOS boot banner and the text:

booting wd0a:netbsd - starting in 5

It should then print

type "?" or "help" for help.
>

Now boot your new kernel (replace the "wd" with "sd" if your boot disk is SCSI):

> boot wd0a:netbsd.pcvt

Note that the kernel boot messages now print with red as their background color. Instructions on how to change these colors may be found here.

When you login as root on the console with this new kernel, it will offer to make "pc3" be the default terminal setting. Now that you've verified your new kernel is working, let's update the terminal settings. Edit /etc/ttys:

ttyv0   "/usr/libexec/getty Pc"         pc3     on secure

Change this to (the lines marked off are placeholders for X and mouse emulation features):

ttyv0   "/usr/libexec/getty Pc"         vt100   on secure
ttyv1   "/usr/libexec/getty Pc"         vt100   on secure
ttyv2   "/usr/libexec/getty Pc"         vt100   on secure
ttyv3   "/usr/libexec/getty Pc"         vt100   on secure
ttyv4   "/usr/libexec/getty Pc"         vt100   on secure
ttyv5   "/usr/libexec/getty Pc"         vt100   on secure
ttyv6   "/usr/libexec/getty Pc"         vt100   off secure # X11 screen :0
ttyv7   "/usr/libexec/getty Pc"         vt100   off secure # X11 screen :1
ttyv8   "/usr/libexec/getty Pc"         vt100   off secure # mouse emulation
To recognize the new terminal entries without rebooting, run this:
% kill -HUP 1

Now type Control-Alt-F2 (note that this is not the same sequence you would use with FreeBSD) and you should be rewarded with this:

NetBSD/i386 (nobody.erewhon.com) (ttyv1)

login:

To make your new kernel the default for future boots, do this:

% mv /netbsd /netbsd.safe
% mv /netbsd.pcvt /netbsd

For the font features, you'll need the pcvt utility programs, which don't ship with the standard binary distribution of NetBSD 1.3.2. When I tried switching to pcvt, I snooped around in the kernel sources (syssrc.tgz) and built them myself. You'll want to peruse the README files and other interesting stuff in and around

/sys/arch/i386/isa/pcvt/Util

To build and install the utility programs, do this:

% cd /sys/arch/i386/isa/pcvt/Util
% make depend
% make
% make install
% cd ../Etc
% ls

This will allow you to get started by reading the man pages for everything in the Util directory, perusing the example files in the Etc directory, and examining the key translation tables in /usr/share/misc/keycap.pcvt. You can also adapt the rc.local file to be called from your /etc/rc* scripts so that everything is set up automatically at boot time (cookbook instructions here).


The New Stuff

Did you spot the F-key typo?
Changing the display colors for kernel output
Fonts and large terminal screens
How does it know which font to use?
Boot time configuration
Device node details
Using X and pcvt together
Why does it beep at me when I switch between text
or graphics twice while holding down Control-Alt?
Updated /etc/rc.pcvt script
How do I make Backspace and Delete work consistently?

Did you spot the F-key typo?

I goofed! When I told you (in the Dæmonnews column) to type Control-Alt-F1, nothing happened, right? That was because Control-Alt-F1 is what you type to get back to the primary console ttyv0. The actual sequence you type to get ttyv1 is Control-Alt-F2. Argh! Here's the list of shortcuts to switch terminal screens:
Terminal
Device
"Switch to"
Key Sequence
Shortcut
(0-3 only)
ttyv0Control-Alt-F1F9
ttyv1Control-Alt-F2F10
ttyv2Control-Alt-F3F11
ttyv3Control-Alt-F4F12
ttyv4Control-Alt-F5
ttyv5Control-Alt-F6
ttyv6Control-Alt-F7
ttyv7Control-Alt-F8

This rule holds for however many terminal devices the driver is compiled to support (assuming you have enough function keys, that is), and may be set to something other than eight. (See Device node details below.)

Changing the display colors for kernel output

The colors for kernel output are just #define's in the pcvt code, with values taken from /sys/arch/i386/include/pc/display.h and defaults being set at the bottom of /sys/arch/i386/isa/pcvt/pcvt_conf.h. To change your kernel text colors to be red on a black background, add these lines to your GENERIC file:

options COLOR_KERNEL_FG = FG_LIGHTRED   # this must be a FG_ color
options COLOR_KERNEL_BG = BG_BLACK      # this must be a BG_ color

To play a practical joke on a fellow NetBSD user, try the following:

options COLOR_KERNEL_FG = "FG_YELLOW|FG_BLINK"  # this must be a FG_ color
options COLOR_KERNEL_BG = BG_BLUE       # this must be a BG_ color

Now rebuild your kernel (note the extra rm step):

% cd /sys/arch/i386/conf
% config GENERIC
% cd ../compile/GENERIC
% rm pcvt*.o
% make depend && make
% mv netbsd /netbsd.pcvt
When you are happy with the new colors, make your new kernel the default one:
% mv /netbsd /netbsd.safe
% mv /netbsd.pcvt /netbsd

Fonts and large terminal screens

Start by checking the current state of the video display font memory:

% loadfont -i
In general this only works from sessions running on one of the /dev/ttyvn terminals, due to terminal device permission bits. The output you want to see is something like the following:
EGA/VGA Charactersets Status Info:

Set Status Lines CharScanLines ScreenScanLines
--- ------ ----- ------------- ---------------
 0  Loaded  25        16            400
 1  Empty
 2  Empty
 3  Empty
 4  Empty
 5  Empty
 6  Empty
 7  Empty
(If your video card is old enough to not have VGA capability, then you'll only see four slots, instead of eight.) Let's try loading a small (8 by 8 pixels) font into slots 2 and 3. The "low" font in slot 2 is normal ASCII characters, and the "high" font in slot 3 is a bunch of special characters from the VT220.
% loadfont -d /dev/ttyv0 -c2 -f /usr/share/misc/pcvtfonts/vt220l.808
% loadfont -d /dev/ttyv0 -c3 -f /usr/share/misc/pcvtfonts/vt220h.808
% loadfont -i
This time you should see:
EGA/VGA Charactersets Status Info:

Set Status Lines CharScanLines ScreenScanLines
--- ------ ----- ------------- ---------------
 0  Loaded  25        16            400
 1  Empty
 2  Loaded  50        08            400
 3  Loaded  50        08            400
 4  Empty
 5  Empty
 6  Empty
 7  Empty
Now we're ready to throw this terminal into 50-line mode:
% scon -s 50
% cursor -s 0 -e 7
We have to fix up the cursor because it is specified in terms of scan lines within a single character cell, and the default cursor is an underline positioned near the bottom of a 16-line cell. When we change to a 50-line screen the character cells only have 8 lines each, and the cursor disappears.

How does it know which font to use?

The driver is hardcoded to search for the two lowest slots that contain an appropriately sized font for the scon -s argument. If it can't find at least one, it ignores the request. The second character set (if found) is used to display control character symbols (little CR's and LF's in a single character cell, if you've ever seen those on a real terminal) and also alternate character sets (accessed via VT220 control codes) that display math symbols or accented characters.

Note that the above implies you can only have one font per screen size. To fix it, the ioctl() interface to the driver would need to be enhanced to let you pick the character set directly. Right now it only accepts a screen size and finds the character sets on its own.

Boot time configuration

I adapted the sample rc.local file into a proper /etc/rc.pcvt which you can download. To activate it, add these commands to the bottom of your /etc/rc.local:

# set up the pcvt driver settings and virtual terminals
if [ -f /etc/rc.pcvt ]; then
    sh /etc/rc.pcvt
fi
Also, change your /etc/ttys file to reflect the higher-density terminals:
ttyv0   "/usr/libexec/getty Pc"         pcvt50  on secure
ttyv1   "/usr/libexec/getty Pc"         pcvt40  on secure
ttyv2   "/usr/libexec/getty Pc"         pcvt28  on secure
ttyv3   "/usr/libexec/getty Pc"         pcvt25  on secure
ttyv4   "/usr/libexec/getty Pc"         pcvt43  on secure
ttyv5   "/usr/libexec/getty Pc"         pcvt35  on secure
ttyv6   "/usr/libexec/getty Pc"         vt100   off secure # X11 screen :0
ttyv7   "/usr/libexec/getty Pc"         vt100   off secure # X11 screen :1
ttyv8   "/usr/libexec/getty Pc"         vt100   off secure # mouse emulation
On subsequent reboots, rc.pcvt will attempt to set the terminal sizes automatically, by scanning /etc/ttys. Its algorithm is not incredibly smart, but will usually get the right size. Note that with the available fonts, VGA cards support 25, 28, 40, or 50 lines and EGA cards support 25, 35, or 43 lines. If you ask for sizes other than these, rc.pcvt will quietly use a safe default depending on the video card type, but the TERM variable will still be what /etc/ttys declared for that terminal.

Device node details

In /sys/arch/i386/isa/pcvt/pcvt_conf.h the define PCVT_NSCREENS specifies how many virtual terminal screens are available. For the default 8 this means that /dev/ttyv0 through /dev/ttyv7 correspond to virtual terminal screens, and /dev/ttyv8 is reserved for use by the optional keypad mouse emulator (look for comments near uses of PCVT_EMU_MOUSE; its default is off). This last device is always the highest-numbered of the ttyvn set.

Using X and pcvt together

To avoid problems while running X11 on top of pcvt, make sure that for each X screen (:0, :1, etc.) displayed on the main screen by your primary X server, there is one virtual terminal device node marked as being off in /etc/ttys so that getty leaves it alone. If the X server cannot find enough free virtual terminal device nodes to represent itself, it will try to open devices already in use by getty, causing a fight over input data (e.g. sporadically dropped characters) on that device.

On most setups there is only one X screen on the console, so my examples that reserve both ttyv6 and ttyv7 are unnecessarily conservative. Here is what my /etc/ttys file currently does:

ttyv0	"/usr/libexec/getty Pc"		pcvt50	on secure
ttyv1	"/usr/libexec/getty Pc"		pcvt50	on secure
ttyv2	"/usr/libexec/getty Pc"		pcvt50	on secure
ttyv3	"/usr/libexec/getty Pc"		pcvt50	off secure	# X server!
ttyv4	"/usr/libexec/getty Pc"		pcvt50	on secure
ttyv5	"/usr/libexec/getty Pc"		pcvt40	on secure
ttyv6	"/usr/libexec/getty Pc"		pcvt28	on secure
ttyv7	"/usr/libexec/getty Pc"		pcvt25	on secure
ttyv8	"/usr/libexec/getty Pc"		pcvt25	off secure	# mouse emu
Since the X server picks the first free terminal, and F12 is a shortcut for switching to ttyv3, I can use just F12 to get back to X from any of the text screens. Note that the X server does not support single-key shortcuts for virtual terminals, so you'll need to use Control-Alt-Fn to get out of X into text mode. This behavior appears to be pretty deeply hardcoded into the X server. If anyone knows how to do this without hacking the source, please email me as it'll be a while before I can justify compiling a new X server to fix this :)

The idea behind the last four terminals is to display one of each possible screen size, so I can play with them.

Apparently the X server will use a specific terminal device if you give it an argument of the form vtn, where n is taken from the Control-Alt-Fn key sequence which switches to that terminal. I tried using this to see if I could get the X server to grab the same terminal as the one I invoked it from, and it appears to work okay, but when I exited the server it beeped and printed some gunk characters.

I decided that since I like logging in on a text screen and running the X server manually (with output redirected into a log file), I would just do so on the first virtual terminal and let it be dedicated to console messages.

Why does it beep at me when I switch between text or graphics twice while holding down Control-Alt?

Apparently when you transition between text and graphics display, the fact that you have Control-Alt held down is forgotten. This can be very annoying because an "uncaught" Fn key ends up producing a five character escape sequence (at least on my keyboard it does). Just remember to release the modifier keys once any time you switch between text and graphics mode.

Updated /etc/rc.pcvt script

An updated version of /etc/rc.pcvt is now available. Most of the changes were to compact the script and make it more readable. The only functional change was to allow reading of a specified keyboard mapping, and not just the "de" German keyboard layout.

How do I make Backspace and Delete work consistently?

Both pcvt and X11 have their own code to read the keyboard directly, and use their own translation tables to decide what each key combination means. This makes it non-obvious to set things up so that "key" keys (ha ha) like Backspace and Delete work consistently. Here's the (somewhat expedient) method I ended up with:

  1. Install the binary package for xkeycaps and use it to diagnose your X keyboard settings. In particular, keep picking keyboard types until you get one that really looks like your actual keyboard, so you can be sure the keycodes are probably right. While doing this, I found out that I had been using 101-key keyboard settings in my XF86Config file for over a year without noticing anything, even though all of my keyboards are variants of the 104-key "win95" keyboard style.
  2. When you have figured out which xmodmap settings work best for you, either install them in your X startup scripts (as described under "Write Output" in the xkeycaps man page and dialogs) or, if you use the default xinitrc (as I currently do), put them in the default xmodmap file, /usr/X11R6/lib/X11/xinit/.Xmodmap. As an example, mine is just this:
    keycode 0x16 = BackSpace
  3. To diagnose your pcvt key mappings, look through the output of this:
    % kcon -l | more
    I don't see any sane relationship between the X keycodes and the kcon key numbers, so I just reverse-engineered the keys manually by running
    % cat
    and typing the key I was interested in. For example, Delete on my keyboard yielded ^[[3~ (Escape-[-3-~) and was key number 76; Backspace was easily spotted as being key number 15.
  4. To try out new key mappings, add a "map entry" to /usr/share/misc/keycap.pcvt:
    # [toddpw] I like mine set so backspace is really backspace unless control'd.
    # Also I have the delete key really typing delete too.
    local|Local Settings:\
    	:K15=\010:S15=\010:C15=\177:\
    	:K76=\177:S76=\177:C76=\177:
    (Knn is normal, Snn is shifted, and Cnn is control'd.) To install these key mappings, execute
    % kcon -m local
    To reset your key mappings to the compiled-in default, there is an alias in keycaps.pcvt for you to use:
    % kcon -m default
  5. To install a set of key mappings on every boot, use the new rc.pcvt and change these lines
    # set to YES to set an alternate keyboard layout or local changes
    #set_keybd=YES
    set_keybd=NO
    # if set to YES, this is the key "map" that will be requested
    # these maps are defined in /usr/share/misc/keycap.pcvt
    #set_keybd_map=de     # German layout
    #set_keybd_map=local
    to
    # set to YES to set an alternate keyboard layout or local changes
    set_keybd=YES
    #set_keybd=NO
    # if set to YES, this is the key "map" that will be requested
    # these maps are defined in /usr/share/misc/keycap.pcvt
    #set_keybd_map=de     # German layout
    set_keybd_map=local
    This will cause "kcon -m local" to be executed by the rc.pcvt script.


Back to the main toddpw.org home page
If you have comments or suggestions, email me at webmaster@toddpw.org