2002-04-01 18:41:48

by Andries E. Brouwer

[permalink] [raw]
Subject: [PATCH] omission in video driver

Documenting the video ioctls, I noticed to my dismay
that the ioctl to set the border color of the console
screen is lacking.

Here part of the fix for 2.4.19:

--- /linux/2.4/linux-2.4.19pre4/linux/drivers/video/vgacon.c Fri Mar 29 01:02:00 2002
+++ ./vgacon.c Tue Apr 1 20:14:14 2002
@@ -244,6 +244,14 @@
outb_p (6, 0x3ce) ;
outb_p (6, 0x3cf) ;
#endif
+ /*
+ * Load overscan register red.
+ */
+ inb_p(0x3da); /* clear flipflop */
+ outb_p(0x11, 0x3c0); /* index overscan color */
+ outb_p(0x0c, 0x3c0); /* load value */
+ outb_p(0x20, 0x3c0); /* allow display memory
+ to access palette */

/*
* Normalise the palette registers, to point

Andries

[this is the nontrivial part; the rest is left as an exercise]


2002-04-03 13:43:11

by Paul Gortmaker

[permalink] [raw]
Subject: Re: [PATCH] omission in video driver

[email protected] wrote:
>
> Documenting the video ioctls, I noticed to my dismay
> that the ioctl to set the border color of the console
> screen is lacking.
>
> Here part of the fix for 2.4.19:
...
> [this is the nontrivial part; the rest is left as an exercise]

Heh, you mean "here is the hardware information, please make a patch".
But your choice of red makes it truly a "bleeding edge" kernel :)

The fact that we have been using linux for ~ 10 yrs and nobody has
complained about the lack of this function yet says something...

Anyway, have a look at this and see if it is what you had in mind.
I figured it would be sensible to have a per VC colour, which is the
way I've done it. At end of 2.4.19pre5 patch is a $0.02 test program.

Paul.

diff -ur ../linux/include/linux/console.h include/linux/console.h
--- ../linux/include/linux/console.h Thu Nov 22 11:46:19 2001
+++ include/linux/console.h Wed Apr 3 07:18:43 2002
@@ -41,6 +41,7 @@
int (*con_blank)(struct vc_data *, int);
int (*con_font_op)(struct vc_data *, struct console_font_op *);
int (*con_set_palette)(struct vc_data *, unsigned char *);
+ void (*con_border)(struct vc_data *);
int (*con_scrolldelta)(struct vc_data *, int);
int (*con_set_origin)(struct vc_data *);
void (*con_save_screen)(struct vc_data *);
diff -ur ../linux/include/linux/console_struct.h include/linux/console_struct.h
--- ../linux/include/linux/console_struct.h Thu Oct 11 11:17:22 2001
+++ include/linux/console_struct.h Wed Apr 3 07:18:43 2002
@@ -23,6 +23,7 @@
unsigned char vc_def_color; /* Default colors */
unsigned char vc_color; /* Foreground & background */
unsigned char vc_s_color; /* Saved foreground & background */
+ unsigned char vc_border; /* Border color */
unsigned char vc_ulcolor; /* Color for underline mode */
unsigned char vc_halfcolor; /* Color for half intensity mode */
unsigned short vc_complement_mask; /* [#] Xor mask for mouse pointer */
diff -ur ../linux/include/linux/kd.h include/linux/kd.h
--- ../linux/include/linux/kd.h Tue Aug 4 10:52:57 1998
+++ include/linux/kd.h Wed Apr 3 07:18:43 2002
@@ -155,6 +155,9 @@

#define KDFONTOP 0x4B72 /* font operations */

