;--pport.asm--------------------------------------------------------------
;
;Dumps the screen to a remote machine over an 11 wire null printer cable
; using the 3-bit IRQ method with this program running on both ends.
;
;Public Domain from James Vahn - July 2,1996 - (jvahn@short.circuit.com)
;
;IRQ7 hooks INT 0Fh
;IRQ5 hooks INT 0Dh
;
;Generally LPT1 is on port 378/IRQ7, and LPT2 is port 278/IRQ5
;Port 3BC does not work well for this, apparently a broken IRQ line.
;
; Standard null-printer cable wiring (machine1 - machine2):
; 2-15, 3-13, 4-12, 5-10, 6-11, 15-2, 13-3, 12-4, 10-5, 11-6, 25-25
;
;
;Data flows 3 bits at a time:
; sender receiver
; (send first set) IRQ1->
; <-ACK1
; (send second set) IRQ2->
; <-ACK2
; (send third set) IRQ3->
; <-ACK3
;
;No error checking, no BUSY.
Hook EQU 0Dh ;IRQ5
Port EQU 278h ;
Screen EQU 0B000h ;Monochrome 0B000h Color 0B800h
timer EQU 1 ;Timing loop value. Increase if needed.
.286 ;Uses 286 opcodes.
cseg segment
assume cs:cseg, ds:cseg
org 100h ;COM format.
Begin:
call Setup ;Initialize ports.
getkey:
mov ah,0 ;Use BIOS to get a
int 16h ; key from the keyboard.
cmp al,27 ;Is escape key?
jne main
jmp alldone ; yes, so we quit.
main:
mov ax,Screen ;Do a screen dump.
mov ds,ax
xor si,si
mov cx,2000
s: lodsb
inc si ;Skip screen attribute.
call Send
loop s
jmp getkey
;********************************************************************
Setup proc near
mov dx,offset Msg ;Prints the hello message.
mov ah,09h
int 21h
mov ah,35h ;Get old vector and store it.
mov al,Hook
int 21h
mov word ptr [Old_Int],bx
mov word ptr [Old_Int+2],es
mov al,Hook ;Change the target vector.
mov dx,offset New_ISR
mov ah,25h
int 21h
mov dx,Port
mov al,00000000b ;Clear IRQ.
out dx,al
mov dx,Port+2 ;Control register.
mov al,00011100b ;Initialize (IRQ on).
out dx,al
in al,21h ;Enable IRQ's 5 and 7.
and al,01011111b ;Doing both, don't need to.
out 21h,al
ret
endp
;****************************************************************
; Sends a byte over the parallel port.
; Registers unchanged.
;
Send proc near
pusha
push ds
push es
push cs
pop ds
mov ah,al ;Save it.
;Send 1st
mov dx,Port
mov al,00000000b ;Bring IRQ line low.
out dx,al
call delay
mov al,ah ;Load data from AH.
and al,00000111b ;Only lower three bits.
or al,00001000b ;Set IRQ line high.
out dx,al ;Ship it.
mov bl,1
call listen ;ACK'd?
jc nobody
;Send 2nd
;
mov dx,Port
mov al,00000000b ;Bring IRQ line low.
out dx,al
call delay
mov al,ah ;Load data from AH.
shr al,3 ;Move second set into position.
and al,00000111b ;Only those three bits.
or al,00001000b ;Set IRQ line high.
out dx,al ;Ship it.
mov bl,2
call listen ;ACK'd?
jc nobody
;Send 3rd
;
mov dx,Port
mov al,00000000b ;Bring IRQ line low.
out dx,al
call delay
mov al,ah ;Load data from AH.
shr al,6 ;Move third set into position.
and al,00000111b ;Only those bits. (Really 2 bits)
or al,00001000b ;Set IRQ line high.
out dx,al ;Ship it.
mov bl,3
call listen ;ACK'd?
jc nobody
pop es
pop ds
popa
ret
endp
;***********************************************************************
; Listen on port for ACK in BL. Carry set on failure.
;
listen proc near
mov cx,0FFFFh
listen1:
call delay
mov dx,Port+1 ;Read data waiting.
in al,dx
shr al,3 ;Move bits into position.
and al,00000111b ;Mask upper nibble away.
cmp al,bl ;Is it our ACK in BL?
loopne listen1 ; nope, loop.
stc ;Carry set on error.
jcxz listen2 ;If CX=0 then we have timed out.
clc ;Okay, clear carry.
ret
listen2:
ret
endp
;***********************************************************************
; Miscellaneous routines.
;
delay:
push cx
mov cx,timer
d1: out 0BDh,al ;Simple I/O delay.
loop d1
pop cx
ret
nobody:
mov dx,offset Msg2
mov ah,9
int 21h ;Print 'nobody home' message
; and fall through...
alldone:
in al,21h ;Disable IRQ's 5 and 7.
or al,10100000b
out 21h,al
mov ax,word ptr cs:[Old_Int +2]
mov dx,word ptr cs:[Old_Int]
mov ds,ax
mov al,Hook ;Restore old ISR.
mov ah,25h
int 21h
int 20h ;Exit to DOS.
;***********************************************************************
; Data storage area.
Msg db 13,10
db 'Parallel port Screen dump, demonstrating data transfer.',13,10
db 'Press any key to dump screen, ESC to terminate.',13,10
db 13,10,36
Msg2 db 13,10,"There's nobody listening..",13,10,36
Old_Int dd ? ;Storage- points to the old ISR.
tmp db ?
ack db 1
;***********************************************************************
; This ISR prints the data received to the screen.
;
; Note: Receiving 00001000b appears as 11000111b on the input port.
; ^^^^ ^^^^
; Input port bits: 7 6 5 4 3 2 1 0
; Useage: BUSY, IRQ/DATA, DATA, DATA, DATA, N/C, N/C, N/C
;
New_ISR proc near
pusha ;Save the registers
push ds
push es
push cs
pop ds
mov al,ack ;Determine which set.
cmp al,1
je _1st
cmp al,2
je _2nd
cmp al,3
je _3rd
jmp exit
_1st:
mov dx,Port+1 ;Get from input port
in al,dx
shr al,3 ;Move into position.
and al,00000111b ;Just those three bits.
mov tmp,al ;Store them.
mov al,1
mov ack,al ;Return ACK1
jmp ackd
_2nd:
mov dx,Port+1 ;Get from input port
in al,dx
and al,00111000b ;Bits already in position.
or tmp,al ;Store them.
mov al,2
mov ack,al ;Return ACK2
jmp ackd
_3rd:
mov dx,Port+1 ;Get from input port
in al,dx
shl al,3 ;Move into position.
and al,11000000b ;Just those two bits.
or tmp,al ;Store them.
mov al,tmp
int 29h ;Print to screen. A cheat, potential bug.
mov al,3
mov ack,al ;Return ACK3
jmp ackd
ackd:
mov dx,Port
mov al,ack
and al,00000111b ;Send ACK, no IRQ.
out dx,al
inc ack ;Increment data counter
cmp ack,4 ; for next set. 1, 2, 3
jb reset
mov al,1
mov ack,al
reset:
mov al,20h ;Ready for more interrupts.
out 20h,al
exit:
pop es ;Restore registers
pop ds
popa ;End of ISR- exit
jmp cs:[Old_Int] ; to old vector.
endp
;***********************************************************************
cseg ends
end Begin