Category : Assembly Language Source Code
Archive   : USRSPOOL.ZIP
Filename : USRSPOOL.ASM

 
Output of file : USRSPOOL.ASM contained in archive : USRSPOOL.ZIP
page 60,132
title spool - printer buffer for ibm-pc

;14may85 lmp minor changes, release for production
;xxmay85 jdn added rate command, fixed xon/xoff, upgraded parser


exit macro
int 20h
endm

EOL equ '$'

TRUE equ 0ffh
FALSE equ 000h

CR equ 00dh
LF equ 00ah

COM1 equ 0
COM2 equ 1
LPT1 equ 2
LPT2 equ 3
LPT3 equ 4
NONE equ 0

D_PORT equ LPT1 ;default port
D_PROTOCOL equ NONE ;default protocol
D_BUFFSIZE equ 20 ;K bytes

CTS equ 010h ;mask for 8250
DSR equ 020h ;mask for 8250

ITxRdy equ 002h ;TxRdy int id from PIC
IRxRdy equ 004h

EOI equ 020h ;EOI cmd for PIC

_MSTATUS equ 006h ;offset to modem status register

XON equ 011h
XOFF equ 013h
SPECIAL equ 0fh

STATUS_OK equ 90h ;selected, not busy

subttl segment 0 defined
page
abs0 segment at 0

org 17h * 4
int_17 dd ? ;bios print_char interrupt
org 408h
printer_base dw ? ;bios printer base addresses (3)
org 478h
print_tim_out db ? ;bios printer time out values (4?)

abs0 ends

subttl Main program begins here
page
code segment byte public
org 100h
assume cs:code

start:
jmp init
subttl srv17 - Int 17 (bios print-char) handler
page
;Resident Data Area

;These areas are initialized by the loader portion of this program.

data_start equ $ ;start of global data storage

buff_head dw offset buffer
buff_tail dw offset buffer
buff_start dw buffer
buff_end dw ?
buff_size dw D_BUFFSIZE*1024 ;parm set by parse - default = 4k

stopped db TRUE ;true if buffer empty and last char done
prot_ready db TRUE ;true if protocol says go.

port db D_PORT ;port code - 0=COM1, 1=COM2, 2=LPT1
; 3=LPT2, 4=LPT3
protocol db D_PROTOCOL ;protocol code - see init routines

noparms db TRUE ;used by parse
status db STATUS_OK

data_len equ $-data_start ;length of global data

es_save dw 0 ;es save area

;This is the Signature. Do NOT move or change it.
Signature dw 'SP'

srv17 proc near
assume cs:code,ds:nothing,es:nothing

;on entry:
; ah = opcode
; 0 - print
; 1 - init
; 2 - status
; al = char (if opcode = print)
;on exit:
; ah = status
;
push dx
push si
push cx
push bx

lea bx, srv17exit ;no conditional calls, so
push bx ;fake return address & jump

cmp dx,3
jnz skip_mess
jmp message_int
skip_mess:
or ah, ah ;print char?
jz put_buff
dec ah
jz init_port
;if we get here, it was status, or error, so fall thru to status
pop bx ;clear faked return address

srv17exit:
call return_status ;everybody must do this

pop bx
pop cx
pop si
pop dx
iret

srv17 endp
;
; ==========================
;
message_int proc near
cmp ah,0
jnz mess1
;
push cs
pop es

pop bx ;return address
pop bx ;b register
;
cmp bx,signature
jnz not_me
;
mov bx,0
not_me:
push bx ;put it back on the stack
jmp srv17exit ;return
mess1:
ret
;
message_int endp


subttl put_buff - put a char in our buffer
page
put_buff proc near
assume cs:code, ds:nothing, es:nothing
;put the char (al) into the printer buffer

cmp stopped, FALSE ;stopped?
jz pb_not_stopped

mov stopped, FALSE
call out_char ;send char manually
ret

pb_not_stopped:
put_buff_wait:
mov bx, buff_tail

mov si, bx
call inc_ptr
cmp bx, buff_head ;buffer full?
je put_buff_full ;yes - wait...

mov cs:[si], al ;buffer character
mov buff_tail, bx ;upd tail ptr

ret

put_buff_full:
sti ;enable interrupts
nop ;allow an interrupt
nop
cli
jmp put_buff_wait

