        title netclock


cseg    segment para public 'code'

        org 100h

        assume cs:cseg,ds:cseg,es:nothing



entry   proc far


su1:
  call parms                 ;read command line
  call clock1                ;read the remote clock, set here
  mov ah,4Ch                 ;exit to DOS
  int 21h

                             ;return code    0=clock set ok
                             ;               1=link did not respond
                             ;               2=network not installed
                             ;               3=remote clock read was bad
                             ;               4=error writing local clock

entry  endp



;page
subs proc near
;........................... clock routine ..................................

clock1:
  push cs                    ;ds=cs
  pop ds
  call test5C                ;make sure int 5C is valid
  jnz test1a                 ;it isn't:        it is-->
  test msgmode,1             ;are we printing messages?
  jz t0a                     ;yes:   no-->
  mov si,offset msg4         ;print "NETWORK NOT INSTALLED"
  call outstr

t0a:
  mov al,2                   ;return code (2) = network not installed
  ret                        ;exit

test1a:
  mov ah,4                   ;ah = command "alive"
  mov al,cs:comnum           ;al = com port link (0=default)
  mov cx,cs:wait             ;cx = wait count in char times 1..255

  push dx
  mov dx,1234h
  int 5Ch                    ;execute network request
  pop dx

  push cs                    ;ds=cs
  pop ds
  or al,al                   ;things go ok?  (al=0 if so)
  jz t2                      ;no:   yes-->

t1:
  test msgmode,1             ;are we printing messages?
  jz t1a                     ;yes:   no-->
  mov si,offset msg1         ;print "COMx LINK IS DEAD"
  call outstr
  mov si,offset msg3
  call outstr

t1a:
  mov al,1                   ;return code (1) = dead network link
  ret                        ;exit

;. . . . . . . . . . . . . . network is alive . . . . . . . . . . . . . . .
t2:
  test msgmode,1             ;are we printing messages?
  jz t2a                     ;yes:    no-->
  mov si,offset msg5         ;print "NETWORK CLOCK READ"
  call outstr
                             ;now read remote clock:
t2a:
  mov parms5C+2,cs           ;set rqh pointer seg
  mov rqh+16,cs              ;set transfer addr seg
  mov di,cs                  ;es:di--> parameter list
  mov es,di
  mov di,offset parms5C
  mov ah,0                   ;ah = command (normal write)
  mov al,cs:comnum           ;al = com port

  push dx
  mov dx,1234h
  int 5Ch                    ;execute network request
  pop dx

  push cs                    ;ds:di--> request header returned
  pop ds
  mov di,offset rqh
  mov ax,[di+3]              ;ax = status word
  test ax,8000h              ;any errors?
  jz t2c                     ;yes:      no-->
  test msgmode,1             ;are we printing messages?
  jz t2b                     ;yes:    no-->
  mov si,offset msg6         ;print "ERROR READING REMOTE CLOCK"
  call outstr

t2b:
  mov al,3                   ;return code (3) = clock read was bad
  ret

;. . . . . . . . . . . . . . got good read of remote clock . . . . . . . . . .

t2c:
  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 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?
  mov al,0                   ;assume good
  jz t2d                     ;yes:   no-->
  mov al,4                   ;return code (4) = error writing local clock
  test msgmode,1             ;are we printing messages?
  jz t2d                     ;yes:    no-->
  mov si,offset msg7         ;print "ERROR WRITING LOCAL CLOCK"
  call outstr
  mov al,4                   ;return code (4) = error writing local clock

t2d:
  ret

;........................... test for valid 5C ...............................

test5C:
  push ds                    ;ds=abs0
  xor dx,dx
  mov ds,dx
  lds si,dword ptr ds:170h   ;get vector
  mov dx,ds                  ;is 0:0?
  or dx,si
;  jnz t5Cb                  ;will be valid signature in future
;  cmp word ptr [si-4],"EN"  ;(vector-4 = "NET?")
;  jnz t5Cb
;  cmp byte ptr [si-2],"T"

t5Cb:
  pop ds
  ret

subs endp


;page
setup proc near
;........................... Get setup parameters ............................

parms:
  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:
  cmp al,"O"                 ;*****  is ON:x ? *****
  jne parms2
  call nxtchar
  cmp al,"N"
  jne parms1a
  call nxtchar
  cmp al,":"
  jne parms1a                ;yes:                no-->
  call getnum                ;pickup number
  mov cs:comnum,dl           ;save COM number to use
  add dl,"0"
  mov cs:msg1+5,dl
  jmp parms1



parms2:
  cmp al,"M"                 ;*****  Is it PRINT MSG *****
  jne parms6
  call nxtchar
  cmp al,"S"
  jne parms1a
  call nxtchar
  cmp al,"G"
  jne parms1a                ;yes:                no-->
  mov cs:msgmode,1           ;messages on
  jmp parms1

;page


parms6:
  cmp al,"W"                 ;*****  is WAIT:n ? *****
  jne parms9
  call nxtchar
  cmp al,"A"
  jne parms6b
  call nxtchar
  cmp al,"I"
  jne parms6b
  call nxtchar
  cmp al,"T"
  jne parms6b
  call nxtchar
  cmp al,":"
  jne parms6b                ;yes:                no-->
  call getnum                ;pickup number
  test dh,0FFh               ;too big?
  jz parms6a                 ;yes:   no-->
  mov dx,255                 ;limit to 255

parms6a:
  mov cs:wait,dx             ;set wait count
  jmp parms1

parms6b:
  jmp parms1a

parms9:
  jmp parms1
          


;page
;........................... 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-->
  lodsb                      ;yes, get next one
  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-->
  xchg ax,dx
  mov ah,10                  ;decimal shift left
  mul ah
  xchg ax,dx
  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

setup endp

;page
;........................... CON string output ................................
outstr proc near

  lodsb
  or al,al
  jz o2
  mov ah,14
  push si
  int 10h
  pop si
  jmp outstr

o2: ret

outstr endp

;..............................................................................

lcall   dw 0           ;dword used for long call
        dw 0

comnum  db 0           ;COM link to use
wait    dw 100         ;count to wait for reply (in character times)


                       ;INT 5C normal character device parm list
parms5C dw rqh         ;ofs of request header (normal DOS)
        dw 0           ;seg of request header
        db "CLOCK$  "  ;8 char name of remote device


                       ;DOS request header:
rqh     db 22          ;len
        db 0           ;unit
        db 4           ;command = READ
        dw 0           ;status
        db 8 dup(0)    ;reserved
        db 0
        dw taddr       ;transfer addr
        dw 0
        dw 6           ;count
        dw 0


taddr   db 0,0,0,0,0,0 ;transfer address


msgmode db 0
msg1    db 13,10,"COMx LINK IS ",0
msg2    db "ALIVE",10,13,0
msg3    db "DEAD",10,13,0
msg4    db 13,10,"NETWORK NOT INSTALLED",13,10,0
msg5    db 13,10,"NETWORK CLOCK READ",13,10,0
msg6    db 13,10,"ERROR READING REMOTE CLOCK",13,10,0
msg7    db 13,10,"ERROR WRITING LOCAL CLOCK",13,10,0

cseg    ends
        end su1


