title netclock - LBL
cseg segment public 'code'
org 100h
assume cs:cseg,ds:cseg,es:nothing
;return code 0=good link
; 1=link did not respond
; 2=network not installed
; 3=remote clock read was bad
; 4=error writing local clock
entry proc far
su1: jmp su1a
entry endp
waitime db 9 ;9 ticks
targetnode db 0
thisnode db 0
retcode db 0
msgmode db 1
; INT 14h AH=0C0h (or LBL Command 0)
; DX=0AB000H (or LBL signature id)
;
; DS:SI--> db action (r/w) +0
; .... .111 = check "alive"
; .... 1... = driver hit
; 10.. .... = finished good (alive)
; 11.. .... = finished error (assume dead)
; 00.. .... = if timeout, assume dead
;
; db target node +1
; db channel +2
; db timeout +3
; db requesting node +4
; db type +5 (internal)
; db target node +6 (internal)
req db 7 ;0 action/flags
db 0 ;1 target node
db 0 ;2 channel
db 0 ;3 timeout in ticks, 0 = no timeout
db 0 ;4 requesting node (this node)
db 0 ;5 type, set to 0
db 0 ;6 internal
db 0 ;7 reserved
subs proc near
su1a:
call parms
call get_sysreq
jnc su1b
mov dx,offset msg2
jmp su3
su1b:
call getnodename
mov al,[si+1]
mov cs:thisnode,al
push cs
pop ds
mov si,offset req
mov byte ptr [si],7
mov al,targetnode
mov [si+1],al
mov byte ptr [si+2],1 ;channel 1 ... background fix:v1.0L
mov al,waitime
mov [si+3],al
mov al,thisnode
mov [si+4],al
mov byte ptr [si+5],0 ;sendout mode
mov dx,cs:netint_id
mov ah,cs:netint_cmd
call netint
test cs:req,8 ;did any driver trap it?
jnz w1 ;no: yes-->
;error in drivers, on node# bad
or cs:req,0C0h ;force done, error
jmp w1b
w1:
test cs:req,80h ;wait for done
jz w1
test cs:req,40h ;is error?
jnz w1b
cmp cs:req+3,0FFh ;is nul tick?
je su2 ;yes-->
mov cs:req+3,1 ;force only 1 tick more
w1a:
test cs:req,40h ;wait timeout error
jz w1a ;(else will set bit later after exit!)
mov cs:req,80h
jmp su2
w1b:
mov cs:retcode,1
su2:
push cs
pop ds
mov dx,offset msg0
mov al,cs:retcode
cmp al,0
je su3
mov dx,offset msg1
su3:
cmp cs:retcode,0
jne su3c
su3b:
call readclock
jc su3c
call setclock
su3c:
cmp cs:msgmode,1
jne su4
push cs
pop ds
mov ah,9
int 21h
su4:
mov ah,4ch
mov al,cs:retcode
int 21h
;transfer description: R/W DEVICE
;
;REQUEST:
;
;target node +0 HEADER
;sending node +1
;module id +2
;transaction# +3
;command = 18 +4
;
;00 +5 SPECIFIC
;source device# +6
;targ device name +7..14
;write count +15/16
;read count +17/18
;write data +19...
;
;
;
;ANSWER:
;
;target node +0 HEADER
;sending node +1
;module id +2
;transaction# +3
;command/code +4
; 92h = good
; D2h = bad
;
;00 +5 SPECIFIC
;source device# +6
;write status 0=ok +7/8
;count written +9/10
;read status +11/12
;count read +13/14
;read data +15..
c_transmitter equ $
db 0 ;action/flags 0
db 0 ;routing link 1
db 0 ;channel 2
db 0 ;timeout 3
dw 0 ;buffer ofs 4
dw 0 ; seg 6
dw 0 ;count 8
dw 0 ;current count 10
dd 0 ;exec addr 12
dw 0 ;link to companion 16
dw 0 ; " seg 18
dw 0 ; 20
dw 0 ; 22
dw 0 ; 24
reqpacket db 00 ;+0 target node filled in by net21
db 00 ;+1 sending node "
db 00 ;+2 module id "
db 00 ;+3 transaction# "
db 00 ;+4 command 18
db 0 ;+5 type 00
db 0 ;+6 source device#
db "CLOCK$ " ;+7..14 target name
dw 0 ;+15 write count
dw 0 ;+17 read count
taddr db 6 dup (0) ;+19 buffer
db 0,0
devicenum db 255
;........................... read from remote clock ........................
readclock:
mov si,offset reqpacket
mov al,cs:targetnode ;set target node
mov [si],al
mov byte ptr [si+4],18 ;command = CHAR I/O
mov byte ptr [si+5],0 ;always 0
mov al,cs:devicenum ;set this device number
mov [si+6],al
mov ax,6
mov [si+17],ax ;set read count = 6 bytes
mov word ptr [si+15],0 ;no write count
mov di,offset c_transmitter ;es:di--> requestor
push cs
pop es
mov word ptr es:[di+4],offset reqpacket ;set ptr to packet
mov es:[di+6],cs
mov byte ptr es:[di],0Eh ;command = char i/o transfer
mov word ptr es:[di+8],20 ;set packet count
call wait_answer ;send it, wait answer
jc read4 ;if error-->
lds si,dword ptr es:[di+4] ;ds:si--> answer packet
test byte ptr [si],40h ;is error in receiver?
jc read4 ;yes-->
mov ax,[si+11] ;get read status
test ax,8000h
jnz read3
mov cx,[si+13] ;get count transfered
cmp cx,6
jne read4
lea si,[si+15] ;ds:si--> bytes returned
mov word ptr cs:rqh+14,si ;setup seg:ofs of transfer addr
mov word ptr cs:rqh+16,ds
clc
ret
read3:
read4:
mov dx,offset msg6
mov cs:retcode,3 ;return code (3) = error reading remote clock
stc
ret
lcall dw 0,0
;DOS request header:
rqh db 22 ;+0 len
db 0 ;+1 unit
db 4 ;+2 command = READ
dw 0 ;+3 status
db 8 dup(0) ;+5 reserved .... ....
db 0 ;+13
dw taddr ;+14 transfer addr
dw 0 ;+16
dw 6 ;+18 count
dw 0 ;+20
;. . . . . . . . . . . . . . got good read of remote clock . . . . . . . . . .
setclock:
mov ah,52h ;get DOS var list
int 21h
lds si,dword ptr es:[bx+8] ;ds:si--> local clock$ device
push cs ;es:bx--> request header
pop es
mov bx,offset rqh
mov byte ptr es:[bx+2],8 ;command = write
mov word ptr es:[bx+3],0 ;zero status
mov word ptr es:[bx+18],6 ;6 byte transfer
mov ax,[si+6] ;get strategy address
mov cs:lcall,ax ;form long call dword
mov cs:lcall+2,ds
call dword ptr cs:lcall ;do strategy
mov ax,[si+8] ;get interrupt address
mov cs:lcall,ax ;form long call dword
call dword ptr cs:lcall ;do interrupt
mov ax,es:[bx+3] ;get status
test ax,8000h ;any errors?
jz t2d ;yes: no-->
mov dx,offset msg7 ;print "ERROR WRITING LOCAL CLOCK"
mov cs:retcode,4 ;return code (4) = error writing local clock
ret
t2d:
mov dx,offset msg0
ret
event1 db 16 dup(0) ;***
;........................... Wait for device to finish .......................
;es:di--> raw transfer requestor (tmt)
;cx = timeout
wait_answer:
call swap_ptrs ;ds:si--> raw transfer requestor (tmt)
call netlink_0 ;start it
call swap_ptrs ;es:di--> raw transfer requestor
les di,dword ptr es:[di+16] ;es:di--> answer requestor companion
mov cx,200 ;100 ticks
mov si,cs
mov ds,si
mov si,offset event1 ;ds:si--> timeout event
mov byte ptr [si],0 ;clear mode/flags
mov [si+1],cx ;set event countdown
call netlink_2 ;start countdown
sti
;. . . . . . . . . . . . . . LOOP: waiting
wait_ans2:
test byte ptr es:[di],80h ;is answer back?
jnz wait_ans3 ;no: yes-->
test byte ptr cs:c_transmitter,40h ;is error in tmtr?
jnz wait_ans2a ;no: yes-->
test byte ptr [si],80h ;is timeout?
jz wait_ans2 ;yes: no-->
wait_ans2a:
call wait_time ;forcs tick counter to end fix:v1.0m
stc ;ret error
ret
wait_ans3:
call wait_time ;forcs tick counter to end fix:v1.0m
clc
ret
;fix:v1.0m add to kill tick service
wait_time:
mov word ptr [si+1],9 ;set event countdown = 1 tick
wait_time2:
test byte ptr [si],80h ;is timeout?
jz wait_time2 ;yes: no-->
push es
pop ds
mov si,di
mov byte ptr [si],3 ;clear rcvr
call netlink_0 ;
push cs
pop ds
mov si,offset req
mov byte ptr [si],2 ;clr tmtr
call netlink_0 ;
ret
;.......................... swap_ptrs ...................................
swap_ptrs:
push di
push si
pop di
pop si
;........................... swap_esds ...................................
swap_esds:
push es
push ds
pop es
pop ds
ret
netintc:
mov dx,cs:netint_id
jmp netint
;........................... netlink_0 .......................................
netlink_0:
push dx
push ax
mov ah,cs:netint_cmd
call netintc
pop ax
pop dx
ret
;........................... netlink_2 .......................................
netlink_2:
push dx
push ax
mov ah,cs:netint_cmd+2
call netintc
pop ax
pop dx
ret
msg0 db "CLOCK SET TO NETWORK TIME.",13,10,"$"
msg1 db "NETWORK CLOCK Node is DEAD.",13,10,"$"
msg2 db "NETWORK is not properly installed!",13,10,"$"
msg6 db "ERROR READING NETWORK CLOCK",13,10,"$"
msg7 db "ERROR WRITING LOCAL CLOCK",13,10,"$"
;........................... Get setup parameters ............................
parms:
cld
push cs
pop es
push cs
pop ds
xor cx,cx ;cx will = # of chars in line
mov si,81h ;ds:si --> command line
mov cl,[si-1] ;get count
parms1:
call nxtchar ;get next char
jnc parms1a ;if no more, return
ret
parms1a:
parms2:
cmp al,"N" ;***** is NODE:x ? *****
jne parms3
call nxtchar
cmp al,"O"
jne parms2a
call nxtchar
cmp al,"D"
jne parms2a
call nxtchar
cmp al,"E"
jne parms2a
call nxtchar
cmp al,":"
jne parms2a
call getnum
mov cs:targetnode,dl
jmp parms1
parms2a:
jmp parms1a
parms3:
cmp al,"W" ;***** is WAIT:x ? *****
jne parms4
call nxtchar
cmp al,"A"
jne parms3a
call nxtchar
cmp al,"I"
jne parms3a
call nxtchar
cmp al,"T"
jne parms3a
call nxtchar
cmp al,":"
jne parms3a
call getnum
mov cs:waitime,dl
jmp parms1
parms3a:
jmp parms1a
parms4:
jmp parms1
netint_vec db 14h ;0
netint_id dw 0AB00h ;1/2
db 5 ;3
netint_cmd db 0C0h ;4
db 0C1h ;5
db 0C2h ;6
db 0C3h ;7
db 0C4h ;8
netint_fix equ $+1
netint:
int 14h
ret
;........................... get_sysreq .......................................
;The Little Big LAN will be able to use any
;interrupt to pass LAN system requests. NET00000
;keeps that information so that all drivers
;can lookup the system request interrupt.
;The device name NET0 is used.
net0name db "NET0",0
net0cmd1 db 1
get_sysreq:
push cs
pop ds
mov dx,offset net0name ;ds:dx--> device to read
mov ax,3D02h ;open for read/write
int 21h
jnc get_srq2 ;open ok-->
mov cs:retcode,2
ret
get_srq2:
mov bx,ax ;bx=handle
;- - - - - - - - - - - - ;can't be in cooked mode !!!
mov ax,4400h ;get device info
int 21h
test dl,80h ;must be char device
jz get_srq4 ;if not-->
or dl,20h ;binary mode
xor dh,dh ;dos fails if dh<>0!!!
mov ax,4401h ;set device info
int 21h
;- - - - - - - - - - - -
push cs
pop ds
mov dx,offset net0cmd1 ;command = set "read sysreq mode"
mov cx,1 ;1 byte
mov ah,40h ;write to device
int 21h
jc get_srq4
mov cx,9 ;9 bytes
push cs
pop ds
mov dx,offset netint_vec
mov ah,3Fh ;read sysreq info
int 21h
jc get_srq4
mov al,cs:netint_vec ;fix INT XX code
or al,al ;can't be INT 0!
jz get_srq4
mov byte ptr cs:netint_fix,al
mov ah,3Eh ;close
int 21h
clc
ret
get_srq4:
mov ah,3Eh ;close
int 21h
stc
ret
;........................... getnodename ....................................
getnodename:
push cs
pop ds
mov si,offset requestor
mov byte ptr [si],1 ;get node info
mov ah,netint_cmd+4
mov dx,netint_id
call netint
test byte ptr [si],40h ;error?
jz gnn2 ;yes: no-->
stc
ret
gnn2:
xor ah,ah
mov al,[si+1] ;get node#
or al,al ;is any?
jnz gnn3 ;no: yes-->
gnn3:
mov [si+1],al ;set node
ret
requestor equ $
db 64 dup (0)
;........................... Get next char ...................................
nxtchar:
jcxz nc10 ;if no more chars in buffer-->
lodsb ;get next char
dec cx ;decrement count remaining
cmp al,13 ;is CR ?
jz nc9 ;no: yes-->
cmp al,"a" ;force to CAPs
jc nc8
cmp al,"z"+1
jnc nc8
xor al,20h
nc8:
clc ;return good
ret
nc9:
dec si ;dont go passed CR
xor cx,cx ;no more chars
nc10:
stc ;return, none found
ret
;........................... Get number .....................................
getnum:
xor dx,dx ;init number = 0
gn1:
jcxz gn9 ;are any chars left? no--> fix:12/13/89
lodsb ;yes, get next one changed to new
dec cx ;dec # left
mov ah,al ;save char
sub ah,"0" ;adjust ascii to number
jc gn8 ;was char < "0" ? yes-->
cmp ah,10 ;is char > "9" ?
jnc gn8 ; yes-->
push ax
mov ax,10 ;decimal shift left
mul dx
mov dx,ax
pop ax
add dl,ah ;add in ones
adc dh,0
jmp gn1 ;see if more
gn8:
dec si ;restore buffer ptr
inc cx ;restore # remaining
gn9:
ret
;........................... gethexnum .......................................
gethexnum:
xor dx,dx
gh1:
call nxtchar
jc gh9
mov ah,al
sub al,"0"
jc gh8
cmp al,10
jc gh4
add al,"0"
sub al,"A"
jc gh8
cmp al,6
jnc gh8
add al,10
gh4:
shl dx,1
shl dx,1
shl dx,1
shl dx,1
add dl,al
adc dh,0
jmp gh1
gh8:
dec si
inc cx
gh9:
ret
uptr dw 0
;........................... ishexdigit ...................................
ishexdigit:
sub al,"A" ;is char A..F ?
jc ihd9
cmp al,6
jnc ihd9 ;yes: no-->
add al,10 ;al = A..F hex nibble
clc
ret
ihd9:
add al,"A"
stc
ret
;........................... isdecdigit ...................................
isdecdigit:
sub al,"0" ;is char out of range (too small) ?
jc idd9 ;no: yes-->
cmp al,10 ;is char 0..9?
jnc idd9 ;yes no-->
clc
ret
idd9:
add al,"0"
stc
ret
;........................... getanynum ....................................
getanynum:
push si ;save $ ptr
push cx
;find eos
geta1:
call nxtchar
jc geta2
call isdecdigit
jnc geta1
call ishexdigit
jnc geta1
geta2:
pop cx ;restore ptr
pop si
cmp al,"H" ;did number end on "H"ex ?
je geta3 ;no: yes-->
call getnum
ret
geta3:
call gethexnum
call nxtchar
ret
subs endp
cseg ends
end su1
Top of Programmer Stuff -or- Main Table of Contents -or- Top of Form