+#define PIO_BORDER 0x4B73 /* Border color */
+#define GIO_BORDER 0x4B74
+
struct console_font_op {
unsigned int op; /* operation code KD_FONT_OP_* */
unsigned int flags; /* KD_FONT_FLAG_* */
@@ -175,6 +178,6 @@

/* note: 0x4B00-0x4B4E all have had a value at some time;
don't reuse for the time being */
-/* note: 0x4B60-0x4B6D, 0x4B70-0x4B72 used above */
+/* note: 0x4B60-0x4B6D, 0x4B70-0x4B74 used above */

#endif /* _LINUX_KD_H */
diff -ur ../linux/include/linux/vt_kern.h include/linux/vt_kern.h
--- ../linux/include/linux/vt_kern.h Sun Sep 23 10:31:02 2001
+++ include/linux/vt_kern.h Wed Apr 3 07:18:43 2002
@@ -47,12 +47,15 @@
void vc_disallocate(unsigned int console);
void reset_palette(int currcons);
void set_palette(int currcons);
+void set_border(int currcons);
void do_blank_screen(int gfx_mode);
void unblank_screen(void);
void poke_blanked_console(void);
int con_font_op(int currcons, struct console_font_op *op);
int con_set_cmap(unsigned char *cmap);
int con_get_cmap(unsigned char *cmap);
+int con_set_border(int currcons, unsigned char *arg);
+int con_get_border(int currcons, unsigned char *arg);
void scrollback(int);
void scrollfront(int);
void update_region(int currcons, unsigned long start, int count);
--- ../linux/drivers/char/console.c Fri Dec 21 16:40:32 2001
+++ drivers/char/console.c Wed Apr 3 07:18:43 2002
@@ -608,6 +608,7 @@
set_origin(currcons);
update = sw->con_switch(vc_cons[currcons].d);
set_palette(currcons);
+ set_border(currcons);
if (update && vcmode != KD_GRAPHICS)
do_update_region(currcons, origin, screenbuf_size/2);
}
@@ -2425,6 +2426,7 @@
def_color = 0x07; /* white */
ulcolor = 0x0f; /* bold white */
halfcolor = 0x08; /* grey */
+ border = 0x00; /* black */
init_waitqueue_head(&vt_cons[currcons]->paste_wait);
reset_terminal(currcons, do_clear);
}
@@ -2749,6 +2751,7 @@
if (console_blank_hook)
console_blank_hook(0);
set_palette(currcons);
+ set_border(currcons);
if (sw->con_blank(vc_cons[currcons].d, 0))
/* Low-level driver cannot restore -> do it ourselves */
update_screen(fg_console);
@@ -2838,6 +2841,31 @@
palette[k++] = default_blu[j];
}
set_palette(currcons);
+}
+
+/*
+ * Borders
+ */
+
+int con_set_border(int currcons, unsigned char *arg)
+{
+ if (get_user(border, arg))
+ return -EFAULT;
+ set_border(currcons);
+ return 0;
+}
+
+int con_get_border(int currcons, unsigned char *arg)
+{
+ if (put_user(border, arg))
+ return -EFAULT;
+ return 0;
+}
+
+void set_border(int currcons)
+{
+ if (vcmode != KD_GRAPHICS && sw->con_border != NULL)
+ sw->con_border(vc_cons[currcons].d);
}

/*
--- ../linux/drivers/char/vt.c Fri Nov 16 10:08:28 2001
+++ drivers/char/vt.c Wed Apr 3 08:16:23 2002
@@ -8,6 +8,7 @@
* Restrict VT switching via ioctl() - [email protected] - Dec 1995
* Some code moved for less code duplication - Andi Kleen - Mar 1997
* Check put/get_user, cleanups - [email protected] - Jun 2001
+ * Get/set VT border color - Paul Gortmaker/aeb - Apr 2002
*/

#include <linux/config.h>
@@ -967,6 +968,14 @@

case GIO_CMAP:
return con_get_cmap((char *)arg);
+
+ case PIO_BORDER:
+ if (!perm)
+ return -EPERM;
+ return con_set_border(fg_console, (unsigned char *)arg);
+
+ case GIO_BORDER:
+ return con_get_border(fg_console, (unsigned char *)arg);

case PIO_FONTX:
case GIO_FONTX:
--- ../linux/drivers/video/vgacon.c Thu Feb 28 13:57:29 2002
+++ drivers/video/vgacon.c Wed Apr 3 08:13:44 2002
@@ -86,6 +86,7 @@
static void vgacon_deinit(struct vc_data *c);
static void vgacon_cursor(struct vc_data *c, int mode);
static int vgacon_switch(struct vc_data *c);
+static void vgacon_border(struct vc_data *c);
static int vgacon_blank(struct vc_data *c, int blank);
static int vgacon_font_op(struct vc_data *c, struct console_font_op *op);
static int vgacon_set_palette(struct vc_data *c, unsigned char *table);
@@ -470,6 +471,22 @@
}
}

