Category : Assembly Language Source Code
Archive   : IBMRS232.ZIP
Filename : RS232.INC

 
Output of file : RS232.INC contained in archive : IBMRS232.ZIP
page
;***********************************************************
;** **
;** Device Driver for RS232 communications **
;** Copyright (C) Texas Instruments 1986 **
;** Author: Greg Haley **
;** revisor: Joe McDaniel, Fein-Marquart **
;** **
;** THIS SOURCE CODE MAY BE DISTRIBUTED AND MODIFIED **
;** ONLY IF THE ORIGINAL COPYRIGHT AND AUTHOR CREDITS **
;** REMAIN INTACT. **
;** **
;** Project Start Date: 09/09/86 **
;** **
;** Re: 10/14/86 by Greg Haley **
;** Added more delays (jmp $+2) for more tolerant **
;** timing. Also increased stacks to 80 words for **
;** Business Pro compatibility. **
;** **
;** Re: 10/15/86 by Greg Haley **
;** The COMM chip is no longer initialized on every **
;** write request. **
;** **
;** Re: 10/23/86 by Greg Haley **
;** Added code to block interrupts while setting up **
;** and restoring the stack. **
;** **
;** Re: 11/07/86 by Greg Haley **
;** Added option to echo RS232 I/O to the CRT. **
;** **
;** Re: 11/13/86 by Greg Haley **
;** Save SI and AX when calling DOS fast write. **
;** Changed SAR's and SAL's to SHR's and SHL's. **
;** Added keyboard input in parallel with RS232 input. **
;** **
;** Re: 11/20/86 by Greg Haley **
;** Modified I/O channel commands so that a more **
;** standard structure could be used, and to make it **
;** easier to add new commands in the future. Also, **
;** all machine dependent code was moved to a seperate **
;** file to allow new machines to be added much more **
;** easily. **
;** **
;** Re: 12/29/86 by Greg Haley **
;** Fixed bug in XON-XOFF busy handling where XON **
;** was not sent to reset the busy condition. **
;** **
;** Re: 8/10/87 by Joe McDaniel **
;** 1. Fixed bugs in xon/xoff handling. It now works **
;** 2. Removed echoing options and keyboard input **
;** 3. Added interrupt driven transmit **
;** 4. Fixed bugs with RAW mode calls **
;** 4. Removed the TI version as I had no way to test **
;** whether it would still work. **
;** 5. Fixed the 19,200 baud stuff **
;** 6. Fixed circular buffer bugs **
;***********************************************************

cr equ 13
lf equ 10

com1_tbl: ;header for device
dw -1
dw -1
dw 1100000000000000B ; CHAR device with I/O control
dw strategy
dw entry
db 'AUX ' ; Device name to use

; command jump table
cmdtbl:
dw init
dw exit
dw exit
dw ioctl_in
dw read
dw nd_read
dw input_status
dw input_flush
dw write
dw write
dw output_status
dw exit
dw ioctl_out
dw exit ; open
dw exit ; close
dw exit
dw exit

oldss dw 0 ; Old SS reg
oldsp dw 0 ; Old SP reg
dw 80 dup (?) ; New stack
e_stack label word
ptrsav dd 0 ; DOS cmd block pointer
init_once db 0 ; flag for init
dcw_len db 0 ; DCW (0) or Length (not 0) mode
tx_cnt dw 0 ; count of bytes sent
page
;***********************************************************
;** Device Driver Entry **
;***********************************************************
cmdlen = 0 ;length of this command
unit = 1 ;sub unit specifier
cmd = 2 ;command code
status = 3 ;status
media = 13 ;media descriptor
trans = 14 ;transfer address
count = 18 ;count of blocks or characters
start = 20 ;first block to transfer

;***********************************************************
;** Strategy Routine **
;***********************************************************
stratp proc far

strategy:
mov word ptr cs:[ptrsav],bx
mov word ptr cs:[ptrsav+2],es
ret

stratp endp

;***********************************************************
;** Entry Routine **
;***********************************************************
entry:
cli ; disable ints
mov cs:word ptr oldss,ss
mov cs:word ptr oldsp,sp
mov sp,cs
mov ss,sp
mov sp,offset e_stack
sti ; enable ints
push si
push ax
push cx
push dx
push di
push bp
push ds
push es
push bx

