home *** CD-ROM | disk | FTP | other *** search
- page ,132
- title LpPlot - Disguise Plotter as LPT3
-
- ;* Terminate-and-stay-resident program to drive an HP plotter
- ; with a GPIB interface as LPT3.
- ;
- ; Copyright 1990, Sydex. All Rights Reserved.
- ;
- ; Consult the accompanying documentation for specific licensing
- ; rights and descriptive information.
- ;
-
- .model small,c
-
- ; The following needs to be changed if your printer card differs.
-
- Base_Port equ 0278h ; where our GPIB printer card located.
-
- ; GPIB talker-listener addresses.
-
- Plotter equ 5 ; plotter address
- Us equ 15 ; our address
-
- ; Interrupts.
-
- dosint equ 21h ; DOS interrupt
- lpint equ 17h ; BIOS lp server interrupt
-
- ; Characters.
-
- cr equ 13 ; ascii return
- lf equ 10 ; ascii linefeed
-
- .data
-
- extrn Last_Memory:word ; highest memory location used
- extrn Stack_Buf:word ; where we put the stack
-
- AlreadyInMess db cr,lf,'LPT3 GPIB driver already present',cr,lf,'$'
-
- Plot_Init db 0 ; Plotter initialized
-
- High_Para dw 0 ; for DOS function 31 - highest memory
-
- .code
-
- ;* The following calls are available to us:
- ;
- ; int GPIB_Init( int io_port, int our_address)
- ; int GPIB_Send( int listen, char what)
- ; int GPIB_PutStr( int listen, char *string, int count)
- ; int GPIB_Stat(void);
- ; int GPIB_Get( int listen)
- ; int GPIB_GetStr( int listen, char *buf)
- ; int GPIB_SerPoll( int listen)
- ; int GPIB_PutAdd( char what)
- ; int GPIB_PutData( char what)
- ; int GPIB_GetData();
-
- ; The following calls are used:
-
- extrn GPIB_Init:near
- extrn GPIB_PutAdd:near
- extrn GPIB_PutData:near
- extrn GPIB_Stat:near
-
- ;* The following doubleword hold the address of the original
- ; BIOS print servicer. We keep this in the code segment for
- ; simplicity.
- ;
-
- PrtVector label dword
- PrtOff dw (?) ; offset to native driver
- PrtSeg dw (?) ; segment to native driver
-
- ;* Main routine.
- ;
- ;
-
- Start proc near
-
- ; Before we clobber DS, figure out how many paragraphs of memory
- ; this thing will take for the TSR call later.
-
- mov dx,seg @Data
- mov ax,ds ; PSP area
- sub dx,ax ; figure segment difference
- lea ax,@Data:Last_Memory
- add ax,15 ; round up highest data offset
- shr ax,1
- shr ax,1
- shr ax,1
- shr ax,1
- add dx,ax ; total paragraphs needed
-
- ; Set up segments.
-
- mov ax,seg @Data ; data segment
- mov es,ax
- mov ds,ax
- mov ss,ax
- lea sp,@Data:Stack_Buf ; set stack up
- mov bp,sp
- mov High_Para,dx ; save high paragraphs
-
- ; Next, see if we're already in--issue function call F1 to the
- ; BIOS printer interface. If we're already in, we'll get AL = FF.
-
- Start2:
- mov ax,0F100h
- mov dx,2 ; lpt2
- int lpint ; see if already in
- cmp al,0ffh ; says we're in
- jne Start4
-
- lea dx,@Data:AlreadyInMess
- mov ah,9
- int dosint ; issue error message
- mov ax,4c01h ; terminate with error
- int dosint
-
- ; Initialize the parallel interface.
-
- Start4:
- mov ax,Us
- push ax
- mov ax,Base_Port
- push ax
- call GPIB_Init ; initialize
- mov sp,bp ; clear stack
-
- mov Plot_Init,0 ; say not initialized
-
- ; Now "hook" interrupt 17h.
-
- push es
- mov ax,3500h+lpint
- int dosint ; get vector
- mov PrtSeg,es
- mov PrtOff,bx ; set segment/offset
- pop es
- push ds
- mov ax,cs
- mov ds,ax
- lea dx,ServLpt ; new entry
- mov ax,2500h+lpint
- int dosint ; set vector
- pop ds
- mov dx,High_Para ; total paragraphs
- mov ax,3100h ; Advanced TSR
- int dosint ; do it
-
- Start endp
-
- subttl LPT3 Servicer Code.
- page
-
- ;* Servicer Code for LPT3.
- ;
- ; This is entered when a call is made to the BIOS to output
- ; a character to LPT3.
- ;
-
- ServLpt proc near
- sti
- cmp dl,2
- je ServLpt4 ; if LPT3
- ServLpt2:
- jmp PrtVector ; go handle non-LPT3 with original
-
- ; Got LPT3, now figure what's going on...First off, set up our
- ; working segments and a stack.
-
- ServLpt4:
- push ds
- push es
- push ax
- mov ax,seg @Data
- mov ds,ax
- mov es,ax
- pop ax
- mov Stack_Buf,ss
- mov Stack_Buf-2,sp
- push ds
- cli
- pop ss
- lea sp,@Data:Stack_Buf-4 ; set the stack up
- sti
- cmp ah,0
- jne ServLpt6 ; if not write
- call WriteLpt ; write
- jmp short ServLpt20 ; exit...
-
- ServLpt6:
- cmp ah,1
- jne ServLpt8 ; if not initialize
- call InitLpt ; if initialize
- jmp short ServLpt20 ; exit...
-
- ServLpt8:
- cmp ah,2
- jne ServLpt10 ; if not status
- call InitLpt ; status--same as init
- jmp short ServLpt20
-
- ServLpt10:
- cmp ah,0f1h
- stc ; signal error
- jne ServLpt12 ; if not test of who's in
- mov al,255 ; say we are
- jmp short ServLpt20 ; exit...
-
- ServLpt12:
- mov ah,1
- stc
- jmp short ServLpt20 ; exit with error
-
-
- ; Restore segments, exit, preserving flags.
-
- ServLpt20:
- cli
- mov ss,Stack_Buf
- mov sp,Stack_Buf-2
- sti
- pop es
- pop ds
- retf 2
- ServLpt endp
-
-
- ;* Write to printer - Make sure plotter is initialized...
- ;
- ;
-
- WriteLpt proc near
- test Plot_Init,-1
- jnz WriteLpt2 ; if initialized already
- call SendAddress
- jc WriteLpt4 ; if error, skip
- WriteLpt2:
- push ax ; the data byte
- call GPIB_PutData ; write it
- add sp,2 ; unstack
- cmp ax,-1
- je WriteLpt4 ; if error
- call GetStatus
- ret ; exit with status
-
- ; Error -- set for re-initialize.
-
- WriteLpt4:
- mov Plot_Init,0 ; say not initialized
- push ax ; save data
- mov ax,Us
- push ax
- mov ax,Base_Port
- push ax
- call GPIB_Init ; re-initialize
- add sp,4 ; unstack
- pop ax ; restore data
- mov ah,11010001b ; say timeout
- stc
- ret ; exit...
- WriteLpt endp
-
- ;* InitLpt - Initialize/Status Plotter.
- ;
- ; We initialize only the first time in.
- ;
-
- InitLpt proc near
- test Plot_Init,-1
- jnz InitLpt2 ; if initialized already
- call SendAddress
- jc InitLpt4 ; if error
- InitLpt2:
- call GetStatus ; get printer status
- ret ; return with flags
-
- ; Error return.
-
- InitLpt4:
- mov Plot_Init,0 ; say not initialized
- mov ax,Us
- push ax
- mov ax,Base_Port
- push ax
- call GPIB_Init ; re-initialize
- add sp,4 ; unstack
- mov ah,11010001b ; say timeout
- stc
- ret ; exit...
- InitLpt endp
-
-
- ;* SendAddress - Send talk/listen addresses to interface.
- ;
- ; Pretty much straightforward. We do preserve (ax), however.
- ;
-
- SendAddress proc near ; send address out to plotter
- push ax
- mov ax,'?'
- push ax
- call GPIB_PutAdd ; send an unlisten
- add sp,2 ; clean off stack
- cmp ax,-1
- je SendAddress2 ; if error
-
- mov ax,Us+40h ; talker is us
- push ax
- call GPIB_PutAdd ; send talker address
- add sp,2 ; unstack
- cmp ax,-1
- je SendAddress2 ; if error
-
- mov ax,Plotter+20h
- push ax
- call GPIB_PutAdd ; send listener address
- add sp,2 ; unstack
- cmp ax,-1
- je SendAddress2 ; if error
- mov Plot_Init,-1 ; say we did it
- stc
- SendAddress2: ; error exit...
- cmc ; set carry if error
- pop ax
- ret
- SendAddress endp
-
- ;* GetStatus -- Simulate printer status from GPIB status.
- ;
- ; A fake--only returns ready/not ready.
- ;
-
- GetStatus proc near ; read status
- call GPIB_Stat
- mov ah,11010000b ; normal status
- test al,100b ; see if NRFD set
- jz GetStatus2 ; if not...
- and ah,7fh ; say not ready
- stc
- GetStatus2:
- ret ; exit...
- GetStatus endp
-
- EndMem label byte
-
- end Start