[comp.sys.ibm.pc.rt] ACG Display question & VRM sample program

buck@siswat.UUCP (A. Lester Buck) (04/26/89)

I need to do some VRM programming, so I was writing a VRM printf()
routine that prints on the console from the bowels of VRM.
As far as I can tell, the entire virtual terminal system is
inaccessible from _within_ VRM (it does not support receipt
of general queue elements), so I am just blasting away at the
bare hardware to get my debugging information on the screen.
(The VRM debugger has its uses, but I need a more dynamic
tool.  Another VRM programmer I talked to at IBM did
his own printf() for the monochrome display - why does everyone
have to reimplement this themselves?)

I got a basic varargs printf() from someone on the net, found
an 8x14 EGA font, and wrote a vrmputc() tty-mode routine.  I have gotten
this to work, but only by kludging a bit, and I was wondering if
anyone, AIX or AOS, knows the tricks of the Advanced Color
Graphics Display Adapter.

At the end of this posting, I include a complete, but empty,
piece of code that plugs into VRM.  This is the smallest piece
I have gotten to work so far; if you know how to make it smaller,
please speak up.  This should install directly into AIX, with
"vrmconfig -{a,d} ydev0".  At the -a call, the VRM debugger will
start at the trap instruction, type "g<return>" and AIX comes back.
With a simple makefile and some shell scripts to run vrmconfig, the
debug cycle time is quite short (one of the very nice points
about VRM that I hope is not going away in the new version).

All my information about the ACGD comes from the (rather sparse)
documentation in the Hardware Technical Reference manual.
My main question about the ACGD Adapter is that I can't get the
auto-increment facility to write the LSB of the 16 bit transfer,
at least in a running VRM program.  It works just fine if I
do it by hand from the debugger.  I.e., if I perform the
following sequence in the debugger:

>sth f0000150 c030		<Y increment, increasing, system write mode>
>stc f0000154 1f		<select all planes, fg/bg write through>
>stc f0000156 ab		<bg=color A, fg=color B>
>stc f0000158 000a		<color A all black>
>stc f0000158 3f0b		<color B bright white (nice on green)>
>stc f0000152 ffff		<data masks 1 & 2 = 0xFF>
>stc f4d3a000 ff0f		<write bytes 0xFF, then 0x0F, to bitmap>

then just about here on the debugger screen appear the pixels:

********
    ****

which is correct, since the second byte  is incremented by one bit row.
If the c030 is changed to c830 (X increment), then the pattern that 
appears is:

********    ****

This all makes sense.

BUT, if I try this in the program (even with huge delays between
each write) with the following brute-force code (so I know that
it is a halfword/char being written):

*((unsigned short *) f0000150) = 0xC030;
*((unsigned char  *) f0000154) = 0x1F;
*((unsigned char  *) f0000156) = 0xAB;
*((unsigned short *) f0000158) = 0x000A;
*((unsigned short *) f0000158) = 0x3F0B;
*((unsigned short *) f0000152) = 0xFFFF;
*((unsigned short *) f4d3a000) = 0xFF0F;

only the first byte's pixels appear on the screen (at the correct place):


********


Really weird, if I change the data halfword to 0xFF80, I get the pattern


********
*

(only the first pixel of the incremented byte is ever written).