put_buff endp
subttl return_status - return the printer status in ah
page
return_status proc near
assume cs:code, ds:nothing, es:nothing

; return code bits (ah)
; 0 timeout
; 1 0
; 2 0
; 3 i/o error
; 4 selected
; 5 out of paper
; 6 acknowledge
; 7 not busy

mov ah, status ;return code
mov status, STATUS_OK ;set up for next time

ret ;for now
return_status endp
subttl init_port - init the selected printer port
page
init_port proc near
assume cs:code, ds:nothing, es:nothing

;uses:
; port
; protocol
;

;enable int on PIC
mov bl, port
xor bh, bh
lea si, init_PIC_table[bx]
mov dl, cs:[si]
in al, 21h
and al, dl ;enable (clear) int bit
out 21h, al

mov al, protocol

mov ah, port
or ah, ah ;just COM1 for now
jz COM1_init
dec ah
jz COM2_init
jmp PAR_init

;-------------------------------------
;Hardware / Setup dependent routines go here
;-------------------------------------
;
init_PIC_table:
; these bytes enable (clear bit) the appropriate bit on the PIC.
db 0efh ;COM1 (IRQ 4)
db 0f7h ;COM2 (IRQ 3)
db 07fh ;PAR (IRQ 7)
db 07fh ;all par ports share this int
db 07fh
;-------------------------------------
;
;Init Routines. Protocol type is passed in al.
; 0 None
; 1 XON/XOFF
; 2 CTS
; 3 ETX/ACK
; 4 DSR
;-------------------------------------
COM1_init: ;initialize com1 port
;-------------------------------------
mov bx, 3f8h ;base for COM1
jmp COMx_init

;--------------------------------------
COM2_init: ;initialize com2 port
;--------------------------------------
mov bx, 2f8h ;base for COM2
;fall through to COMx_init
;--------------------------------------
COMx_init: ;common routine to init an 8250
;---------------------------------------
mov dx, bx
inc dx ;int enable reg
xor ah, ah
mov bx, ax
lea si, COMx_int_table[bx]
mov al, cs:[si]
out dx, al ;set it

add dx, 3 ;CR reg
mov al, 0bh
out dx, al ;DTR + Int Enable (user 1 pin)

ret

;-------------------------------------
COMx_int_table:
db 02h ;no protocol txrdy only
db 03h ;xon/xoff txrdy, rxrdy
db 0ah ;cts txrdy, delta modstat
db 03h ;etx/ack txrdy, rxrdy
db 0ah ;dsr txrdy, delta modstat
;
PAR_init:

ret ;for now
;
init_port endp

subttl srvUART - handle the printer (hardware) interrupts
page
srvUART proc near

; Entry via hardware interrupt
; Exit -none-

;this routine handles the printer interrupt
assume cs:code, ds:nothing, es:nothing

push ax
push bx
push cx
push dx
push si

call protocol_check
jz notus

cmp prot_ready, FALSE
je notus

mov bx, buff_head ;buffer check
cmp bx, buff_tail ;empty?
jz su_empty ;-yep..

mov al, cs:[bx] ;get char to print
call inc_ptr
mov buff_head, bx ;store updated pointer

call out_char
jmp notus

su_empty:
mov stopped, TRUE ;set stopped flag

notus:
pop si
pop dx
pop cx
pop bx

mov al, EOI
out 20h, al ;send eoi to PIC
pop ax
iret
srvUART endp

subttl protocol_check - see if protocol is ready or blocked
page
protocol_check proc near

; Entry -none-
; Exit ZR if not TxRdy int.
; Protocol flag set/reset by protocol routines if COMx port.

assume cs:code, ds:nothing, es:nothing

;uses:
; protocol
;
; Protocol routines set 'stopped' when protocol is disabled.
; Reset 'stopped' when protocol is enabled.
; Return Zero flag set if no character should be printed on
; this interrupt. (ie. this was not a txrdy)
;
push ax
push dx

cmp port, 02h ;LPT# port?
jae pc_ret2 ;yes - no protocol, always ready

mov bl, port ;set up int id byte for prot routines
and bl, 1
mov bh, 0
add bl, bl

lea si, port_base[bx]
mov dx, cs:[si]