+static void vgacon_border(struct vc_data *c)
+{
+ unsigned long flags;
+ unsigned char color = c->vc_border & 0x0f;
+
+ if (c->vc_can_do_color == 0)
+ return;
+
+ spin_lock_irqsave(&vga_lock, flags);
+ inb_p(0x3da); /* clear flipflop */
+ outb_p(0x11, 0x3c0); /* index overscan color reg */
+ outb_p(color, 0x3c0); /* load color value */
+ outb_p(0x20, 0x3c0); /* allow display memory */
+ spin_unlock_irqrestore(&vga_lock, flags);
+}
+
static int vgacon_switch(struct vc_data *c)
{
/*
@@ -1042,6 +1059,7 @@
con_scroll: vgacon_scroll,
con_bmove: DUMMY,
con_switch: vgacon_switch,
+ con_border: vgacon_border,
con_blank: vgacon_blank,
con_font_op: vgacon_font_op,
con_set_palette: vgacon_set_palette,
--- ../linux/drivers/char/console_macros.h Thu Sep 17 09:35:03 1998
+++ drivers/char/console_macros.h Wed Apr 3 07:18:43 2002
@@ -41,6 +41,7 @@
#define color (vc_cons[currcons].d->vc_color)
#define s_color (vc_cons[currcons].d->vc_s_color)
#define def_color (vc_cons[currcons].d->vc_def_color)
+#define border (vc_cons[currcons].d->vc_border)
#define foreground (color & 0x0f)
#define background (color & 0xf0)
#define charset (vc_cons[currcons].d->vc_charset)

-----------------8<---------------8<-----------8<-------------------
/*
* set VGA border colour.
*
* 0 -> 7 are blk, blu, grn, cyn, red, mag, yel, wht.
* 8 -> 15 are brighter versions (bright version of blk = grey).
*
*/

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <asm/io.h>

/* #include <linux/kd.h> */
#define PIO_BORDER 0x4B73
#define GIO_BORDER 0x4B74

int main(int argc, char** argv)
{
unsigned char colour, oldcolour;
int i;

if (argc != 2) {
fprintf(stderr,"Usage %s <colour_number>\n", argv[0]);
exit(EINVAL);
}

colour = atoi(argv[1]) & 0xf;

i = ioctl(0, GIO_BORDER, &oldcolour);
if (i != 0) {
perror("ioctl(GIO_BORDER)");
exit(errno);
}
printf("Old colour was %d\n", oldcolour);

i = ioctl(0, PIO_BORDER, &colour);
if (i != 0) {
perror("ioctl(PIO_BORDER)");
exit(errno);
}

return 0;
}

2002-04-03 22:52:00

by Andries E. Brouwer

[permalink] [raw]
Subject: Re: [PATCH] omission in video driver

: Heh, you mean "here is the hardware information, please make a patch".
: But your choice of red makes it truly a "bleeding edge" kernel :)

: The fact that we have been using linux for ~ 10 yrs and nobody has
: complained about the lack of this function yet says something...

: Anyway, have a look at this and see if it is what you had in mind.
: I figured it would be sensible to have a per VC colour

Yes, bleeding edge it was.

Adding something like this is allowed only on April 1st.

[But other systems have it. I find that both FreeBSD and UnixWare
have a KDSBORDER ioctl.]

Yes, your patch sounds more or less OK, but more less than more,
since I think that this should be treated completely parallel
to the palette stuff. And that works as follows:
There are ioctls and escape sequences. Escape sequences set
the palette per-VC. Upon reset the palette is reset to a default.
The default is set by ioctl. (And at the moment the ioctl sets
the default, it is also applied to the actual screen.)

[Not that I like this construction so much, but for uniformity..]
[In fact the author of the palette patch did not know the standard
for escape sequences, but nobody stopped him.]

Andries

2002-04-04 13:13:33

by Andries E. Brouwer

[permalink] [raw]
Subject: Re: [PATCH] omission in video driver

> if you think a linux KDSBORDER is worthwhile

Maybe mostly fun.

> Ok, so if we feed the above four lines through s/palette/border/g
> then we have an acceptable API?

Yes.

>> [In fact the author of the palette patch did not know the standard
>> for escape sequences, but nobody stopped him.]

> Alas, I too don't know what would be the standard/ANSI escape
> sequences for setting border colours

I meant it differently.

Escape sequences have a certain structure described
in various standards, like ISO 6429 (ECMA 48).
That is useful, it enables applications to parse input
into text and escape sequences without knowing of all
escape sequences precisely what they are supposed to do.

For example, for security one might want to have a filter
that removes the escape sequences (or maybe only the
unrecognized escape sequences) from text written to the
terminal.

Attempt to summarize very briefly:
One has
- single byte codes in 0x00-0x1f, like CR, LF, FF, ESC, BEL, etc.
- single byte codes in 0x80-0x9f, also representable as
ESC followed by a single byte code in 0x40-0x5f.
For example, CSI can be 0x9b or ESC [.
- two byte sequences of the form ESC followed by a byte in 0x60-0x7e.
- sequences that start with CSI, then zero or more parameter bytes
in 0x30-0x3f, then zero or more intermediate bytes in 0x20-0x2f,
then one final byte in 0x40-0x7e.
For example, a typical sequence might be ESC [ rr ; cc H
where rr and cc are sequences of decimal digits, and this
sequence moves the cursor to row rr and column cc.
- finally there sequences that start with an opening delimiter
(e.g. ESC _ or ESC P or ESC ] or ESC ^ or ESC X) and end
with a string terminator (0x9c or ESC \).

The palette setting sequence that Linux uses is
ESC ] P nrrggbb. There is no string terminator here.

So, the structure of the sequence is wrong.
The choice of sequence, probably random, with P for palette,
is also wrong, SGR (set graphics rendition) or DCS (device
control string) would have been more logical choices.

Andries