lds bx,cs:[ptrsav] ;get pointer to i/o packet
mov al,byte ptr ds:[bx].cmd ; al = command

cbw
mov si,offset cmdtbl
add si,ax
add si,ax
cmp al,16
ja cmderr

les di,dword ptr ds:[bx].trans ; es:di = tranfer address
mov cx,ds:[bx].count ; cx=count

push cs
pop ds
cld

assume ds:code

jmp word ptr [si] ;go do command

page
;***********************************************************
;** Device Driver Exit **
;***********************************************************
bus$exit: ;device busy exit
mov ah,00000011b
jmp short done

cmderr:
mov al,3 ;unknown command error

err$exit:
mov ah,10000001b ;mark error return
jmp short done

exitp proc far

exit:
mov ax,0000000100000000b ; mark as done
done:
lds bx,cs:[ptrsav]
mov ds:word ptr [bx].status,ax ;mark operation complete

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

; restore stack
cli ; disable ints
mov ss,cs:word ptr oldss
mov sp,cs:word ptr oldsp
sti ; enable ints

ret ;restore regs and return
exitp endp

page
;***********************************************************
;** Write Routine **
;** **
;** ES:DI contain xfer adrs on entry **
;** CX contains num chars to write **
;** **
;** **
;***********************************************************
write proc near

jcxz write_2 ; if nothing to send, exit immediately

push es ; Move pointer to DS:SI
pop ds
mov si,di

mov dx,cs:word ptr tq_head ; get transmitter head into dx


send_chars:
mov ax,tran_limit ; see if room for more
cli
sub ax,cs:tq_len ; subtract current count
sti
jne write_1 ; there is still room

jmp write_2 ; no more room

write_1:
lodsb ; al now has char
mov di,offset tqueue ; Queue char
add di,dx ; add in tq_head value
mov cs:byte ptr [di],al ; store char in trans_buffer
inc dx ; update header pointer, too
and dx,tran_limit ; and adjust for overflow
mov cs:word ptr tq_head,dx ; update head
cli
inc cs:word ptr tq_len ; Adjust queue length
sti

loop send_chars ; look for more chars

write_2:
call update_count ; sets count=count-cx

cli
cmp cs:byte ptr xmit_busy,0 ; is transmitter busy?
je write_3
jmp write_4 ; it was, so we can just exit

write_3:
call xmit_mt ; force first character out
write_4:
sti
jmp exit
write endp

page
;***********************************************************
;** Non Destructive Read Routine **
;** **
;** On entry, ES points to buffer segment **
;***********************************************************
nd_read proc near
mov di,13 ; point to byte buffer

cmp cs:word ptr rq_len,0 ; Any chars in receive buffer?
jnz nd_read_1 ; Yes, continue
mov ah,00000011b ; Set busy & done
jmp done ; We're done

nd_read_1:
mov bx,offset rqueue ; Get queue ptr
mov dx,cs:word ptr rq_tail
add bx,dx ; point at char
mov al,byte ptr[bx] ; al now has char


stosb ; store char in buffer
jmp exit
nd_read endp

page
;***********************************************************
;** Get Input Status **
;***********************************************************
input_status proc near
cmp cs:word ptr rq_len,0 ; Any chars in receive buffer?
jnz xit_in_stat ; Yes, continue
mov ah,00000011b ; No, set busy & done
jmp done ; We're done

xit_in_stat:
jmp exit ; Normal exit code
input_status endp

page
;***********************************************************
;** Flush Input Buffer **
;***********************************************************
input_flush proc near
mov cs:word ptr rq_head,0 ; Head = 0
mov cs:word ptr rq_tail,0 ; Tail = 0
mov cs:word ptr rq_len,0 ; make queue length 0
jmp exit ; Normal exit code
input_flush endp

page
;***********************************************************
;** Get Output Status **
;***********************************************************
output_status proc near
cmp cs:byte ptr t_busy,0 ; Are we busy?
je xit_out_stat ; No, continue
mov ah,00000011b ; Set busy & done
jmp done ; We're done

xit_out_stat:
jmp exit ; Normal exit code
output_status endp