inc dx
inc dx
in al, dx ;grab int id register

dec dx
dec dx ;leave base port in dx for protocol routines

lea bx, pc_return ;ON protocol GOSUB ....
push bx

mov bl, protocol
add bl, bl
mov bh, 0
lea si, pc_offset[bx]
jmp word ptr cs:[si]

pc_return:
and al, ITxRdy ;set zr flag if not TxRdy
;prot routines will force TxRdy if restarting...
pop dx
pop ax
ret
pc_ret2:
mov al, ITxRdy ;force TxRdy for parallel port
jmp pc_return

pc_offset:
dw offset p_None
dw offset p_XON
dw offset p_CTS
dw offset p_ETX
dw offset p_DSR

protocol_check endp
subttl p_None - handle no-protocol option
page
p_None proc near
assume cs:code, ds:nothing, es:nothing

; Entry al = int id byte
; Exit -same-

;supports printers with no protocol.
;assumes they can handle full UART speed.

ret ;Nothing needed here...

p_None endp

subttl p_XON - XON/XOFF protocol
page
p_XON proc near

; Entry al = int id byte
; dx = base port address
; Exit -all regs intact-

assume cs:code, ds:nothing, es:nothing
push bx

mov bl, al
and al, IRxRdy ;was it RxRdy?
jz pxreturn

in al, dx ;read the character
and al, 07fh ;strip hi bit if present
mov bh, FALSE ;flag for 'prot_ready' if XOFF

cmp al,SPECIAL ;a cntr p
jnz try_xon_off

mov bh,prot_ready
xor bh,0ffh
jmp pxset

try_xon_off:
cmp al, XOFF
je pxset

mov bh, TRUE ;flag if XON
cmp al, XON
jne pxreturn ;char not valid in protocol, ignore

or bl, ITxRdy ;we have to print a char to get started again.
pxset:
mov prot_ready, bh
pxreturn:
mov al, bl ;restore int id byte

pop bx
ret

p_XON endp

subttl p_CTS - handle CTS protocol
page
p_CTS proc near

; Entry al = int id byte
; dx = base port address
; Exit -intact-

assume cs:code, ds:nothing, es:nothing

push bx

mov bl, al
or al, al ;al = 0?
jnz pcreturn

add dx, 6
in al, dx ;modem status register
sub dx, 6 ;put it back

and al, CTS ;cts bit
mov bh, FALSE
jz pcset

mov bh, TRUE
or bl, ITxRdy
pcset:
mov prot_ready, bh
pcreturn:
mov al, bl

pop bx
ret

p_CTS endp

subttl p_ETX - handle ETX/ACK protocol
page
p_ETX proc near
assume cs:code, ds:nothing, es:nothing

xor ah, ah
ret
p_ETX endp

subttl p_DSR - handle DSR protocol
page
p_DSR proc near

; Entry
;
; Exit

assume cs:code, ds:nothing, es:nothing
push bx

mov bl, al
or al, al
jnz pdreturn

add dx, 6
in al, dx ;modem status register
sub dx, 6

and al, DSR ;dsr
mov bh, FALSE
jz pdset

mov bh, TRUE
or bl, ITxRdy
pdset:
mov prot_ready, bh
pdreturn:
mov al, bl

pop bx
ret

p_DSR endp

subttl out_char - send char in al to appropriate port
page
out_char proc near

; Entry al = char to print
; Exit -none-

assume cs:code, ds:nothing, es:nothing

;uses:
; port

push bx
push dx
push si

cmp port, 02h ;LPT#?
jae oc_par ;yes - special handling

mov bl, port
add bl, bl
mov bh, 0
lea si, port_base[bx]
mov dx, cs:[si]

oc_cont1:
out dx, al

oc_ret:
pop si
pop dx
pop bx
ret

oc_par:
push es
mov cl, port
mov ch, 0
mov si, cx ;printer number
dec si ;-2 to index par printer table
dec si

shl si, 1
mov bx, 0
mov es, bx
assume es:abs0
mov dx, es:printer_base[si]
pop es

or dx, dx ;is it there?
jz oc_ret ;nope - bit bucket

out dx, al ;send char
inc dx ;status port

in al, dx ;get status for later use
mov ah, al

