Return bytes starting from the current (row, column) in typwriter
order until you have met the request or there are no more bytes on the
screen. Successive reads should read from successive locations.
The column and row are to be kept by file descriptor, not by process ID
or globally.
Point | Task |
3 | It's a module |
3 | Claims a major number |
5 | Can tell if there is a video card |
3 | Can tell where video ram is |
3 | Can tell the current location of the displayed memory |
2 | Can clear the screen on startup |
4 | Can clear the screen on <ESC>c |
6 | Can clear the current line on <ESC>l |
4 | Writing to the device changes the screen |
4 | Device keeps track of (row,column) for writes. Successive writes write to successive locations |
4 | Screen scrolls |
4 | Reading gives data from the screen |
4 | Device keeps track of (row,column) for reads. Successive reads read from successive locations |
8 | Row and column are kept by file descriptor, not globally or some other way. |
1-6 | The Status file (one point for each item) |
-4 | I can crash the module |
-6 | I can crash the kernel |
3 | Done before the due date |
-3 | Done more than one day after the due date |
6 | Implements the <ESC>g sequence |
4 | Implements the <ESC>r sequence |
The Linux Kernel Code contains these lines
You must always map a virtual address to a physical address. To change location 1234 in ram to a 99, use this:static unsigned long vga_vram_base = 0xa0000; static unsigned long vga_vram_end = 0xbffff;
unsigned long pos = 1234; char *ptr = (char *)(__va(pos)); *ptr = 99; -- OR -- *((char *)(__va(1234))) = 99;
The kernel contains the following code, lifted from drivers/video/vgacon.c,modified by me /* * Find out if there is a graphics card present. * Are there smarter methods around? */ volatile u16 *p = (volatile u16 *)__va(vga_vram_base); u16 saved1 = scr_readw(p); u16 saved2 = scr_readw(p + 1); scr_writew(0xAA55, p); scr_writew(0x55AA, p + 1); if (scr_readw(p) != 0xAA55 || scr_readw(p + 1) != 0x55AA) { scr_writew(saved1, p); scr_writew(saved2, p + 1); return 0; } scr_writew(0x55AA, p); scr_writew(0xAA55, p + 1); if (scr_readw(p) != 0x55AA || scr_readw(p + 1) != 0xAA55) { scr_writew(saved1, p); scr_writew(saved2, p + 1); return 0; } scr_writew(saved1, p); scr_writew(saved2, p + 1); return 1;Stephan has some code that says
static void put_char( char color, char ch )And the kernel has some code that says
{
/* _UGLY_ hack to set vga text window to start of vram
*
* Check /usr/src/linux/drivers/video/vgacon.c lines:
* 149: void write_vga( int, int )
* 351: void vga_set_mem_top( struct vc_data* )
* 928: int vgacon_scrolldelta( struct vc_data*, int )
*
* These functions demonstrate the proper way to do it. ;)
*/
outw( 12, 0x3d4 ); /* FUGLY */
outw( 13, 0x3d4 ); /* HACK! */
static inline void vga_set_mem_top(struct vc_data *c)Or
{
write_vga(12, (c->vc_visible_origin-vga_vram_base)/2);
}
To save where you _were_:int a;
outb( 12, 0x3d4 );
a = inb( 0x3d5 );
outb( 13, 0x3d4 );
a = (a<<8) | (inb( 0x3d5 ) & 0xff);'a' now holds the position we were at, and:
outw( 12 + (a&0xff00), 0x3d4 );
outw( 13 + ((a&0x00ff)<<8), 0x3d4 );will restore that position.
If you didn't already know this... thank Michael Abrash for writing his
'Zen of Graphics Programming' book... a great read anyday!Oh, 0x3d4 is CRT Control Index Register, 0x3d5 is CRT Control Data
register, 12 is register for HIGH byte of display position, and 13 is
register for LOW byte of display position. :)