!DAK 17/05/85
!** routine to derive the time from the MSF clock server
!** (currently filestore BRAVO (15)) and return it as a record.
!** David A Kerr 1985
!** common include file for both VAX and APM, use editor to change
!** comments to switch between both systems.

{APM}%include "INC:FS.IMP"

!VAX!%external %integer %function %spec ether allocate port
!VAX!%external %routine %spec ether free port (%integer port)
!VAX!%external %routine %spec ether open port (%integer port, remaddr, remport)
!VAX!%external %routine %spec ether close port (%integer port)
!VAX!%external %routine %spec ether transmit block (%integer port, bytes,
!VAX!                                               %bytename buffer)
!VAX!%external %routine %spec ether receive block (%integer port, maxbytes,
!VAX!                                              %integername bytes,
!VAX!                                              %bytename buffer)

!******************************************************************************
%record %format time fm (%byte hundred, second, minute, hour,
                         day of week, day of month, month, year, century, BST)
%record %format msf fm  (%byte state,
                         %record (time fm) current time,
                         %record (time fm) last updated,
                         %string (21) compact time,
                         %string (55) full time)

!******************************************************************************
!** Fields:  hundred, second, BST in LAST UPDATED are meaningless and set = 0
!** state :  0 = ok, 249:255 = error, appropriate message in FULL TIME
!** 0   = OK, information in record elements
!** 249 = <whatever server returned>
!** 250 = MSF full time string length error
!** 251 = MSF compact time string length error
!** 252 = This is the MSF server, illegal request
!** 253 = MSF server not responding to request
!** 254 = MSF facility unavailable at server
!** 255 = MSF semaphore error at server

!******************************************************************************
%external %record (msf fm) %function msf time (%integer apm)
  !** Call this routine ONCE ONLY and copy the record into one of your own
  !** else this routine will be executed many more times than you want and
  !** it accesses the server over the ether each time!
  %constant %byte msf service = 11
  %byte service                        {for required PORT0 service}
  %integer tout,                       {APM only,For time out on ether access}
           l,                          {For returned length of ether packet}
           i                           {Ubiquitous counter variable}
  %integer port                        {VAX only,For allocated port}
  %byte %integer %array buffer (0:100) {For returned ether packet}
  %record (msf fm) msf                 {To assemble the %result in}

  !VAX!%on %event 15 %start
  !VAX!  printstring("Ether trouble, god knows what though!")
  !VAX!  newline
  !VAX!  %stop
  !VAX!%finish

  msf = 0                              {initialise the record}

  {APM}%if etherstation = apm %start
  {APM}  !** cannot request MSF service from oneself over the ether, error!
  {APM}  msf_full time = "This is the MSF server, illegal request"
  {APM}  msf_state = 252
  {APM}  %result = msf
  {APM}%finish

  !** send request for service 11 {MSF time} to
  !** port 0 of server 'apm'
  service = msf service

  !VAX!port = ether allocate port
  !VAX!ether open port (port,apm,0)
  !VAX!ether transmit block (port,1,service)
  !VAX!ether receive block (port,100,l,buffer(0))
  !VAX!ether close port (port)
  !VAX!ether free port (port)

  {APM}ether open (31,apm*256)
  {APM}ether write (31,service,1)
  {APM}tout = 0
  {APM}%while DTX&(1<<31) = 0 %cycle
  {APM}  !** loop waiting for a reply on our port 31
  {APM}  tout = tout + 1
  {APM}  %if tout >= 150000 %start
  {APM}    !** if looped 150 000 times then give up as hopeless
  {APM}    msf_full time = "MSF server not responding to request"
  {APM}    msf_state = 253
  {APM}    %result = msf
  {APM}  %finish
  {APM}%repeat
  {APM}!** packet arrived, so read it in
  {APM}l = ether read (31,buffer(0),100)
  {APM}ether close (31)

  msf_state = buffer(0)
  !** first byte MIGHT contain an error message from server
  %if msf_state # 0 %start
    %if msf_state = 254 %start
      msf_full time = "MSF facility unavailable at server"
    %finish %else %if msf_state = 255 %start
      msf_full time = "MSF semaphore error at server"
    %finish %else %start
      !** error state was not one of mine, so copy whole data packet
      !** into a string and return it as an error
      msf_state = 249
      msf_full time = ""
      msf_full time = msf_full time.tostring(buffer(i)) %for i = 0,1,l-1
    %finish
    %result = msf
  %finish
  !** 'state' was zero so server data OK
  msf_current time_hundred      = buffer(1)
  msf_current time_second       = buffer(2)
  msf_current time_minute       = buffer(3)
  msf_current time_hour         = buffer(4)
  msf_current time_day of week  = buffer(5)
  msf_current time_day of month = buffer(6)
  msf_current time_month        = buffer(7)
  msf_current time_year         = buffer(8)
  msf_current time_century      = buffer(9)
  msf_current time_BST          = buffer(10)

  msf_last updated_year         = buffer(11)
  msf_last updated_month        = buffer(12)
  msf_last updated_day of month = buffer(13)
  msf_last updated_day of week  = buffer(14)
  msf_last updated_hour         = buffer(15)
  msf_last updated_minute       = buffer(16)
  %if msf_last updated_year < 85 %and msf_last updated_year # 0 %then %c
    msf_last updated_century = 20 %else msf_last updated_century = 19
  !** make an 'educated guess' on what the century should be
  msf_last updated_BST          = 0
  msf_last updated_second       = 0
  msf_last updated_hundred      = 0

  %if buffer(18) > 21 %start
    !** something wrong with compact time string
    msf_state = 251
    msf_full time = "MSF compact time string length error"
    %result = msf
  %finish
  msf_compact time = string(addr(buffer(18)))

  %if buffer(40) > 55 %start
    !** something wrong with full time string
    msf_state = 250
    msf_full time = "MSF full time string length error"
    %result = msf
  %finish
  msf_full time = string(addr(buffer(40)))
  %result = msf
%end

%end %of %file