mov al, 1dh ;strobe + int enable
inc dx
out dx, al
mov al, 1ch ;strobe off + int enable
out dx, al
jmp oc_ret

port_base label word
dw 3f8h ;COM1
dw 2f8h ;COM2

out_char endp
;
; =================================================================
;
subttl inc_ptr - increment a buffer pointer
page
inc_ptr proc near

; Entry bx = buffer pointer
; Exit bx = (bx + 1) mod buffer size

assume cs:code, ds:nothing, es:nothing

inc bx
cmp bx, buff_end
jne inc_ptr_ret
mov bx, buff_start
inc_ptr_ret:
ret
inc_ptr endp
;
; ================================================================
;
subttl buffer area - init routines are placed here
page
buffer label byte

; These routines are overlayed by the data buffer

init proc near

; Entry From command.com - ds = c
; Exit Spooler installed or status returned.

assume cs:code, ds:code, es:nothing

lea dx, signon
mov ah, 09h ;print sign-on msg (w/ cpyrght)
int 021h

call parse ;parse the command line

cli
call set_uart_int
call init_port ;enable interrupts on port, PIC
call init_protocol ;do any first time stuff

xor ax, ax
mov es, ax
assume es:abs0
mov word ptr int_17, offset srv17
mov word ptr int_17+2, cs

lea dx, buffer ;set up buffer ptrs
mov buff_start, dx
add dx, buff_size ;make pointer to end of buffer
mov buff_end, dx

push cs
pop ds

call show_status ;say whats going on

sti ;re-enable interrupts
int 27h ;term_resident

signon db CR,LF,'SPOOL - (C) Copyright 1985 USRobotics',CR,LF,'$'

init endp
subttl parse - parse the command line options
page
parse proc near

; Entry ds = cs
; Exit Returns if spool needs to be installed.
; Else displays proper msgs and prog term

assume cs:code, ds:code, es:nothing

;this routine sets the following parms:
; port
; protocol
; buff_size

push ds
pop es

call chkinst ;set up es_save

cld

mov noparms, byte ptr 0ffh ;none found yet

mov cl, byte ptr ds:[80h] ;parm string length
cmp cl,0
jnz parm_there
jmp parse_no_more
parm_there:
xor ch, ch
mov di, 81h ;ds:di = parm string addr
parse1:
cmp byte ptr ds:[di],'/'
jz found_switch
cmp byte ptr ds:[di],'-'
jz found_switch
cmp byte ptr ds:[di],'?'
jnz not_usage
call usage
mov noparms,0 ;we got a switch
not_usage:
inc di
loop parse1

jmp parse_no_more
found_switch:
inc di
dec cx

or cx, cx ;hit end of string?
jz parse_no_more

mov bl, ds:[di] ;grab the parm
and bl, 0dfh ;force upper case
lea dx, parse_cont ;fake on_gosub
push dx

cmp bl, 'C' ;clear buff cmd
jnz not_clear ;** fake conditional long jump **
jmp clearbuff
not_clear:
mov noparms, byte ptr 000h
cmp bl, 'P' ;port
jnz not_port
jmp setport
not_port:
cmp bl, 'H' ;handshaking (protocol)
jnz not_prot
jmp setprotocol
not_prot:
cmp bl, 'B' ;buffer size
jnz not_buff
jmp setbuffsize
not_buff:
cmp bl, 'R' ;Rate =
jnz not_rate
jmp set_rate
not_rate:

pop dx ;trash faked return address
call usage ;give help message and quit
exit
parse_cont:
jmp parse1 ;parse the next command

parse_no_more:
cmp noparms, byte ptr 00h ;any parms?
jz pnm2 ; -we got parms, go install
call chkinst ;are we installed?
jnz pnm3 ;nope - give usage msg
call show_status
exit
pnm3:
call usage
exit
pnm2:
call chkinst ;are we already installed?
jnz pnm4

lea dx, msgalrdyin
mov ah, 09h
int 021h
exit
pnm4:
cmp port, 2
jl pnm5
mov protocol, 0 ;force no protocol for parallel ports
pnm5:
;everythings ok - return and install.
ret

msgalrdyin db '** Already Installed **',CR,LF,'$'

parse endp

subttl usage - print usage message
page
usage proc near