page
;***********************************************************
;** Read Routine **
;** **
;** ES:DI contain xfer adrs on entry **
;** CX contains num chars requested **
;***********************************************************
read proc near
cli
mov ax,cs:word ptr rq_len ; Any chars in recv buffer?
sti
or ax,ax
jnz read_1 ; Yes, continue
call update_count ; count=count-cx (therefore, 0)
jmp exit ; We're done

read_1:
; figure out how many chars to get
cmp ax,cx ; More than DOS buffer?
jg read_2 ; Yes, CX already has count
mov cx,ax ; No, only send what we have
lds bx,cs:[ptrsav] ;get pointer to i/o packet
mov word ptr ds:[bx].count,cx ;cx = count of bytes remaining
;to process

read_2:
mov dx,cs:word ptr rq_tail

read_3:
mov si,offset rqueue ; Get queue ptr
add si,dx ; point at char
mov al,cs:byte ptr[si] ; al now has char


stosb ; store char in buffer
inc dx
and dx,recv_limit ; wrap if >= limit
mov cs:word ptr rq_tail,dx ; update tail
cli
dec cs:word ptr rq_len ; Adjust queue length
sti
loop read_3 ; Loop again

call update_count ; count=count-[cx]

; reset busy if we can
cli
cmp cs:word ptr rq_len,not_busy_len ; Room for more chars?
sti
jg read_4 ; No, skip
mov cs:byte ptr r_busy,0 ; Yes, reset busy
mov al,xon
cli
call send_xon ; Send XON char if needed
sti
read_4:

jmp exit
read endp

page
;***********************************************************
;** Write I/O Control Channel **
;** **
;** ES:DI contain xfer adrs on entry **
;** CX contains count **
;***********************************************************
ioctl_out proc near
push es ; Move pointer to DS:SI
pop ds
mov si,di

cmp cx,2 ; Is it a DCW?
je ioo_1 ; Yes, continue
cmp cx,1 ; Is it a CSB?
jz ioo_nc0 ; Yes, continue
jmp exit ; No, exit

ioo_nc0:
lodsb ; Yes, get the byte

push cs ; DS = CS
pop ds

mov ah,al ; Update DCW/LEN mode
and ah,00000100b
mov dcw_len,ah

test al,00000001b ; Drop RS232 signals?
jnz ioo_nc1 ; No, skip
call de_init ; Yes, disconnect
mov byte ptr dcw_len,0 ; Reset to DCW mode
ioo_nc1:

test al,00000010b ; Flush input buffer?
jz ioo_nc2 ; No, skip
jmp input_flush ; Yes, go flush it
ioo_nc2:

jmp exit ; exit
ioo_1:
lodsw ; get DCW in AX

; make ds = cs
push cs
pop ds

; check for serial device
test ah,80h ; Serial device?
jnz ioo_2 ; Yes, continue
jmp exit ; No, exit
ioo_2:

call set_dcw ; Go set DCW

mov word ptr dcw,ax ; Save new DCW
call init_comm ; init comm chip
jmp exit

ioctl_out endp

page
;***********************************************************
;** Read I/O Control Channel **
;** **
;** ES:DI contain xfer adrs on entry **
;***********************************************************
ioctl_in proc near
cmp cx,2 ; Is it a word?
je is_2byte ; Yes, go get it
cmp cx,1 ; Is it a byte?
jne ioi_xit ; No, exit

xor al,al ; Clear status byte
or al,cs:byte ptr m_stat ; Update current modem status
stosb ; and pass it to DOS
jmp exit

is_2byte:
cmp cs:byte ptr dcw_len,0 ; DCW mode?
jz ioi_1 ; Yes, get DCW

mov ax,cs:rq_len ; No, get receive queue length
jmp short ioi_2

ioi_1:
mov ax,cs:dcw ; Get DCW
ioi_2:
stosw ; and pass it to DOS

ioi_xit:
jmp exit
ioctl_in endp

page
;***********************************************************
;** Return Number of Chars Processed **
;** **
;** CX contains number of characters NOT processed **
;***********************************************************
update_count proc near
push ds
push bx

lds bx,cs:[ptrsav] ;get pointer to i/o packet
sub word ptr ds:[bx].count,cx ;cx = count of bytes remaining
;to process

pop bx
pop ds
ret
update_count endp


  3 Responses to “Category : Assembly Language Source Code
Archive   : IBMRS232.ZIP
Filename : RS232.INC

  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/