Does anyone know what might be causing this?  For now, I just
write one byte at a time and it works fine, but the capability
is there to write twice as fast - if I could just figure it out.
[If I change the mode to X increment inside the VRM debugger,
the whole screen loses every other scan line, and scrolling is
messed up, so I know it can be done.]
And if anyone knows what the RAS Status Register bit 7
(1==Enable load address) means, I'd appreciate a pointer.  (It is
always 1 in my code and while in the VRM debugger.)
Any explanation of what the logic unit function control is really
doing with the data masks would be great, too.
[My scrolling function doesn't use the hardware support much,
because I haven't figured out how to set up the logic unit operations.]


Thanks for any help!


A. Lester Buck		...!texbell!moray!siswat!buck

_______________________________________________________________

This is an (approximately) minimal set of programs and stanzas
to load a piece of C code into the VRM.  It comes in appearing
to be a device driver.  The only odd thing about this code is
that our lp queue dies once this is vrmconfig'ed.  Vrmconfig
may be doing extra stuff with the ddi information that conflicts
with the printer.  I guess I'll have to track that down someday.
Rebooting brings the printer back when necessary, and I think
vrmconfig'ing the lp0 device again would clean it up, too.
Also, I don't even look at what "devices" thinks of these
stanzas, and for the time being I don't care, since I add
this all by hand.

Most of this stuff is adapted from the red book "Writing a Device Driver
for the IBM 6150" and the /usr/lpp/examples/{aix,vrm}/... code that
comes with the Device Driver Development Guide.

Have fun!

%%%%%%%%%%%%%
vydev.c		(compile with vcc, put in /etc/vrmdd/vydev)
%%%%%%%%%%%%%
#include <vrm.h>

#define BREAK_PT        asm("tgte 1,1")	/* Force trap to debugger */
 
main(op_type, op_data, op_len)		/* Common handler interface  */
unsigned op_type;			/* Operation type            */
char     *op_data;			/* Operation data            */
int      op_len;			/* Length of operation data  */
{
    BREAK_PT;	/* optional, need VRM debugger loaded or crashes */
    /* when you hit this breakpoint, you know vrmconfig worked */

    /* insert whatever code here */

    return(0);
}
%%%%%%%%%%%%%%%%%%
ydev.master (stanzas for /etc/master)
%%%%%%%%%%%%%%%%%%
uydev:
	major = < pick 20<unique<32 >
	prefix = yd
	routines = init
	vdriver = vydev
	config = vrcmain

vydev:
	iocn = 2567 <pick unique>
	code = /etc/vrmdd/vydev
	ctype = vdrvr
%%%%%%%%%%%%%%%%%%%
ydev.predef (stanza for /etc/predefined)
%%%%%%%%%%%%%%%%%%%
ydev:
* my very own (pseudo-)device
	minor = c0
	aflag = false
* adapter description
	noduplicate = true
	shared = false
	switchable = false
	noipl = true
	vint = 4
	name = ydev
	crname = false
	nname = ydev
	dname = ydev
	dtype = OEM
* OEM devices
	driver = uydev
	iodn = 6987 <just make this unique>
	noddi = false
	noshow = false
	file = /etc/ddi/ydev
	use = dydev
	kaf_file = /etc/ddi/ydev
	kaf_use = kydev
%%%%%%%%%%%%%%%%%%%%%%
ydev.system (stanza for /etc/system)
%%%%%%%%%%%%%%%%%%%%%%
ydev0:
* my very own (pseudo-)device
	minor = c0
	aflag = false
* adapter description
	noduplicate = true
	shared = false
	switchable = false
	noipl = true
	vint = 4
	name = ydev
	crname = false
	nname = ydev
	dname = ydev
	dtype = OEM
* OEM devices
	driver = uydev
	iodn = 6987	<just make this unique>
	noddi = false
	noshow = false
	file = /etc/ddi/ydev
	use = dydev
	kaf_file = /etc/ddi/ydev
	kaf_use = kydev
%%%%%%%%%%%%%%%%%%%%%%%%%
/etc/ddi/ydev	
(this can probably be made smaller, but I wasn't able to get
 "noddi = true"  to work with vrmconfig)
%%%%%%%%%%%%%%%%%%%%%%%%%
default:
	smf_file = /etc/ddi/ydev
	sysadd = none
	sysdel = none


dydev:
	nr = true
	ddbw = 8
	noi = 1
	sn = 0
	at = 99
	pn = 0
	biopa = 03bc
	iopar = 0
	dmas = false
	noi = 0
	ei = false
	ei1 = false
	si1 = false
	rl = 0

kydev:
	add = u/n
	delete = u/n
	startup = u/n
	shutdown = u/n
	dsize = 500
	vsize = 500
	usize = 500
	nsmf = none
	usmf = none
	vsmf = none
%%%%%%%%%%%%%%%%%%%%%%%%%%
aydev.c		(cc and archive into /usr/sys/lib2)
%%%%%%%%%%%%%%%%%%%%%%%%%%
/*
 * ydev driver shell
 * for now, just implements init to do attach
 * with these stanzas, init is not activated at all
 */
#include <sys/types.h>
#include <sys/param.h>
#include <sys/sysmacros.h>
#include <sys/user.h>
#include <sys/errno.h>

#define YDEVlevel	4
#define YDEVMAGIC	1692

static int	ydevlevel = 0;
static int	pathid = 0;

ydintr(pmagic)
int	*pmagic;
{
    printf("ydintr: called (!!!###$$$), magic = %d\n", *pmagic);
    return;
}

ydinit(dev, iodn, ilev, ddilen, ddiptr)
dev_t dev;
unsigned short	iodn;
short		ilev;
ushort		ddilen;
int ddiptr;
{
    int		rv;

    printf("ydinit: called\n");

    /*
     * Attach device, get path id.
     */

    ydevlevel = vec_init(YDEVlevel, ydintr, YDEVMAGIC);

    rv = S_XADEV((ydevlevel<<16) | iodn, 5, &pathid);
    if (rv != 0  &&  rv != 4) {
	errprintf("dopen: ADEV error %d on iodn %d\n", rv, iodn);
	u.u_error = ENXIO;
	return;
    }
    return(0);
}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

-- 
A. Lester Buck		...!texbell!moray!siswat!buck