; Entry ds = cs
; Exit -none-

assume cs:code, ds:code
lea dx, msguse
mov ah, 09h ;print string
int 021h ;do it

ret

msguse:
db 'Usage:',CR,LF,LF
db ' spool Display Current Status',CR,LF
db LF
db ' spool /P /H /B /R Install Spool With Options',CR,LF
db ' /P L=LPT [1,2,3] Port',CR,LF
db ' C=COM [1,2]',CR,LF
db ' /H X=Xon/Xoff Protocol',CR,LF
db ' C=CTS',CR,LF
db ' D=DSR',CR,LF
db ' N=NONE',CR,LF
db ' /B #=SIZE Buffer Size',CR,LF
db ' /R=baud,parity,wordlen,stopbits',CR,LF
db LF
db ' spool /C Clear current spool buffer',CR,LF
db eol

;; db ' ALONE Display Current Status',CR,LF
;; db ' ? HELP SCREEN',CR,LF,LF,LF,eol
;; db ' /C Clear Current Print Buffer',CR,LF
;; db ' E=ETX/ACK',CR,LF

usage endp

subttl show_status - display current spooler status
page
show_status proc near

; Entry -none-
; Exit Status displayed on stdout

assume cs:code, ds:code, es:code

push ax
push cx
push dx
push si
push di
push ds
push es

push cs
pop es

mov ds,es_save
mov cx,data_len
mov si,offset data_start
mov di,si
rep movsb

push cs
pop ds

mov cx, buff_size
lea si, msgstatusbs
call itoa

mov cx, buff_tail
cmp cx, buff_head
jae st2
add cx, buff_size
st2:
sub cx, buff_head
lea si, msgstatusused
call itoa

mov ax, cx
mov cx, buff_size
sub cx, ax
lea si, msgstatusleft
call itoa

mov al, port
cbw
mov si, ax
shl si, 1
shl si, 1

add si, offset s_ptab
lea di, msgstatusp
mov cx, 4
repz movsb

mov al, protocol
cbw
mov si, ax
mov cl, 3
shl si, cl ;* 8 for table index

add si, offset s_htab
lea di, msgstatush
mov cx, 8
repz movsb

lea dx, msgstatus
mov ah, 09h
int 21h

pop es
pop ds
pop di
pop si
pop dx
pop cx
pop ax

ret

msgstatus db 'Buffer size: '
msgstatusbs db '00000 bytes', CR, LF
db 'Used: '
msgstatusused db '00000 bytes', CR, LF
db 'Left: '
msgstatusleft db '00000 bytes', CR, LF
db CR, LF
db 'Output Port: '
msgstatusp db 'pppp', CR, LF
db 'Protocol: '
msgstatush db 'hhhhhhhh', CR, LF
db '$'

s_ptab db 'COM1','COM2','LPT1','LPT2','LPT3'
s_htab db 'None ','XON/XOFF','CTS ','ETX/ACK ','DSR '

show_status endp

subttl chkinst - return z if already installed
page
chkinst proc near

; Entry ds = cs
; Exit ZR set if already installed, else NZ.

assume cs:code, ds:code
push es
push ds

mov ah,0
mov dx,3 ;printer # 3
mov bx,'S'*256+'P'
int 17h

mov es_save,es ;save this segment
cmp bx,0 ;is it there?
jz installed ;already installed

mov es_save,ds ;here we are now
installed:

pop ds
pop es
ret

chkinst endp

subttl clearbuff - clear spool buffer
page
clearbuff proc near

; Entry Spool must be loaded.
; Exit Buffer ptrs set back to buffer start

push ds
mov ds,es_save

assume ds:code
mov ax, word ptr buff_start ;ptr to beginning of buffer
mov word ptr buff_head, ax ;stuff into head and tail ptrs
mov word ptr buff_tail, ax

pop ds
ret

clearbuff endp

subttl setprotocol - set the protocol for the command line
page
setprotocol proc near

; Entry ds:di = ptr to 'h' on command line
; Exit 'protocol' set if valid, else prog term

assume cs:code, ds:code
push ax
push di
push cx

inc di
mov al, ds:[di] ;grab protocol parm (char)

cmp al, CR ;look for premature EOL
je sp_bad2

mov msgbadhc, al ;put in err msg just in case

