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