[comp.unix.i386] AT&T V/386 Console Graphics Prog Example

rhc@nsscb.UUCP (Rick Calder) (11/20/89)

/*
		This is an example of how to program graphics on a console
	virtual terminal screen.  It is written for an AT&T VDC600 VGA card,
	at 800x600, but can easily be modified for others supported by the
	compiler.  See '/usr/include/sys/kd.h'.
		It will first open an available virtual terminal, set the
	graphic mode, and then display the graphic area ( 25 ints x 600 lines).
	Program the appropriate bytes of the graphic area to correspond to
	the screen pixels, one bit per pixel.
		You may put this program in the background to free up the
	console, and then use the <ALT-SysReq><Fx> to bounce back and forth.
	Use the <DEL> to close the graphic.  After a bounce out and back, no
	input will be read until the <BEEP>.  Why ?  Let me know if you
	figure it out !  Really, I've no idea.

		See the manpage, display(7)
	Warnings:
		Although it is possible to write character sequences which
	set arbitrary bits on the screen in any of the three graphic modes,
	this mode of operation is not currently supported.

		Rick Calder, AT&T National Systems Support Center
		      [att!]rick!rick     rick@rick.att.com
				attmail!rcalder

--------------------------------  cut here ------------------------------------
*/
/* #disclaimer: per the manpage, display(7), this code is not supported by
	AT&T.  Use at your own risk, distribute freely, please leave in my
	authorship info.
		Rick Calder [att!]rick!rick rick@rick.att.com attmail!rcalder
 			programming help : research!debra research!shadow!dhn

	change the following for other video modes:
		VGASCREEN_SIZE	(800 * 600)		 total pixels
		SCREEN		((800/8) * 600)		 bytes per line
		LINES		600
		COLS		((800 / 8) / 4)		 ints per line
	in acquiredisplay():
		ioctl(0, SW_VDC800x600E, 0);	 AT&T VDC600 video card
	in releasedisplay():
		ioctl(0, SW_VGAC80x25, 0);	 any VGA card, text mode
*/

#include <fcntl.h>
#include <memory.h>
#include <stdio.h>
#include <sys/signal.h>
#include <sys/types.h>
#include <sys/at_ansi.h>
#include <sys/kd.h>
#include <sys/vt.h>

#define ALIGN_TO_4K(size)	(((size) + 4095) & ~4095)
#define VGAWINDOW_SIZE		0x10000			/* 65536, 64K */
#define VGASCREEN_ADDR		0xA0000			/* others at 0xB0000 */
#define VGASCREEN_SIZE		(800 * 600)
#define SCREEN			((800/8) * 600)		/* bytes per line */
#define LINES			600
#define COLS			((800 / 8) / 4)		/* ints per line */

struct	kd_memloc memloc;
char	*dp;
int	*pad[LINES][COLS];
void	scribble(), initmem(),
	acquiredisplay(), releasedisplay();

main(argc,argv)
int argc;
char **argv;
{

	int a;
	long vt;
	char devname[15];
	struct vt_mode vtmode;

		/* VT_OPENQRY on stderr allows prog to be put in background */
	if ( ioctl(2,VT_OPENQRY,&vt) == -1 ) {
		perror("VT_OPENQRY failed");
		exit(-1);
		}
	close(0); close(1); close(2);
	setpgrp();

	sprintf(devname,"/dev/vt0%ld", vt);
	a = open(devname,O_RDWR,NULL);
	if ( a == -1 ) {
		perror("vtopen failed");
		exit(-1);
		}
	dup(a); dup(a);

	if ( ioctl(0,VT_ACTIVATE,vt) == -1 ) {
		perror("VT_ACTIVATE failed");
		exit(-1);
		}
	sigset(SIGINT,exit);

	vtmode.mode = VT_PROCESS;  /* process controls console switching */
	vtmode.waitv = 1;          /* no writes on inactive consoles */
	vtmode.relsig = SIGUSR1;   /* received on hot-key for other console */
	vtmode.acqsig = SIGUSR1;   /* received on hot-key to this console */
	vtmode.frsig = SIGUSR2;    /* not used, for forced release of display */
	sigset(SIGUSR2,SIG_IGN);   /* prevents 'User signal 2' message */
	ioctl(0,VT_SETMODE, &vtmode);

	**pad = (int *) malloc(SCREEN);
	memset(pad,'\0',SCREEN);
	initmem();
	scribble();
	acquiredisplay();	/* initial set up */

	while ( 1 );
}

void
scribble()
{
	int x, y;

	for ( y = 0; y < LINES; y++ )
	for ( x = 0; x < COLS; x++ ) {
		pad[y][x] = (int *) 0xFF00FF00;
		x += 2;
	}
}

void
acquiredisplay()
{
	ioctl(0, SW_VDC800x600E, 0);		/* AT&T VDC600 video card */
	sleep(1);				/* settling time */
	ioctl(0, KDMAPDISP, &memloc);
	memcpy(dp, pad, SCREEN);		/* need to refresh screen */
	sigset(SIGUSR1, releasedisplay);	/* set for next signal */
}

void
releasedisplay()
{
	ioctl(0, KDUNMAPDISP, 0);       	/* unmap from user memory */
	sleep(1);				/* settling time */
	ioctl(0, SW_VGAC80x25, 0);		/* any VGA card, text mode */
	ioctl(0, VT_RELDISP, 1);        	/* results in console switch */
	sigset(SIGUSR1, acquiredisplay);	/* set for next signal */
}

void
initmem()
{
		/* get a virtual address that is page aligned */
	dp = (char *) malloc(ALIGN_TO_4K(VGAWINDOW_SIZE + 4096));
	dp = (char *) ALIGN_TO_4K ((unsigned long) dp);

	memloc.physaddr = (caddr_t) VGASCREEN_ADDR;
	memloc.vaddr = dp;
	memloc.length = ALIGN_TO_4K (VGAWINDOW_SIZE);
  	memloc.ioflg = 1;
}
-- 
		Rick Calder, AT&T National Systems Support Center
		      [att!]rick!rick     rick@rick.att.com
				attmail!rcalder

kdg@nirvo.uucp (Kurt Gollhardt) (12/06/89)

In article <1078@nsscb.UUCP> rhc@nsscb.UUCP (Rick Calder) writes a very nice
sample SYSV/386 console graphics program, with the following plaint:
>
>		You may put this program in the background to free up the
>	console, and then use the <ALT-SysReq><Fx> to bounce back and forth.
>	Use the <DEL> to close the graphic.  After a bounce out and back, no
>	input will be read until the <BEEP>.  Why ?  Let me know if you
>	figure it out !  Really, I've no idea.
>

You need to add the following line to the end of your acquiredisplay()
routine:

	ioctl(0, VT_RELDISP, VT_ACKACQ);

This tells the driver that you've finished redrawing the screen and the
acquire process is complete.

-- 
Kurt Gollhardt                      \   Nirvonics, Inc. -- Plainfield, NJ
Kurt.Gollhardt@nirvo.uucp           /\     Software Design and Consulting
...!rutgers!nirvo!Kurt.Gollhardt   /  \
     "It's all about people; not you and me or him and her, but *us*."