and al, 0dfh ;force upper case

lea di, sp_tab1
mov cx, sp_tab1len

repnz scasb ;find table entry
jnz sp_bad ;not found - not valid

sub di, offset sp_tab1 ;get table position
dec di ;went 1 too far.
mov ax, di
mov protocol, al

pop cx
pop di
pop ax
ret

sp_bad:
lea dx, msgbadh
sp_msg:
mov ah, 09h
int 021h

exit

sp_bad2:
lea dx, msgnoh
jmp sp_msg

msgnoh db '** Missing protocol parm **',CR,LF,'$'

msgbadh db '** Bad protocol parm ('
msgbadhc db 20,') **',CR,LF,'$'

sp_tab1 db 'NXCND'
;Note: ^ this char should be 'e' when etx/ack is enabled.
;sp_tab1 db 'NXCED'

sp_tab1len equ $-sp_tab1

setprotocol endp

subttl setport - set 'port' from command line
page
setport proc near

; Entry ds:[di] = ptr to 'p' on cmd line
; Exit 'port' set if valid, else prog term

push ax
push bx
push cx
push dx
push si
push di

mov si, di
inc si
lodsb ;get port type (lpt, com)

cmp al, CR ;look for early EOL
je spnoparm
mov msgbadportc, al ;put char in error msg, just in case

and al, 0dfh ;make upper case

mov bl, 0 ;base code for com ports
cmp al, 'C'
je spok
mov bl, 2 ;base code for par ports
cmp al, 'L' ;was it lpt?
jne spexit ;nope - print error msg
spok:
lodsb ;grab port number 1,2,3
cmp al, CR ;check for early EOL
je spnoparm

mov msgbadportc+1, al ;just in case
sub al, '1' ;make it binary, zero based
mov bh, 2 ;max for lpt ports
cmp bl, 2 ;lpt port specified?
je spok2
dec bh ;max for com ports = 1
spok2:
cmp al, bh ;valid port number?
ja spexit ;with error msg
add al, bl ;final port code
mov port, al ;store port code for int routines

pop di
pop si
pop dx
pop cx
pop bx
pop ax

ret

spexit:
lea dx, msgbadport
spexit2:
mov ah, 09h
int 021h
exit

spnoparm:
lea dx, msgnoparm
jmp spexit2

msgnoparm db '** Missing port parm **',CR,LF,'$'

msgbadport db '** Bad port parm ('
msgbadportc db ' ) **',CR,LF,'$'

setport endp

subttl setbuffsize - set buffer size from command line
page
setbuffsize proc near

; Entry ds:[si] = ptr to 'b'
; Exit 'buff_size' set if valid, else prog term

push ax
push cx
push dx
push si
push di

mov si, di
inc si
call atoi

cmp cx, 64 ;max 64k buffer
ja sbexit ;req'ed too much

cmp cx, 0 ;zero not valid either
je sbexit

mov ax, cx ;make it Kbytes
mov cl, 10 ;log 10 1024
shl ax, cl

mov cx,0fff0h
sub cx,offset buffer

cmp ax, 0 ;see if they wanted 64k
je sbs3 ;yes - set max buffer size

cmp ax,cx
jb sbs2
sbs3:
mov ax,cx
sbs2:
mov buff_size, ax ;set buff size for int routines

pop di
pop si
pop dx
pop cx
pop ax

ret

sbexit:
lea si, msgsbc
call itoa ;insert number into msg
lea dx, msgsb
mov ah, 09h
int 021h
exit

msgsb db '** Bad buffer size ('
msgsbc db ' ) **',CR,LF,'$'

setbuffsize endp

subttl itoa - convert an unsigned integer to its ASCII representation
page
itoa proc near

; Entry cx = unsigned integer to be converted
; ds:[si] = destination of ASCII string
; Exit ds:[si] = end of string +1
; Trashes -none-

push ax
push bx
push cx
push dx
push di

mov di, si ;need to use di for string ops
mov ax, cx
mov cx, 10000 ;max int = 64k
mov bx, 10 ;constant for finding new power of ten
itoa1:
mov dx, 0 ;zap hi byte for 32-bit divide
div cx ;calc next digit
add al, '0' ;make ASCII
stosb ;out to buffer, auto inc

