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