home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / lan / netclk / srvclock.asm < prev    next >
Assembly Source File  |  1989-01-28  |  15KB  |  471 lines

  1.  
  2.             TITLE SRVCLOCK.ASM
  3.             PAGE 60,132
  4. ;.RM150/
  5. ;
  6. ; Revised version of SRVCLOCK previously published in PC Magazine.  Several
  7. ; changes have been made to the way a listen and send are  coordinated. 
  8. ; This version holds up better under heavy requests.
  9. ;
  10. ;
  11. ; Alan Queen (208) 384-9137
  12. ; Boise, ID  83712
  13. ; Last update: 03/18/88
  14.  
  15. CR            EQU    0DH        ;carriage return
  16. LF            EQU    0AH        ;line feed
  17. MAX_RETRY        EQU    3        ;maximum times to retry on startup errors
  18. LSN_BUFFER_LEN        EQU    16        ;length of LSN buffer
  19.                         ;increase this if any nodes return
  20.                         ;a '"RECEIVE" command failed' when 
  21.                         ;running NETCLOCK
  22. CODE    SEGMENT
  23.         ASSUME  CS:CODE,DS:CODE,ES:CODE
  24.         ORG     0100H
  25.  
  26. ENTRY:    JMP    INITIALIZE
  27.  
  28. ;-----------------------------------------------------------------------------
  29. ;Data to remain in resident portion below, startup data at end of program
  30. ;-----------------------------------------------------------------------------
  31. OLDTIMER        LABEL     DWORD              ;Old interrupt 1ch vector
  32. OLD1CH          DW     2 DUP (?)       ;
  33.  
  34. LSN_TAIL_PTR    DW    00                     ;Pointer to most recent session added
  35. LSN_HEAD_PTR    DW    00               ;Pointer to session to be sent
  36. LSN_BUFFER    DB    LSN_BUFFER_LEN dup(0)  ;Circular buffer for session numbers
  37. LSN_BUFFER_END    LABEL    WORD                   ;End of buffer
  38.  
  39. ALL_NAMES    DB     '*               ' ;MCB_CALLNAME for any node on listen
  40.  
  41. CLOCK        EQU    $           ;Clock data area
  42. YEAR        DW    0000H
  43. MONTH        DB    00H
  44. DAY        DB    00H
  45. HOURS        DB    00H
  46. MINUTES        DB    00H
  47. SECONDS        DB    00H
  48. HUNDREDTHS    DB    00H
  49.  
  50. STATUS_FLAGS    DB    0           ;Bit mapped flag 
  51. ;Status_Flags byte used as follows:
  52. ;
  53. ;            +----------- Listen needs reset (a listen has failed)
  54. ;     UNUSED    | +--------- ReSend is required (previous send failed)
  55. ;   | | | | |   | | +------- Timer called operation in process
  56. ;   0 0 0 0 0   0 0 0
  57. ;
  58. ;-----------------------------------------------------------------------------
  59. ; Message Control Blocks, This one for startup and listens  
  60. ;-----------------------------------------------------------------------------
  61. MCB        EQU    $        ;
  62. MCB_COMMAND    DB     00        ;The command to be performed
  63. MCB_RETCODE    DB    00        ;Command completion code
  64. MCB_LSN        DB    00        ;Local Session Number
  65. MCB_NUM        DB    00        ;Number of the name we are using
  66. MCB_BUFFER@    DW    0000        ;Address of the buffer for data sent 
  67.         DW    0000        ;and received (offset:segment format)
  68. MCB_LENGTH    DW    0000        ;Length of the buffer, updated by a receive
  69. MCB_CALLNAME    DB    '*               '    ;name we are calling (* = all)
  70. MCB_NAME        DB      'SRV_CLOCK       '    ;Our name, (names are 16 bytes long )
  71. MCB_RTO        DB    10        ;Receive time out (5 seconds)
  72. MCB_STO        DB    10        ;Send time out (also 5 seconds)
  73. MCB_POST@    DW    0000        ;Post at location for "no wait" commands
  74.         DW    0000        ;offset:segment format
  75. MCB_LANA_NUM    DB    00        ;Lan adapter number 00 for first 01 for second
  76. MCB_CMD_CPLT    DB    00        ;Command completion FFh during while in process
  77. MCB_RESERVE    DB    14 DUP(0)    ;
  78. ;
  79. ; Second MCB for send and hang up operations, fields similar to above
  80. ;
  81. MCB2        EQU    $        
  82. MCB_COMMAND2    DB     00        
  83. MCB_RETCODE2    DB    00        
  84. MCB_LSN2    DB    00        
  85. MCB_NUM2    DB    00        
  86. MCB_BUFFER@2    DW    0000        
  87.         DW    0000        
  88. MCB_LENGTH2    DW    0000        
  89. MCB_CALLNAME2    DB    16 dup(20h)    
  90. MCB_NAME2       DB      'SRV_CLOCK       '
  91. MCB_RTO2    DB    00        
  92. MCB_STO2    DB    00        
  93. MCB_POST@2    DW    0000        
  94.         DW    0000        
  95. MCB_LANA_NUM2    DB    00        
  96. MCB_CMD_CPLT2    DB    00        
  97. MCB_RESERVE2    DB    14 DUP(0)    
  98.  
  99.  
  100.  
  101. ;------------------------------------------------------------------------------
  102. ;INTERRUPT 1CH HANDLING ROUTINE. Execution comes here every timer tick
  103. ;------------------------------------------------------------------------------
  104. TIMER     PROC    NEAR
  105.     STI                                  ;enable interrupts
  106.         PUSHF                                ;save the flags
  107.         CALL     CS:DWORD PTR OLDTIMER       ;and call original timer routine
  108.     
  109.     TEST     CS:STATUS_FLAGS,00000001B  ;are we in a timer called procedure?
  110.     JNZ     T4               ;exit if so
  111.     OR    CS:STATUS_FLAGS,00000001B  ;otherwise set the "in process" bit on
  112.  
  113.     CALL    EOI               ;issue an end of interrupt to 8259 PIC
  114.  
  115.     CMP    CS:MCB_CMD_CPLT2,0FFH       ;Hangup still in process
  116.     JE    T2               ;if so check other flags
  117. T1:
  118.     CALL    CLOCKSEND           ;do the CLOCKSEND procedure
  119. T2:                    
  120.     TEST    CS:STATUS_FLAGS,00000100B  ;necessary to restart listen?
  121.     JZ    T3                 ;if not exit
  122.     CALL     RESET_LISTEN           ;if so do procedure
  123. T3:                    
  124.     AND    CS:STATUS_FLAGS,00001110B  ;set the "in process" bit off
  125. T4:                       ;
  126.         IRET                           ;Done - exit
  127. TIMER    ENDP
  128.  
  129. ;------------------------------------------------------------------------------
  130. ; Issue end of Interrupt to 8259 PIC
  131. ;------------------------------------------------------------------------------
  132. EOI    PROC    NEAR
  133.     PUSH    AX
  134.     MOV    AL,20H
  135.     OUT    20H,AL
  136.     POP    AX
  137.     RET
  138. EOI    ENDP
  139. ;
  140. ;------------------------------------------------------------------------------
  141. ; Execution comes here when called by another node, completing the listen
  142. ;------------------------------------------------------------------------------
  143. LISTEN        PROC    NEAR
  144.         MOV    AX,ES            ;Netbios restores ES
  145.         MOV    DS,AX            ;use it to set DS
  146.  
  147.         CMP    MCB_RETCODE,0        ;listen complete OK? 
  148.         JNE    L2            ;if not restart listen
  149.  
  150.         MOV    BX,LSN_TAIL_PTR        ;get the tail pointer
  151.         INC    BX            ;add 1
  152.         CMP    BX,OFFSET LSN_BUFFER_END ;at the end of the buffer?
  153.         JNE    L1            ;if not proceed
  154.         SUB    BX,LSN_BUFFER_LEN    ;wrap to beginning if so
  155. L1:                        
  156.         CMP    BX,LSN_HEAD_PTR        ;buffer full? 
  157.         JE    L2            ;if so we cannot respond 
  158.         MOV    LSN_TAIL_PTR,BX        ;otherwise, set the tail ptr 
  159.         MOV    AL,MCB_LSN        ;and move the session number
  160.         MOV    BYTE PTR [BX],AL    ;into the buffer
  161. L2:                        
  162.         LEA    SI,ALL_NAMES        ;replace the callers name
  163.         LEA    DI,MCB_CALLNAME        ;with an asterick (meaning any)
  164.         MOV    CX,16            ;
  165.     REPNZ    MOVSB                ;
  166.              MOV    BX,OFFSET MCB        ;Point BX to listen MCB block
  167.         INT     5CH            ;Netbios call
  168.         CMP    AL,0            ;immediate return OK?
  169.         JE    L3            ;exit if so
  170.         OR    STATUS_FLAGS,00000100B    ;else flag that we need new listen
  171. L3:
  172.         IRET
  173. LISTEN        ENDP
  174.  
  175.  
  176. ;------------------------------------------------------------------------------
  177. ; Execution comes here if reset listen bit set.  Called from timer.
  178. ;------------------------------------------------------------------------------
  179. RESET_LISTEN    PROC    NEAR
  180.         PUSH    AX            ;save registers used
  181.         PUSH    BX
  182.         PUSH    DS
  183.         PUSH    ES
  184.         PUSH    CS
  185.         POP    AX
  186.         MOV    DS,AX            ;set data
  187.         MOV    ES,AX            ;and extra segments
  188.  
  189.             MOV    BX,OFFSET MCB        ;Point ES:BX to listen MCB
  190.         INT     5CH            ;Netbios call
  191.         CMP    AL,0            ;command completed OK?
  192.         JNE    RL1            ;if not exit, restart flag still set
  193.         AND    STATUS_FLAGS,00001011B    ;else set the restart bit off
  194. RL1:
  195.         POP    ES            ;restore registers
  196.         POP    DS
  197.         POP    BX
  198.         POP    AX
  199.         RET
  200. RESET_LISTEN    ENDP
  201.  
  202. ;------------------------------------------------------------------------------
  203. ; send clock data to requesting node using a netbios send
  204. ;------------------------------------------------------------------------------
  205. CLOCKSEND    PROC    NEAR
  206.         PUSH    AX            ;save registers used
  207.         PUSH    BX
  208.         PUSH    DS
  209.         PUSH    ES
  210.         PUSH    CS
  211.         POP    AX
  212.         MOV    DS,AX
  213.         MOV    ES,AX
  214.  
  215.         TEST    STATUS_FLAGS,00000010B  ;Check immediate resend flag
  216.         JNZ    CS2            ;if needed resend same MCB2
  217.  
  218.         MOV    BX,LSN_HEAD_PTR        ;Compare Head pointer to tail
  219.         CMP    LSN_TAIL_PTR,BX        ;pointer, if equal, we do not have
  220.          JE    CS5            ;a requesting session. So exit.
  221.                         ;
  222.         INC    BX            ;we got the head ptr above, now add 1
  223.         CMP    BX,OFFSET LSN_BUFFER_END ;are we at the end of the buffer?
  224.         JNE    CS1            ;
  225.         SUB    BX,LSN_BUFFER_LEN    ;if so wrap
  226. CS1:                        ;
  227.         MOV    LSN_HEAD_PTR,BX        ;update head pointer
  228.         MOV    AL,BYTE PTR [BX]    ;get session number in AL
  229.         MOV    MCB_LSN2,AL        ;move it to MCB2
  230.  
  231. CS2:                        ;
  232.         MOV    MCB_COMMAND2,94H    ;send "no wait" command
  233.         MOV    MCB_POST@2,OFFSET HANGUP ;posting into HANGUP
  234.         MOV    MCB_POST@2+2,CS        ;proper segment
  235.         CALL    GET_TIME
  236.  
  237.         MOV    BX,OFFSET MCB2        ;point ES:BX at MCB
  238.         INT     5CH            ;netbios call
  239.         CMP    AL,0            ;immediate completion OK?
  240.         JE    CS4            ;exit with resend bit off
  241.         CMP    AL,22H            ;too many commands outstanding? 
  242.         JE    CS3            ;exit with resend bit on
  243.         CMP    AL,21H            ;interface too busy?
  244.         JE    CS3            ;exit with resend on
  245.         JMP    CS4            ;otherwise, we can't save it, move on
  246. CS3:                        ;
  247.         OR    STATUS_FLAGS,00000010B    ;set resend bit on
  248.         JMP    CS5            ;exit
  249. CS4:                        ;
  250.         AND    STATUS_FLAGS,00001101B    ;set resend bit off
  251. CS5:                        ;
  252.         POP    ES            ;restore registers
  253.         POP    DS
  254.         POP    BX
  255.         POP    AX
  256.         RET
  257.  
  258. CLOCKSEND        ENDP
  259.  
  260. ;------------------------------------------------------------------------------
  261. ;Execution "posts" here on final completion of "no wait" send from CLOCKSEND above.
  262. ;------------------------------------------------------------------------------
  263. HANGUP        PROC    NEAR            
  264.  
  265.         MOV    AX,ES            ;netbios restores ES
  266.         MOV    DS,AX            ;use to set DS
  267.  
  268.         MOV    MCB_POST@2,0        ;set post address off by
  269.         MOV    MCB_POST@2+2,0        ;setting fields to zero
  270.         MOV    MCB_COMMAND2,92H    ;Hang up command 'no wait'
  271.         LEA    BX,MCB2            ;Point ES:BX at MCB2
  272.         INT    5CH            ;Netbios call
  273.  
  274.         IRET                ;return from interrupt
  275. HANGUP        ENDP
  276.  
  277.  
  278. ;------------------------------------------------------------------------------
  279. ; get date and time to send to requesting node  WORKS ON AT or similar CMOS ONLY!
  280. ;------------------------------------------------------------------------------
  281. GET_TIME    PROC    NEAR
  282.         XOR    AX,AX            ;clear AX
  283.         MOV    AL,09            ;09 = Year
  284.                 OUT    70H,AL            ;Real time clock at 70H
  285.         IN    AL,71H            ;returns at 71H
  286.                 CALL    BCD2BIN            ;convert to binary
  287.         ADD    AX,76CH            ;add 1900 decimal, only works
  288.                         ;until 1999
  289.         MOV    YEAR,AX            ;load buffer with year
  290.  
  291.         XOR    AX,AX
  292.         MOV    AL,08            ;get month
  293.         OUT    70H,AL            ;
  294.         IN    AL,71H            ;
  295.                 CALL    BCD2BIN            ;
  296.         MOV    MONTH,AL        ;
  297.  
  298.         XOR    AX,AX            ;
  299.         MOV    AL,07            ;get date of month
  300.         OUT    70H,AL            ;
  301.         IN    AL,71H            ;
  302.         CALL    BCD2BIN            ;
  303.         MOV    DAY,AL            ;
  304.  
  305.         XOR    AX,AX            ;
  306.         MOV    AL,04            ;get hours
  307.         OUT    70H,AL            ;
  308.         IN    AL,71H            ;
  309.         CALL    BCD2BIN            ;
  310.         MOV    HOURS,AL        ;
  311.  
  312.         XOR    AX,AX
  313.         MOV    AL,02            ;get minutes 
  314.         OUT    70H,AL            ;
  315.         IN    AL,71H            ;
  316.         CALL    BCD2BIN            ;
  317.         MOV    MINUTES,AL        ;
  318.  
  319.         XOR    AX,AX            ;
  320.         MOV    AL,00            ;get seconds
  321.         OUT    70H,AL            ;
  322.         IN    AL,71H            ;
  323.         CALL    BCD2BIN            ;
  324.         MOV    SECONDS,AL        ;
  325.         RET
  326. GET_TIME    ENDP
  327.  
  328. ;
  329. ;procedure to convert time as delivered from CMOS clock (binary coded decimal)
  330. ;to binary (as used by DOS function calls and NETCLOCK.EXE) (returns in AL)
  331. BCD2BIN        PROC    NEAR
  332.         PUSH    AX            ;save contents
  333.         AND    AL,0F0H            ;clear out low nibble
  334.         SHR    AL,1            ;divide by 16
  335.         SHR    AL,1            ;so that hi nibble is 
  336.         SHR    AL,1            ;now in lo position
  337.         SHR    AL,1            ;
  338.         MOV    BL,AL            ;hold in al
  339.         SHL    AL,1            ;multiply by ten, two here
  340.         SHL    AL,1            ;four
  341.         SHL    AL,1            ;eight
  342.         ADD    AL,BL            ;nine
  343.         ADD    AL,BL            ;ten
  344.         POP    BX            ;get previous AX contents
  345.         AND    BL,0FH            ;clear out hi nibble
  346.         ADD    AL,BL            ;add to total
  347.         RET
  348. BCD2BIN        ENDP
  349.  
  350.  
  351.  
  352. PROG_ENDS    EQU    $
  353.  
  354.  
  355.  
  356. ;------------------------------------------------------------------------------
  357. ;INITIALIZE prepares the program for residency.
  358. ;------------------------------------------------------------------------------
  359. INITIALIZE    PROC NEAR
  360. ;
  361. ; Check if interrupt 5C has a vector
  362. ;
  363.         PUSH    ES            ;save ES
  364.             MOV     AH,35H                  ;get interrupt 5C vector
  365.               MOV     AL,5CH
  366.                INT     21H
  367.         MOV    AX,ES
  368.         POP    ES            ;get back ES
  369.         CMP    AX,0            ;is segment 0
  370.         JNE    ADD_NAME        ;if not 0 some interface is present
  371.         LEA    DX,NETBIOS_ERR        ;else error message
  372.         JMP    ERROR            ;
  373. ;
  374. ;Add a name to the name table
  375. ;
  376. ADD_NAME:    MOV    MCB_COMMAND,30H        ;Command 30h adds a name
  377.         MOV    BX,OFFSET MCB        ;point ES:BX at MCB
  378.         INT     5CH            ;call netbios 
  379.         CMP    MCB_RETCODE,0        ;check for success
  380.         JE    SET_UP            ;continue if OK
  381.         CMP    MCB_RETCODE,0FBH    ;else check for netbios loaded
  382.         JNE    ADD1            ;
  383.         LEA    DX,NETBIOS_ERR        ;netbios error message
  384.         JMP    ERROR            ;
  385. ADD1:                        ;
  386.         LEA    DX,ADD_ERR        ;write add error message
  387.         JMP    ERROR            ;name that was not successful
  388. ;
  389. ;Set up MCB's with fixed information, initialize circular buffer 
  390. ;
  391. SET_UP:
  392.         MOV    MCB_BUFFER@2,OFFSET CLOCK ;buffer2 always points at clock data
  393.         MOV    MCB_BUFFER@2+2,DS    ;insure correct segment
  394.         MOV    MCB_LENGTH2,8        ;clock takes 8 bytes
  395.  
  396.         LEA     AX,LSN_BUFFER        ;Head and Tail pointers
  397.         MOV    LSN_HEAD_PTR,AX        ;start out pointing at the 
  398.         MOV    LSN_TAIL_PTR,AX        ;beginning of the circular buffer
  399.  
  400. ;
  401. ; do netbios listen with post set to procedure listen
  402. ;
  403.          MOV    MCB_COMMAND,91H        ;listen command to MCB 
  404.         MOV    MCB_POST@,OFFSET LISTEN ;set post at listen procedure
  405.         MOV    MCB_POST@+2,CS        ;CS in segment 
  406.             MOV    BX,OFFSET MCB        ;point ES:BX to block
  407.         INT    5CH            ;netbios call
  408.         CMP    AL,0            ;check for good return
  409.         JE    SET_VECTORS        ;if good set int vectors
  410. LISN_ERR_1:                    ;otherwise
  411.         MOV    MCB_COMMAND,31H        ;delete name command in MCB
  412.         INT    5CH            ;netbios call
  413.         CMP    AL,0            ;work OK?
  414.         JE    LISN_ERR_2        ;if so exit with error msg
  415.         INC    ERR_RETRY        ;else increment retry count
  416.         CMP    ERR_RETRY,MAX_RETRY    ;are we to max retry
  417.         JL    LISN_ERR_1        ;if not try again
  418. LISN_ERR_2:
  419.         MOV    DX,OFFSET LSN_ERR    ;else write error
  420.         JMP     ERROR            ;
  421.  
  422. ;
  423. ;save and replace the timer interrupt vector.
  424. ;
  425. SET_VECTORS:
  426.             MOV     AH,35H                  ;get interrupt 1ch vector
  427.             MOV     AL,1CH
  428.             INT     21H
  429.             MOV     OLD1CH,BX               ;save it
  430.             MOV     OLD1CH[2],ES
  431.             MOV     AH,25H                  ;point it to timer
  432.             LEA     DX,TIMER
  433.             INT     21H
  434. ;
  435. ;indicate success to user
  436. ;
  437.         LEA    DX,SUCCESS
  438.         MOV    AH,09H            ;write error message to screen
  439.         INT    21H            ;
  440. ;
  441. ;Terminate but remain resident in memory.
  442. ;
  443.                   LEA     DX,PROG_ENDS          ;point DX to end of resident code
  444.                   INT    27H                     ;Terminate Stay Resident
  445. ;
  446. ;Error routine in case we failed
  447. ;
  448. ERROR:
  449.         MOV    AH,09
  450.         INT    21H
  451.         INT    20H
  452.  
  453. INITIALIZE       ENDP
  454.  
  455. ;------------------------------------------------------------------------------
  456. ;Error messages and other non resident data
  457. ;------------------------------------------------------------------------------
  458. ADD_ERR        DB    CR,LF,'"ADD NAME" COMMAND FAILED',CR,LF,'$'
  459. LSN_ERR        DB    CR,LF,'"LISTEN" COMMAND FAILED',CR,LF,'$'
  460. NAME_ERR    DB    CR,LF,'ILLEGAL OR MISSING NODE NAME ',CR,LF,'$'
  461. NETBIOS_ERR    DB    CR,LF,'NETBIOS INTERFACE NOT PRESENT',CR,LF,'$'
  462. SUCCESS        DB    CR,LF,'Server Clock Installed Successfully',CR,LF,'$'
  463. ERR_RETRY    DB    0
  464.  
  465.     CODE    ENDS
  466.             END     ENTRY
  467.  
  468.  
  469. 
  470.