push dx ;dx = ax mod cx

mov dx, 0
mov ax, cx ;calc new power of 10
div bx

or ax, ax ;done yet?
jz itoadone

mov cx, ax ;load new power of ten
pop ax ;remainder from previous calc for new calc
jmp itoa1 ;do next digit
itoadone:
pop ax ;trash final remainder of zero

mov si, di
pop di
pop dx
pop cx
pop bx
pop ax

ret
itoa endp

subttl atoi - convert ASCII char string to unsigned int
page
atoi proc near

; Entry ds:[si] = ptr to ASCII string
; Exit cx = integer representation of string
; ds:[si] = end of string +1
; Trashed -none-

push ax
push bx
push dx

mov bx, 10 ;constant
mov ax, 0 ;init sum
atoiagain:
push ax ;hold intermediate result
lodsb ;grab nexr char

cmp al, '0' ;range check
jb atoidone
cmp al, '9'
ja atoidone

sub al, '0' ;make binary
cbw ;make it a full word
mov dx, ax ;hold it...
pop ax
push dx ;current digit onto stack
mul bx ;intermediate result * 10
pop dx ;ignore anything above 16 bits
add ax, dx ;add in current digit
jmp atoiagain ;do next character
atoidone:
dec si ;bring bad char back into si range
pop cx ;put result into return register

pop dx
pop bx
pop ax

ret
atoi endp


subttl set_uart_int - stuff addr of srvUART in vector table
page
set_uart_int proc near
assume cs:code, ds:nothing, es:nothing
xor ax, ax
mov es, ax

mov bl, port
xor bh, bh

shl bx, 1 ;*2 for word indexing
mov bx, cs:word ptr comint_table[bx]
mov ax,offset srvUART
mov es:[bx], ax
mov es:[bx][2], cs
ret

comint_table:
dw 0ch * 4 ;com1 int
dw 0bh * 4 ;com2 int
dw 0fh * 4 ;par int
dw 0fh * 4 ;all par ports share this int
dw 0fh * 4

set_uart_int endp
;
; ================================================
;
subttl init_protocol - first time setup stuff for protocols
page
init_protocol proc near
assume cs:code, ds:code, es:nothing

; Entry -none-
; Uses protocol, port
; Exit -Protocol initialazation completed-

push ax
push bx
push dx

cmp port, LPT1
jae ip_exit ;no init for parallel ports

mov bl, protocol
mov bh, 0
shl bx, 1

call ip_tab[bx]

ip_exit:
pop dx
pop bx
pop ax

ret

ip_tab label word
dw offset ip_none ;no protocol
dw offset ip_none ;xon/xoff
dw offset ip_CTS ;cts
dw offset ip_none ;etx/ack
dw offset ip_DSR ;dsr

init_protocol endp
;
; ======================================
;
subttl ip_xxxx - protocol init routines
page
ip_none proc near
mov prot_ready, TRUE ;always ready
ret
ip_none endp
;
; ======================================
;
ip_CTS proc near
mov bl, port ;get printer base address
mov bh, 0
mov dx, port_base[bx]
mov al, 0 ;force int type 'mod status int'
call p_CTS ;do the real work
ret ;ignore return value
ip_CTS endp
;
; ======================================
;
ip_DSR proc near
mov bl, port
mov bh, 0
mov dx, port_base[bx]
mov al, 0
call p_DSR
ret
ip_DSR endp
;
; =====================================
; SET_RATE - set baud rate etc.
; =====================================
;
baud_rate dw 0
bauds dw 110,150,300,600,1200,2400,4800,9600 ;,1200
bauds_b dw 0,1,2,3,4,5,6,7 ;,4
baud_rate_str dw rate1,rate2,rate3,rate4,rate5,rate6,rate7,rate8;,rate5
rate1 db '110,',eol
rate2 db '150,',eol
rate3 db '300,',eol
rate4 db '600,',eol
rate5 db '1200,',eol
rate6 db '2400,',eol
rate7 db '4800,',eol
rate8 db '9600,',eol
;
parity db 0
parity_str dw parity1,parity2,0,parity3 ;,parity1
parity1 db 'N,',eol
parity2 db 'O,',eol
parity3 db 'E,',eol
;
stop_bit dw 0

