rico@oscvax.UUCP (10/28/87)
In the spirit of previous GURU oriented postings, here's another one that I hope will help someone out there. It's a printer driver for the toshiba 3 in one printer in its Qume (best) mode. I hadn't ever seen the source for a printer driver posted before so hopefully this will make a good example for everyone out there. It's implemented in Aztec C + assembler but porting it to Lattice + assembler should be simple. The rendering function is a *minimal* graphics output generating function, no attempt was made to optimize out unecessary print passes etc. But this could be easily added. This code was developed by me here at the Ontario Science Centre as part of my work (i.e. we needed this driver) and I've been authorized to release it to the public domain. You may slice dice or whatever. Needless to say there's no warranty etc. etc. All usual disclaimers apply. Noteworthy items: - Aztec C doesn't preserve a6 across function calls. This is required in the printer driver code so special inline assembler was added to the render() and dospecial() functions. Look out for this Aztec users! - The toshiba is actually capable of printing 24 pixel rows at 360 dots/inch in a print pass however the printer.device didn't seem to cope with this very well. With these numbers in the printertag the printer device would simply call "case 5" (pre initialization) of the render function and then not send any other data. No fuss, no muss, no data. When I reduced the 360 to the next best print mode (180) all was well. Sigh. If anyone can shed some light on this I'd appreciate it. - I've stolen the debugging code from the dos handler that Matt Dillon recently posted and used this in my driver for debugging output. You folks out there should think about using it to get debugging output where you never dreamed it was possible. The debugging package is a really terrific little subsytem. Thanks Matt! - I've also stolen the flush program from the dos handler, you can use this for devoloping printer drivers as it will cause your Expunge code to be run. The next time you use the printer device your code will be re-loaded, hence you can make recompile etc. and test your new driver without resorting to preferences trickery. Not to mention testing your Expunge code... - Speaking of Expunge code, mine doesn't work when the debugging is enabled. Works perfectly in normal use though... oh well :-( If I ever figure it out I'll post the fix. Meanwhile if any of you figure it out... - If you're writing a printer driver do whatever it takes but get Carolyn's Cmd program. This lets you easily "see" your driver's output which is a must for testing. I used this for my debugging output before I installed Matt's code. If you're checking the output by eye then it sometimes helps if there's readable diagnostics intermixed. Thanks Carolyn! - To compile with debugging enabled just supply the -DDEBUG flag to "cc" and -EDEBUG to "as". Lattice people will have to use whatever flags it is they use to predefine symbols in the compiler/assembler. Enough babbling... here's the source + binary (uuencoded + shar'd) : -------cut here-----------cut here------------cut here-------- : This is a shar archive. Extract with sh, not csh. : Extraction terminated by end of archive message. : The rest of this file will extract: : Makefile data.c debug.c dospecial.c flush.c flush.uu init.asm printertag.asm pwait.asm render.c toshiba.uu echo x - Makefile sed 's/^X//' > Makefile << '/*EOF' X.asm.o: X as -C -D $*.asm X X.c.o: X cc +pB $*.c X XOBJS = printertag.o init.o data.o dospecial.o render.o pwait.o debug.o X Xtoshiba: $(OBJS) X ln -o toshiba $(OBJS) -lcl32 /*EOF echo x - data.c sed 's/^X//' > data.c << '/*EOF' X X/* toshiba p351c command data table */ X Xchar *CommandTable[] = { X "\x1b\x1a\x49", /* reset RIS */ X "\x1b\x00", /* initialize */ X "\x0a", /* line feed IND */ X "\x0d\x0a", /* CRLF NEL */ X "\x0d\x1a", /* reverse LF RI */ X X "\x1b\x14\x1bJ\x1bM", /* normal attributes SGR 0 */ X "\x1b\x12", /* italics on SGR 3 */ X "\x1b\x14", /* italics off SGR 23 */ X "\x1bI", /* underline on SGR 4 */ X "\x1bJ", /* underline off SGR 24 */ X "\x1bK\x02", /* boldface on SGR 1 */ X "\x1bM", /* boldface off SGR 22 */ X "\xff", /* set foreground colour */ X "\xff", /* set background colour */ X X "\x1b*0\x1b]\x1b\x22", /* normal font SHORP */ X "\x1b*1", /* elite on SHORP */ X "\x1b*0", /* elite off SHORP */ X "\x1b[", /* condensed on SHORP */ X "\x1b]", /* condensed off SHORP */ X "\x1b!", /* elongated on SHORP */ X "\x1b\x22", /* elongated off SHORP */ X X "\x1bQ", /* shadow print on DEN6 */ X "\x1bM", /* shadow print on DEN5 */ X "\x1bK\x02", /* double strike on DEN4 */ X "\x1bM", /* double strike off DEN3 */ X "\x1b*2", /* NLQ on DEN2 */ X "\x1b*0", /* NLQ off DEN1 */ X X "\x1bD", /* superscript on */ X "\x1bU", /* superscript off */ X "\x1bU", /* subscript off */ X "\x1bD", /* subscript on */ X "\xff", /* normalize */ X X "\xff", /* US Char Set */ X "\xff", /* French Char Set */ X "\xff", /* German Char Set */ X "\xff", /* UK Char Set */ X "\xff", /* Danish I Char Set */ X "\xff", /* Swedish Char Set */ X "\xff", /* Italian Char Set */ X "\xff", /* Spanish Char Set */ X "\xff", /* Japanese Char Set */ X "\xff", /* Norweign Char Set */ X "\xff", /* Danish II Char Set */ X X "\x1b$", /* Prop. Spacing on PROP */ X "\x1b%", /* Prop. Spacing off PROP */ X "\xff", /* Prop. Clear PROP */ X "\xff", /* Prop. Offset TSS */ X "\xff", /* Auto right justify JFY5 */ X "\xff", /* Auto left justify JFY7 */ X "\xff", /* Auto full justify JFY6 */ X "\xff", /* justify/centre off */ X "\xff", /* place holder JFY3 */ X "\xff", /* Auto Centre on JFY2 */ X X "\x1b\x1e\x06", /* 1/8" line spacing VERP */ X "\x1b\x1e\x08", /* 1/6" line spacing VERP */ X "\xff", /* set form length SLPP */ X "\xff", /* skip perf on */ X "\xff", /* skip perf off */ X X "\x1b9", /* left margin set */ X "\x1b0", /* right margin set */ X "\x1b+", /* top margin set */ X "\x1b-", /* bottom margin set */ X "\xff", /* T & B margin set STBM */ X "\xff", /* L & R margin set SLRM */ X "\xff", /* Clear margins */ X X "\x1b1", /* Set Horizontal Tab HTS */ X "\xff", /* Set Vertical tab VTS */ X "\x1b8", /* Clr Horizontal Tab TBC 0 */ X "\x1b2", /* Clr All Horiz. Tabs TBC 3 */ X "\xff", /* Clr Vertical Tab TBC 1 */ X "\xff", /*. Clr All Vert. Tabs TBC 4 */ X "\x1b8", /* Clr All V & H Tabs */ X /* Set Default Tabs */ X "\x1b(08,16,24,32,40,48,56,64,72.", X "\xff", /* Extended Command */ X}; /*EOF echo x - debug.c sed 's/^X//' > debug.c << '/*EOF' X/* DEBUGGING-- This is Matt Dillon's debugger code, X * which is *real* handy when you're paranoid about what X * you can and can't do because of your task/process state X * X * It's even better than kprintf :-) X */ X X#include <exec/types.h> X#include <exec/nodes.h> X#include <exec/lists.h> X#include <exec/memory.h> X#include <devices/printer.h> X#include <devices/prtbase.h> X X#ifndef DEBUG X Xdbprintf() {} /* empty function declaration */ X X#else X X#define CTOB(x) (void *)(((long)(x))>>2) X Xstruct Task *FindTask(); Xstruct MsgPort *CreatePort(); Xstruct FileHandle *Open(); Xstruct Message *GetMsg(); X X Xstruct MsgPort *Dbport; /* owned by the debug process */ Xstruct MsgPort *Dback; /* owned by the DOS device driver */ Xshort DBDisable; Xstruct Message DummyMsg; X Xvoid dbstart() X{ X X DBDisable = 0; X Dbport = Dback = NULL; X X /* need DosBase and SysBase to use debugger */ X /* DEBUGGING */ X X dbinit(); /* to close off debugger call dbuninit() */ X} X X/* X * DEBUGGING CODE. You cannot make DOS library calls that access other X * devices from within a DOS device driver because they use the same X * message port as the driver. If you need to make such calls you must X * create a port and construct the DOS messages yourself. I do not X * do this. To get debugging info out another PROCESS is created to which X * debugging messages can be sent. X * X * You want the priority of the debug process to be larger than the X * priority of your DOS handler. This is so if your DOS handler crashes X * you have a better idea of where it died from the debugging messages X * (remember that the two processes are asyncronous from each other). X */ X Xextern void debugproc(); X Xdbinit() X{ X struct Task *task = FindTask(NULL); X X Dback = CreatePort(NULL,NULL); X CreateProc("DEV_DB", task->tc_Node.ln_Pri+1, CTOB(debugproc), 4096); X WaitPort(Dback); /* handshake startup */ X GetMsg(Dback); /* remove dummy msg */ X dbprintf("Debugger running V1.00\n"); X} X Xdbuninit() X{ X struct Message killmsg; X X if (Dbport) { X killmsg.mn_Length = 0; /* 0 means die */ X PutMsg(Dbport,&killmsg); X WaitPort(Dback); /* He's dead jim! */ X GetMsg(Dback); X DeletePort(Dback); X X /* X * Since the debug process is running at a greater priority, I X * am pretty sure that it is guarenteed to be completely removed X * before this task gets control again. Still, it doesn't hurt... X */ X X /* Delay(50); */ /* ensure he's dead */ X } X} X Xdbprintf(a,b,c,d,e,f,g,h,i,j) X{ X static char buf[256]; X struct Message *msg; X X if (Dbport && !DBDisable) { X sprintf(buf,a,b,c,d,e,f,g,h,i,j); X msg = AllocMem(sizeof(struct Message)+strlen(buf)+1, X MEMF_PUBLIC|MEMF_CLEAR); X msg->mn_Length = strlen(buf)+1; /* Length NEVER 0 */ X strcpy(msg+1,buf); X PutMsg(Dbport,msg); X } X} X X/* X * BTW, the DOS library used by debugmain() was actually openned by X * the _Init routine. Note: DummyMsg cannot be on debugmain()'s stack X * since debugmain() goes away on the final handshake. X */ X Xdebugmain() X{ X X struct Message *msg; X short len; X void *fh; X X Dbport = CreatePort(NULL,NULL); X fh = Open("con:0/0/640/100/debugwindow", 1006); X PutMsg(Dback, &DummyMsg); X for (;;) { X WaitPort(Dbport); X msg = GetMsg(Dbport); X len = msg->mn_Length; X if (len == 0) X break; X --len; /* Fix length up */ X Write(fh, msg+1, len); X FreeMem(msg,sizeof(struct Message)+len+1); X } X Close(fh); X DeletePort(Dbport); X PutMsg(Dback,&DummyMsg); /* Kill handshake */ X} X X/* X * The assembly tag for the DOS process: CNOP causes alignment problems X * with the Aztec assembler for some reason. I assume then, that the X * alignment is unknown. Since the BCPL conversion basically zero's the X * lower two bits of the address the actual code may start anywhere X * within 8 bytes of address (remember the first longword is a segment X * pointer and skipped). Sigh.... (see CreatProc() above). X */ X X#asm X public _debugproc X public _debugmain X X cseg X_debugproc: X nop X nop X nop X nop X nop X movem.l D2-D7/A2-A6,-(sp) X jsr _debugmain X movem.l (sp)+,D2-D7/A2-A6 X rts X#endasm X X#endif /*EOF echo x - dospecial.c sed 's/^X//' > dospecial.c << '/*EOF' X/* toshiba special commands */ X X#include <exec/types.h> X#include <devices/printer.h> X#include <devices/prtbase.h> X Xextern struct PrinterData *PD; Xextern struct PrinterExtendedData *PED; X XDoSpecial(command,outputBuffer,vline,currentVMI,crlfFlag,Parms) Xregister UWORD *command; Xregister char *outputBuffer; Xregister BYTE *vline; Xregister BYTE *currentVMI; Xregister BYTE *crlfFlag; Xregister UBYTE *Parms; X{ X /* Aztec doesn't preserve a6... we need this in a printer driver */ X#asm X move.l a6,-(sp) X#endasm X int result; X X dbprintf("DoSpecial:"); X X switch (*command) { X X case aRIN: X /* start with initialization string */ X X strcpy(outputBuffer,"\x1b\x1aI"); X X /* set to ELITE mode on LETTER or ELITE spacing... */ X X if ( X (PD->pd_Preferences.PrintQuality == LETTER) || X (PD->pd_Preferences.PrintPitch == ELITE) X ) strcat(outputBuffer,"\x1b*1"); X X /* set to condensed mode if req'd */ X X if (PD->pd_Preferences.PrintPitch == FINE) X strcat(outputBuffer,"\x1b["); X X /* this might look backwards but it's not */ X /* the toshiba allows you to specify the spacing */ X /* in 48ths of an inch, 6/48 == 1/8, 8/48 == 1/6 */ X X if (PD->pd_Preferences.PrintSpacing == SIX_LPI) { X strcat(outputBuffer,"\x1b\x1e\x08"); /* 8 48ths */ X *currentVMI = 36; X dbprintf(" VMI=36"); X } X else { X strcat(outputBuffer,"\x1b\x1e\x06"); /* 6 48ths */ X *currentVMI = 27; X dbprintf(" VMI=27"); X } X dbprintf(" aRIN\n"); X result = strlen(outputBuffer); X break; X X X case aVERP0: X *currentVMI=27; X dbprintf(" VMI=27\n"); X break; X X case aVERP1: X *currentVMI=36; X dbprintf(" VMI=36\n"); X break; X X default: X dbprintf("req:%d\n",*command); X break; X } X#asm X move.l (sp)+,a6 X#endasm X return(result); X} /*EOF echo x - flush.c sed 's/^X//' > flush.c << '/*EOF' X#include <exec/memory.h> X X/* X * Allocate memory until we can't ... force the system to flush all X * non-active DOS devices, libraries, fonts, etc.... X */ X Xextern void *AllocMem(); X Xmain() X{ X char *ptr; X long bytes = 1 << 9; X X while (ptr = AllocMem(bytes, MEMF_PUBLIC)) { X FreeMem(ptr, bytes); X bytes <<= 1; X } X} X /*EOF echo x - flush.uu sed 's/^X//' > flush.uu << '/*EOF' Xbegin 644 flush XM #\P # ( (: 0 !( /I "&F!"3E7_ XM^"M\ " /_X2'@ 2\M__A.N0 ![A03RM __QG'"\M__@O+?_\3KD ?F XM4$\@+?_XXX K0/_X8,Y.74YU87Q#^0 1%^0 "UR68.,CP $6L(= B XMPE')__PCSP L> $(\X $2.> @ @N 0!*6<02_H "$ZN_^)@!D*G XM\U].<T/Z "1.KOYH(\ (9@PN/ #@ =.KO^48 9.N0 ,I03TYU9&]S XM+FQI8G)A<GD 2?D '_^3G5.50 2.<P($AY $ # Y ,'\ 8O $ZY XM 'OE!/(\ ,9AA"ITAY $ $ZY 'BE!/+GD 3G4@>0 Q" XM: $('D ,,7P 0 0(GD ,,WP 0 *('D (#D D*@ !%" XM(\ 0('D 0(+Q-04Y80J=.N0 !\Y83R1 2JH K&<X+RT #"\M @O XM"DZY "5D_O PC_ $ 4('D , &B $('D , &B * XM8%A(:@!<3KD @L6$](:@!<3KD ?^6$\CP !@@>0 !A*J D9Q0@ XM>0 !@B: D+Q%.N0 !UA83R\Y &"\*3KD 284$\C^0 !@ < XM3KD =F('D ,((!.N0 !X @>0 PA0 &9QI(> /M2'H .DZY ' XM<%!/('D ,(4 #"\Y '"\Y ($ZY E!/0J=.N0 !7183TS? XM! Q.74YU*@!.50 2.<\,"1M ! @;0 (("@ K.6 * @1" H !#E@"9 $!-( XM@$C T*T #%2 (\ D0J<O.0 "1.N0 ![Y03R/ *&8(3-\,/$Y= XM3G40$TB 2, O "!+4H@O""\Y *$ZY $/$_O Q(>@%P$!-(@$C T+D XM H+P!.N0 !(A03R\M PO"B\Y *$ZY $9$_O Q"N0 " F>0 XM "@D2Q 32(!(P"H L+P @9R"ZO EG&+J\ #&<0NKP -9PBZ XMO IF!%*+8,P,$P @;0 C@P3 ")F,E*+($M2BQ 02(!(P"H 9R @2E** XM$(6ZO ")F$ P3 ")F!%*+8 9"*O__8 )@TF!$($M2BQ 02(!(P"H 9S"Z XMO "!G*+J\ "6<@NKP ,9QBZO UG$+J\ "F<(($I2BA"% XM8,(@2E**0A!*A68"4XM2N0 "!@ /\Z0A)"IR Y (%* Y8 O $ZY ' XMOE!/(\ <9@I"N0 "!@ /ZL>@ F>0 "A@'B %Y8 @>0 !PABP@ XM+PM.N0 !6)83U* U\!2A;JY (&W:( 7E@"!Y '$*P" !@ /YJ( !, XM[P, 0@""(O Q@ A#95\G__&<&4D%@ D(84<G__$YU,#Q__V $,"\ #B!O XM 1*&&;\4T@B;P (4T 0V5?(__QG D(0("\ !$YU(&\ !" ((F\ "!#99OQ. XM=4Y5 !(YSXP)&T "$*G2'H I$ZY (#%!/(\ \9@A,WPQ\3EU.=2!M XM PB: D+RD !$ZY (6%A/* !G6DAZ 'T@1"\H #9.N0 "#I03R9 2H!G XM.$AX ^TO"TZY '<%!/+ !G)B &Y8 J "!%)6@ " "D)48 G$AX ^U(>@!$ XM3KD =P4$\E0 "@+P1.N0 "$I83R\Y /$ZY 'I%A/0KD \8 #_ XM<&EC;VXN;&EB<F%R>0!724Y$3U< *@ @;P $( A*&&;\D< @"%. 3G5.50 XM2.<P $JY 0&<(('D ! 3I O+0 (3KD 6@6$],WP ,3EU.=4Y5__Q( XMYS@ *VT "/_\2KD ,9S9X & ,+P1.N0 !L983U*$,#D 2,"X@&WH XM,#D P?P !B\ +SD ,3KD ?L4$]*N0 $1G""!Y 1$Z02KD XM L9PXO.0 "Q.N0 !ZI83TJY ,&<.+SD P3KD >J6$]*N0 XM #1G#B\Y -$ZY 'JEA/+'@ ! @N 0!*6<4+PU+^@ *3J[_XBI?8 9" XMI_-?3G-*N0 !AF.$JY *&<N+SD D+SD H3KD ?L4$\@.0 XM "!2@.6 +P O.0 !Q.N0 !^Q03V 43KD ?<+SD 83KD @>6$\@ XM+?_\+GD 3G5,WP <3EU.=4Y5 !(YSX@*"T "'(&( 1.N0 !R8D0-7Y XM #$J$;1 P.0 !(P+B ; 1*DF84(_P " .'#_3-\$?$Y=3G4P XM*@ $P'R &8*+Q).N0 !TI83T*2< !@WDCG< T <3 )@%(0\; 2$-"0]2# XM2$# P4A 0D#0@DS? Y.=2(O 0L>0 A.[O_<(B\ !"QY "$[N_X(L XM>0 A.[O_*3.\ !@ $+'D (3N[_XBQY "$[N_\1(YP$$3.\@@ , XM+'D $3J[_E$S?((!.=4[Y 'JB)O 0L>0 1.[OYB3OD >^3.\ XM P $+'D $3N[_.B)O 0L>0 1.[O[:+'D $3N[_?$[Y '[")O XM 0@+P (+'D $3N[_+B!O 0L>0 1.[OZ,+'D $(F\ !" O A. XM[OW8(F\ !"QY !$[N_H8@;P $+'D $3N[^@$SO P !"QY /$[N XM_Z @;P $+'D \3N[_IB!O 0L>0 #Q.[O^R /L !@ $ XM !( Q -H 7( %U !NH L !@ N K@ XM .8 #^ !5@ 7 &B !K@ =0 'D !]@ @0 (> " XM/ D8 *4 "P MP +P #X !!0 2L $T !.8 3Z XM %( !2X 4\ %D@ !;X 7F &# !B( 8X &? !I8 XM :@ &K !M@ <: 'I@ ![H ?H 5@ ( !. 9@ XM ' ": [@ 08 $. !& 20 $P !-@ 4( %( ! XM?@ 80 &0 !M@ ;P '( !W >P 'P !_ @H (F XM ", C8 *& "C@ IP *Z "U NH +Z # \8 XM /4 #Z _ /\ $" !"( 0N $M !38 5$ %?@ XM!88 6P %X !>X 7V %_@ !@8 84 &' !BH 8R & XM8 !F@ 9P &=@ !H0 :0 &I@ !K@ ;@ &_@ !U => XM ': !W@ >" 'E@ ![ ?& 'U !]X ?V (! " X XM @D (,@ "$( A0 (7@ /R #Z@ $ % #\@ X* ^L 2 #\D( X Xend /*EOF echo x - init.asm sed 's/^X//' > init.asm << '/*EOF' X* X* initialization stub for the toshiba printer driver X* X X INCLUDE "exec/types.i" X INCLUDE "exec/nodes.i" X INCLUDE "exec/lists.i" X INCLUDE "exec/memory.i" X INCLUDE "exec/ports.i" X INCLUDE "exec/libraries.i" X X INCLUDE "macros.i" X INCLUDE "devices/prtbase.i" X X XREF_EXE CloseLibrary X XREF_EXE OldOpenLibrary X XREF_EXE OpenLibrary X X XREF _AbsExecBase ;these are in the Aztec Library X XREF _SysBase ;and this X X XREF _PEDData X X ifd DEBUG X XREF _dbstart X XREF _dbuninit X XREF _dbprintf X XREF _PWait X endc X X XDEF _Init X XDEF _Expunge X XDEF _PrOpen X XDEF _PrClose X XDEF _PD X XDEF _PED X XDEF _DOSBase X XDEF _GfxBase X XDEF _IntuitionBase X X*------------------------------------------------------ X section printer,data X_PD dc.l 0 X_PED dc.l 0 X_DosBase dc.l 0 X_GfxBase dc.l 0 X_IntuitionBase dc.l 0 X X*------------------------------------------------------ X section printer,code X_Init X move.l 4(sp),_PD X X lea _PEDData(pc),a0 X move.l a0,_PED X move.l a6,-(a7) X move.l _AbsExecBase,a6 X move.l a6,_SysBase X X* open dos library X X lea DLName,a1 X moveq #1,d0 X callexe OpenLibrary X move.l d0,_DOSBase X beq initDLErr X X* open gfx libarary X X lea GLName,a1 X moveq #1,d0 X callexe OpenLibrary X move.l d0,_GfxBase X beq initGLErr X X* open intuition libarary X X lea ILName,a1 X moveq #1,d0 X callexe OpenLibrary X move.l d0,_IntuitionBase X beq initILErr X X ifd DEBUG X jsr _dbstart X endc X X moveq #0,d0 XpdiRts: X move.l (a7)+,a6 X rts X XinitPAErr: X move.l _IntuitionBase,a1 X LINKEXE CloseLibrary X XinitILErr: X move.l _GfxBase,a1 X LINKEXE CloseLibrary X XinitGLErr: X move.l _DOSBase,a1 X LINKEXE CloseLibrary X XinitDLErr: X moveq #-1,d0 X bra.s pdiRts X XILName: dc.b "intuition.library",0 XDLName: dc.b "dos.library",0 XGLName: dc.b "graphics.library",0 XDeathMsg: dc.b "I'm being rubbed out!",0 X ds.w 0 X X X X*------------------------------------------------------ X X_Expunge: X move.l a6,-(sp) X X ifd DEBUG X pea.l DeathMsg X jsr _dbprintf X addq.l #4,sp X pea 0 X pea 1 X jsr _PWait X addq.l #8,sp X jsr _dbuninit X endc X X move.l _SysBase,a6 X X move.l _IntuitionBase,a1 X callexe CloseLibrary X X move.l _GfxBase,a1 X callexe CloseLibrary X X move.l _DOSBase,a1 X callexe CloseLibrary X X move.l (sp)+,a6 X moveq #0,d0 X rts X X*------------------------------------------------------ X_PrOpen: X moveq #0,d0 X rts X X*------------------------------------------------------ X_PrClose: X moveq #0,d0 X rts /*EOF echo x - printertag.asm sed 's/^X//' > printertag.asm << '/*EOF' X* X* printer tag file for the toshiba printer X* X X INCLUDE "exec/types.i" X INCLUDE "exec/nodes.i" X INCLUDE "exec/strings.i" X INCLUDE "devices/prtbase.i" X X XREF _Init X XREF _Expunge X XREF _PrOpen ; called PrOpen and PrClose so as not to X XREF _PrClose ; override the Dos Open and Close calls X XREF _CommandTable X XREF _DoSpecial X XREF _Render X X XDEF _PEDData X X XVERSION EQU $21 XREVISION EQU $24 X X X section printer,code X X moveq #0,d0 ;in case anyone tries to run this X rts X X dc.w VERSION X dc.w REVISION X X_PEDData: X X dc.l printerName X dc.l _Init X dc.l _Expunge X dc.l _PrOpen X dc.l _PrClose X dc.b PPC_COLORGFX ; PrinterClass X dc.b PCC_YMCB ; ColorClass X dc.b 80 ; max columns X dc.b 1 ; num char sets X dc.w 24 ; num rows X dc.l 180*8 ; max x dots X dc.l 0 ; max y dots X dc.w 180 ; x dots/inch X dc.w 180 ; y dots/inch X dc.l _CommandTable X dc.l _DoSpecial X dc.l _Render X dc.l 30 X dc.l 0 X XprinterName: X dc.b 'toshiba',0 /*EOF echo x - pwait.asm sed 's/^X//' > pwait.asm << '/*EOF' X* X* PWait - wait for a time X* X* PWait(seconds, micros) X* X X INCLUDE "exec/types.i" X INCLUDE "exec/ports.i" X INCLUDE "exec/devices.i" X INCLUDE "exec/io.i" X X INCLUDE "devices/timer.i" X INCLUDE "macros.i" X INCLUDE "devices/prtbase.i" X X XREF_EXE Forbid X XREF_EXE Permit X XREF_EXE WaitIO X X XREF _SysBase X XREF _PD X X XDEF _PWait X X_PWait: X movem.l a4/a6, -(a7) X move.l _PD,a4 X move.l pd_PBothReady(a4),a0 X jsr (a0) X tst.l d0 X bne.s error X X lea pd_TIOR(a4),a1 X move.w #TR_ADDREQUEST,IO_COMMAND(a1) X move.l 12(a7),IOTV_TIME+TV_SECS(a1) X move.l 16(a7),IOTV_TIME+TV_MICRO(a1) X clr.b IO_FLAGS(a1) X move.l IO_DEVICE(a1),a6 X LINKEXE Forbid X lea pd_TIOR(a4),a1 X LINKEXE WaitIO X LINKEXE Permit X moveq #0,d0 X tst.l d0 Xerror: X movem.l (a7)+,a4/a6 X rts /*EOF echo x - render.c sed 's/^X//' > render.c << '/*EOF' X#include <exec/types.h> X#include <exec/nodes.h> X#include <exec/lists.h> X#include <exec/memory.h> X#include <devices/printer.h> X#include <devices/prtbase.h> X Xextern struct PrinterData *PD; Xextern struct PrinterExtendedData *PED; X X#define PWrite (*(PD->pd_PWrite)) /* write data to device */ X#define PReady (*(PD->pd_PBothReady)) /* wait for both buffers ready */ X X#define LEAD 4 /* bytes to start each complete cycle */ X#define EXTRA 9 /* bytes to prefix each pass of the head */ X#define TAIL 2 /* bytes to end each complete cycle */ X Xvoid *AllocMem(); X X/* these two tables wouldn't normally be bothered with but in light of X * the number of times that these operations need to be performed X * for each pass of the print head I thought they'd be worthwhile X */ X X/* X * this table simulates the operation (1<<(5-(y%6))) X * for values of y between 0 and 23 (the number of pixels in a printer pass) X * X */ X XUBYTE bit_table[] = { X 32,16,8,4,2,1, X 32,16,8,4,2,1, X 32,16,8,4,2,1, X 32,16,8,4,2,1 X}; X X/* this table simulates y/6 for values of y between 0 and 23 */ X/* saves a long division opeation */ XUBYTE div_table[] = { X 0,0,0,0,0,0, X 1,1,1,1,1,1, X 2,2,2,2,2,2, X 3,3,3,3,3,3 X}; X XUBYTE *GfxBuffer; X XULONG Render(ct,x,y,status) Xregister UBYTE ct; Xregister UWORD x,y; Xregister UBYTE status; X{ X static ULONG ROWSIZE; X static ULONG COLOURSIZE; X static ULONG BUFSIZE; X static ULONG colours[4]; X static ULONG centre; X static ULONG bufptr; X static UBYTE *ptr; X static ULONG psize; X int i,filler; X int err; X X/* Aztec doesn't preserve a6, we need this in a printer driver */ X#asm X move.l a6,-(sp) X#endasm X err = 0; X X switch (status) { X X case 0: /* alloc memory for printer buffer */ X X filler = (centre) ? ((PED->ped_MaxXDots -x ) / 2 ) : 0; X ROWSIZE = ((x+filler)<<2) + EXTRA; X COLOURSIZE = ROWSIZE<<2; X BUFSIZE = COLOURSIZE+LEAD+TAIL+1; /* plus 1 for NULL */ X X colours[0] = LEAD + EXTRA + filler + ROWSIZE*0; X colours[1] = LEAD + EXTRA + filler + ROWSIZE*1; X colours[2] = LEAD + EXTRA + filler + ROWSIZE*2; X colours[3] = LEAD + EXTRA + filler + ROWSIZE*3; X psize = x+filler; X X dbprintf("Size Data:\n"); X dbprintf("\tfiller: %d\n",filler); X dbprintf("\tROWSIZE: %d\n",ROWSIZE); X dbprintf("\tCOLOURSIZE: %d\n",COLOURSIZE); X dbprintf("\tBUFSIZE: %d\n",BUFSIZE); X dbprintf("\tcolours: %d %d %d %d\n", X colours[0],colours[1],colours[2],colours[3]); X X GfxBuffer = AllocMem(BUFSIZE*2,MEMF_PUBLIC); X X if (err = (GfxBuffer==0)) break; X if (err = PWrite("\x1b\x1a\x49",3)) break; X if (err = PWait(1,0)) break; X X /* set to first buffer */ X bufptr = 0; X break; X X case 1: /* render pixel */ X y %= 24; /* blecch, I wanted to avoid this calculation */ X i = bufptr + (x<<2) + div_table[y] + colours[3-ct]; X GfxBuffer[i] |= bit_table[y]; X break; X X case 2: /* write a buffer */ X dbprintf("Writing a buffer\n"); X X /* BUFSIZE-1 is so that we don't send the trailing null */ X if (err=PWrite(&GfxBuffer[bufptr],BUFSIZE-1)) break; X bufptr = BUFSIZE-bufptr; X break; X X case 3: /* initialize the current buffer */ X dbprintf("Performing initialization\n"); X X ptr = &GfxBuffer[bufptr]; X X for (i=BUFSIZE;i--;) *ptr++ = 0; /* clear buffer */ X X ptr = &GfxBuffer[bufptr]; X sprintf(ptr,"\x1bL07"); X sprintf(ptr+LEAD ,"\r\x1bc\x1b;%04d",psize); /* c */ X sprintf(ptr+LEAD+ROWSIZE ,"\r\x1bm\x1b;%04d",psize); /* m */ X sprintf(ptr+LEAD+ROWSIZE*2,"\r\x1by\x1b;%04d",psize); /* y */ X sprintf(ptr+LEAD+ROWSIZE*3,"\r\x1bb\x1b;%04d",psize); /* b */ X sprintf(ptr+LEAD+ROWSIZE*4,"\r\n"); /* crlf + NULL */ X X break; X X case 4: /* cleanup -- release memory */ X dbprintf("Print finished -- cleanup\n"); X dbprintf("waiting for printer\n"); X X err = PReady(); X X dbprintf("Freeing memory\n"); X X FreeMem(GfxBuffer,BUFSIZE*2); X X dbprintf("Returning\n"); X X break; X X case 5: /* handle any special commands */ X centre = x & SPECIAL_CENTER; X dbprintf("special: %d %d %d %d\n",ct,x,y,status); X X break; X X default: X break; X } X#asm X move.l (sp)+,a6 X#endasm X return(err); X} /*EOF echo x - toshiba.uu sed 's/^X//' > toshiba.uu << '/*EOF' Xbegin 644 toshiba XM #\P # ( /A @0 !P /I #X7 3G4 XM(0 D 0@ $H $N !6@ 5X#!% ! !@ 6@ "T +0 4 XM "3 ^X > '1O<VAI8F$ (^\ ! !!^0 @CR 0O XM#BQY !"/. ,$/Z (QP 4ZN_=@CP #1G9D/Z (9P 4ZN_=@CP XM QG0$/Z %9P 4ZN_=@CP !!G&G +%].=2)Y $"\.+'D P3J[^ XM8BQ?(GD ,+PXL>0 #!.KOYB+%\B>0 #0O#BQY ,$ZN_F(L7W#_ XM8+QI;G1U:71I;VXN;&EB<F%R>0!D;W,N;&EB<F%R>0!G<F%P:&EC<RYL:6)R XM87)Y $DG;2!B96EN9R!R=6)B960@;W5T(0 +PXL>0 # B>0 !!.KOYB XM(GD ,3J[^8B)Y -$ZN_F(L7W 3G5P $YU< !.=1L:20 ; * T* XM T: !L4&TH;30 ;$@ ;% ;20 ;2@ ;2P( &TT _P#_ !LJ,!M=&R( &RHQ XM !LJ, ;6P ;70 ;(0 ;(@ ;40 ;30 ;2P( &TT &RHR !LJ, ;1 ;50 ; XM50 ;1 #_ /\ _P#_ /\ _P#_ /\ _P#_ /\ _P ;) ;)0#_ /\ _P#_ /\ XM_P#_ /\ &QX& !L>" #_ /\ _P ;.0 ;, ;*P ;+0#_ /\ _P ;,0#_ !LX XM !LR /\ _P ;. ;*# X+#$V+#(T+#,R+#0P+#0X+#4V+#8T+#<R+@#_ $Y5 XM__Q(YS\P)&T ""9M PH+0 0*BT %"PM !@N+0 <+PY(>@$N3KD G06$]P XM # 28 _$AZ 24O"TZY *"E!/('D #&@! I89PXB>0 ,:00 XM"E9F#DAZ /\O"TZY )X%!/('D #&@( I69@Y(>@#G+PM.N0 ">!0 XM3R!Y $IH"EIF(DAZ - O"TZY )X%!/($40O D2'H P$ZY )T%A/ XM8"!(>@"Z+PM.N0 ">!03R!%$+P &TAZ *I.N0 "=!83TAZ *9.N0 "=!8 XM3R\+3KD \@6$\K0/_\8% @11"\ !M(>@"+3KD G06$]@/"!%$+P )$AZ XM (!.N0 "=!83V H< P$B\ 2'H =4ZY )T%!/8!13@&< _P*0O #9G XMME. 9\9@V"Q?("W__$S?#/Q.74YU1&]3<&5C:6%L.@ ;&DD &RHQ !M; !L> XM" @5DU)/3,V !L>!@ @5DU)/3(W "!A4DE."@ @5DU)/3(W"@ @5DU)/3,V XM"@!R97$Z)60* !.5?_T2.<_ !@M LZ+0 ./"T $AXM !<O#D*M__1P ! ' XM8 $%$JY '&<4('D $("@ &G( ,@60@>*(8 )P "M __AP # %T*W_ XM^.6 T+P )(\ (#D Y8 CP 0@.0 1>@"/ "" M XM__C0O TCP P@+?_XT+D T+P -(\ 0(#D XX#0 XMK?_XT+P -(\ 4<@,@.0 !.N0 #S+0K?_XT+P -(\ 8 XM< P!="M__@CP "A(>@-R3KD G06$\O+?_X2'H#;DZY )T%!/+SD XM 2'H#:4ZY )T%!/+SD $2'H#94ZY )T%!/+SD (2'H#9$ZY XM )T%!/+SD 8+SD 4+SD 0+SD ,2'H#3DZY )T$_O !1( XM> !(#D (XX O $ZY /5E!/(\ X2KD X9@HK? '_]& $ XM0JW_]&8 KI(> #2'H#'2!Y ")H &1.D5!/*T#_]&8 IQ"ITAX %. XMN0 "6903RM __1F *&0KD @8 "?$A&0D9(1HS\ !A(1G #<@ 2!)"! XMY8!!^0 QT #0%Y8(F, @ UH)#^0 51T !0Q8 #6@M:Y ("M#__P@ XM+?_\('D XT<!#^0 3P2,6 @Q!@ (@2'H"BTZY )T%A/(#D ( XM4X O "!Y .-'Y ("\(('D (F@ 9$Z14$\K0/_T9@ !YB Y XM")"Y ("/ (& =!(>@)-3KD G06$\@.0 #C0N0 " CP XM "0K>0 C__& .('D D4KD D0A @+?_\4ZW__$J 9N8@.0 #C0 XMN0 " CP "1(>@(4+SD D3KD H:4$\O.0 "A(>@(!('D D XM6(@O"$ZY *&D_O PO.0 "A(>@'M('D DT?D 6(@O"$ZY * XM&D_O PO.0 "A(>@'3(#D XX#0N0 "18@"\ 3KD H:3^\ #"\Y XM *$AZ ;=R R Y $ZY /,M"Y )%B +P!.N0 "AI/[P ,2'H! XMFR Y .6 T+D D6( O $ZY *&E!/8 M$AZ 7Q.N0 "=!83TAZ XM 8M.N0 "=!83R!Y ")H &A.D2M __1(>@&$3KD G06$\@.0 CC XM@"\ +SD X3KD ]L4$](>@%P3KD G06$]@6' , 7 O $ CP XM !QP ! '+P!R #(&+P%T #0%+P)V !8$+P-(>@%%3KD G03^\ %& @8![[ XMWOV(_>3^-/]0_ZJPO 9DZN. ,#L Z$[[ L7R M__1,WP#\3EU.=5-I XM>F4@1&%T83H* EF:6QL97(Z("5D"@ )4D]74TE:13H@)60* E#3TQ/55)3 XM25I%.B E9 H "4)51E-)6D4Z("5D"@ )8V]L;W5R<SH@)60@)60@)60@)60* XM !L:20!7<FET:6YG(&$@8G5F9F5R"@!097)F;W)M:6YG(&EN:71I86QI>F%T XM:6]N"@ ;3# W T;8QL[)3 T9 -&VT;.R4P-&0 #1MY&SLE,#1D T;8AL[ XM)3 T9 -"@!0<FEN="!F:6YI<VAE9" M+2!C;&5A;G5P"@!W86ET:6YG(&9O XM<B!P<FEN=&5R"@!&<F5E:6YG(&UE;6]R>0H 4F5T=7)N:6YG"@!S<&5C:6%L XM.B E9" E9" E9" E9 H $CG HH>0 @; !H3I!*@&900^P!$#-\ D XM'"-O P ("-O ! )$(I !XL:0 4+PXL>0 #!.KO]\+%]#[ $0+PXL>0 XM #!.KOXF+%\O#BQY ,$ZN_W8L7W 2H!,WU 3G5.50 2.<P $S? Q. XM74YU,#Q__V $,"\ #B!O 1*&&;\4T@B;P (4T 0V5?(__QG D(0("\ !$YU XM(&\ !" ((F\ "!#99OQ.=4Y5 !(YS@ (^T " "Q(;0 0+RT #$AZ "!. XMN0 "PQ/[P ,* @>0 "Q"$" $3-\ '$Y=3G5.50 2.<P "!Y +%*Y XM +! M L0@$B 2,# O /],WP ,3EU.=4Y5 !(YS@@)&T $ RM XM! 49@@@;0 (*!!@%$JM QO""!M @H$& &(&T ""@00JT %$JM QL$D2M XM Q*A&P*1(0K? $ %"(M P@!$ZY .ND'Y !;%.*%+ ( "(M P@ XM!$ZY .QB@ 9MA*K0 49P93BA2\ "T@"DS?!!Q.74YU3E7_%$CG.# D;0 ( XM)FT #$*M__@K;0 0__P@2U*+$!!(@$C * !G ,\N+P E9@ #%D(M_R(K XM? '_]"M\ (/_P*WP "<0_^P@2U*+$!!(@$C * "PO "UF$$*M XM__0@2U*+$!!(@$C * "XO #!F%"M\ ,/_P($M2BQ 02(!(P"@ N+P XM J9AH@;?_\6*W__"M0_^@@2U*+$!!(@$C * !@.$*M_^A@)'(*("W_Z$ZY XM /,M"$D+P P*T#_Z"!+4HL0$$B 2, H $'Y !?P@P )( &;.N+P XM N9F8@2U*+$!!(@$C * "PO "IF&B!M__Q8K?_\*U#_["!+4HL0$$B XM2, H & X0JW_[& D<@H@+?_L3KD \RT(20O # K0/_L($M2BQ 02(!( XMP"@ 0?D %_"# D@ 9LXK? 3_Y+B\ ;&86($M2BQ 02(!(P"@ XM*WP $_^1@%+B\ :&8,($M2BQ 02(!(P"@ ( 1@ ""*WP (_^!@ XM'"M\ "O_@8!(K? !#_X& (*WS____V_^ O+?_D2&W_(B\M_^ O+?_\ XM3KK]I$_O ! K0/_<("W_Y-&M__Q@7"!M__Q8K?_\*U#_W"\M_]Q.N0 #R!8 XM3RM _^1@2B!M__Q8K?_\*!!![?\A*TC_W!"$8"B0O &-GXE. 9Y*0O XM MG /]L68!GLE6 9P#_;%> 9P#_<&#,0>W_(I'M_]PK2/_D("W_Y+"M_^QO XM!BMM_^S_Y$JM__1G<"!M_]P,$ M9PHB;?_<#!$ *V8T#*T P__!F*E.M XM_^@@;?_<4JW_W! 02(!(P"\ 3I)83["\_____V8*</],WPP<3EU.=6 8+RW_ XM\$Z26$^PO/____]F!'#_8.)2K?_X("W_Z%.M_^BPK?_D;MI"K?_@8"0@;?_< XM4JW_W! 02(!(P"\ 3I)83["\_____V8$</]@JE*M_^ @;?_<2A!G"B M_^"P XMK?_L;<H@+?_@T:W_^$JM__1F*F :2'@ ($Z26$^PO/____]F!G#_8 #_<%*M XM__@@+?_H4ZW_Z+"M_^1NV& 8+P1.DEA/L+S_____9@9P_V _TA2K?_X8 #\ XMN" M__A@ /\X2.=( $*$2H!J!$2 4D1*@6H&1($*1 !83Y*1&<"1(!,WP 2 XM2H!.=4CG2 !"A$J :@1$@%)$2H%J D2!81H@ 6#8+P%A$B !(A]*@$YU+P%A XM!B(?2H!.=4CG, !(04I!9B!(038!- !"0$A @,,B $A ,@*"PS !0D%(04S? XM Q.=4A!)@$B $)!2$%(0$) = _0@-.!MH%B!)*#4D!1RO_R3-\ #$YU(&\ XM!" (2AAF_)' ( A3@$YU2.=P #0!Q, F 4A#QL!(0T)#U(-(0,#!2$!"0-"" XM3-\ #DYU3OD ]<3.\ P $+'D P3N[_.D[Y /<B)O 0@+P (+'D XM P3N[_+@ ^P 7 0 "X !. 6@ (H "< J@ XM +X $X !0@ I( *@ "O M@ 0> %B@ !>@ 8, & XM0 !Z EL *W "^H Q8 -0 ( # ! 4 XM & #( V 5 G0 ** "M M +J "_ PP XM ,> #*@ S0 -, #8 W0 2P $V !.@ 3Z %# XM!1X 5" %6@ !:8 8@ &< !LH ;F '"@ !S =, ' XM7 !WP >, 'F ![0 ?, 'V " X HX *U@ "NX O, XM ,.@ #0( ]8 /;@ $T " : '@ "R Q@ -( XM #: !,@ 4P 06 $2 !$X 16 $7 !&0 1T $?@ XM!(H 20 $H@ !*H 3 $S@ !/ 4" %% !28 4L % XM,@ !3@ 50 %8@ !6@ 6V %U@ !?8 8$ &* !C( 8X XM &5@ !EP 9B &> !GX :$ &B@ !I0 :: &K@ !K0 XM :Z &Q !M( ;< &\ !OH < '% !QX <F '.@ XM!T8 =2 ':@ !W( >\ 'Q@ !^P F< )K@ ";P HF * XM1 "EX ID /9 #WP #\@ ^H "! XM %B !9@ 6D %K !;@ 7$ %X !>P 7X XM &! !A 8@ &+ !C0 8\ &7 !FP 9\ &B !I0 XM :@ &K !K@ ;$ &U !N ;P ' !PP <8 ') ! XMS <X '0 !T@ =0 '6 !V =H '< !W@ > 'B XM !Y >< 'J ![ >X 'P !\@ ?0 'V !^ ?H XM '^ " @ @0 (& "" @L (. "$0 A0 (6 "& XM AH (= "'P B( (E ")P BD (L "2B 0" 0" 2 0" 0" XM 2 0" 0" 2 0" 0" 0 $! 0$! 0(" @(" @,# P,# S Q,C,T-38W XM.#EA8F-D968 @(" @(" @(" P,# P," @(" @(" @(" @(" @(" @()! XM0$! 0$! 0$! 0$! 0$ ,# P,# P,# P,0$! 0$! 0 D)"0D)"0$! 0$! 0$! XM 0$! 0$! 0$! 0$!0$! 0$! "@H*"@H* @(" @(" @(" @(" @(" @(" @) XM0$! ( % #[ $H % !@ < ( "0 H XM + # T . #P ! 1 $@ !, 4 %0 XM !8 7 & !D : &P !P = '@ !\ @ XM (0 "( C ) "4 F )P "@ I *@ "L XML +0 "X O , #$ R ,P #0 U -@ #< XM X .0 #H [ / #T ^ /P $ !! 0@ XM $, !$ 10 $8 !' 2 $D !* 2P $P !- X6 3@ #\@ ^L < #\B X Xend /*EOF echo end of archive exit 0 -- {watmath|allegra|decvax|ihnp4|linus}!utzoo!oscvax!rico or just rico@oscvax.UUCP if you're lucky [NSA food: terrorist, cryptography, DES, drugs, CIA, secret, decode] [CSIS food: supermailbox, tuna, fiberglass coffins, Mirabel, microfiche] [Cat food: Nine Lives, Cat Chow, Meow Mix, Crave]
stroyan@hpfcdc.HP.COM (Mike Stroyan) (11/03/87)
Thank you Thank you Thank you Thank you Thank you Mike Stroyan, [hplabs!]hpfcla!stroyan