stop_bit_str dw stop1,stop2 ;,stop1
stop1 db '1',CR,LF,LF,eol
stop2 db '2',CR,LF,LF,eol
;
wordlen dw 0
wordlen_str dw word1,word2 ;,word1
word1 db '7,',eol
word2 db '8,',eol
;
baud_str db CR,LF,'Com'
com_num db '#: Set to ',eol
;
set_rate proc near
;
assume cs:code,ds:code,es:code
;
push cs
pop ds
;
push es
mov es,es_save
;
mov al,es:port
mov ds:port,al
;
cmp al,2
pop es
;
jb go_rate
ret
go_rate:
mov si,di
;
; Find the '=' sign
;
rate_loop:
cmp byte ptr ds:[si],'=' ;well?
jz rate_found
cmp byte ptr ds:[si],CR ;done?
jz rate_ret
inc si
jmp rate_loop

rate_found:
inc si
cmp byte ptr ds:[si],' ' ;any spaces?
jz rate_found
;
call atoi
mov baud_rate,cx ;save the baud rate
parity_find:
cmp byte ptr ds:[si],','
jz comma
cmp byte ptr ds:[si],CR
jz rate_ret
inc si
jmp parity_find
;
comma:
inc si
cmp byte ptr ds:[si],CR
jz rate_ret
cmp byte ptr ds:[si],' '
jz comma
;
mov al,byte ptr ds:[si]
and al,0dfh
;
xor ah,ah
cmp al,'N'
jz got_parity
;
inc ah
cmp al,'O'
jz got_parity
;
add ah,2
cmp al,'E'
jz got_parity
;
mov ah,0 ;default none
got_parity:
mov parity,ah
;
get_wordlen:
cmp byte ptr ds:[si],CR
jz rate_ret
cmp byte ptr ds:[si],','
jz comma2
inc si
jmp get_wordlen

comma2:
inc si
cmp byte ptr ds:[si],' '
jz comma2
;
call atoi
mov wordlen,cx
get_stop_bit:
cmp byte ptr ds:[si],CR
jz rate_ret
cmp byte ptr ds:[si],','
jz comma3
inc si
jmp get_stop_bit

comma3:
inc si
cmp byte ptr ds:[si],' '
jz comma3

call atoi
mov stop_bit,cx
rate_ret:
;
; If invalid, set to default
;
mov ax,baud_rate
mov bx,0 ;offset of bauds
b_rate_test:
cmp bauds[bx],ax
jz got_rate
add bx,2
cmp bx,16
jnz b_rate_test
mov bx,10
got_rate:
mov ax,bauds_b[bx] ;get what is there
mov baud_rate,ax ;set it
;
; ======
; skip do parity
; ======
;
mov ax,wordlen
cmp ax,8
jz ok_wl
cmp ax,7
jz ok_wl

mov ax,8
ok_wl:
sub ax,5 ;2 or 3 (7,8)
mov wordlen,ax
;
; ======
; do the stop bits
; ======
;
mov ax,stop_bit
cmp ax,1
jz ok_st
cmp ax,2
jz ok_st

mov ax,1
ok_st:
dec ax
mov stop_bit,ax
;
mov al,port
mov com_num,al
add com_num,'1'
;
lea dx,baud_str ;Comm Port Set to
mov ah,9
int 21h
;
mov bx,baud_rate
shl bx,1
mov dx,baud_rate_str[bx]
mov ah,9
int 21h
;
mov bl,parity
xor bh,bh
;
shl bx,1
mov dx,parity_str[bx]
mov ah,9
int 21h
;
mov bx,wordlen
sub bx,2
shl bx,1
mov dx,wordlen_str[bx]
mov ah,9
int 21h
;
mov bx,stop_bit
shl bx,1
mov dx,stop_bit_str[bx]
mov ah,9
int 21h
;
mov ax,baud_rate
mov cl,2
shl ax,cl
or al,parity
shl ax,1
or ax,stop_bit
mov cl,2
shl ax,cl
or ax,wordlen
;
mov dl,port
xor dh,dh
;
int 14h
;
ret
set_rate endp

code ends
end start


  3 Responses to “Category : Assembly Language Source Code
Archive   : USRSPOOL.ZIP
Filename : USRSPOOL.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/