!  File  NMOUSE:2MEG

! 2MHz "old protocol" ether access routines

%option "-low-nocheck-nodiag"
%include "mouse.inc"
%include "2meg.inc"

! Basic interface

%ownrecord(mailbox fm)%name server == nil, reply

%externalrecord(ether buffer fm)%map acquire packet buffer
! Acquire a message buffer and initialise some of the fields in it.
%record(ether buffer fm)%name buf
  %if server==nil %start
    server == lookup mailbox(ether mailbox name)
    reply == create mailbox("",create semaphore("",0))
  %finish
  buf == record(addr(acquire message buffer))
  buf_system part_reply == reply
  buf_code = 0; buf_status = 0
  buf_tag = 0; buf_context = 0
  buf_timeout = 100; buf_type = 0
  buf_ra = 0; buf_rp = 0; buf_lp = 0
  buf_bytes = 0; buf_offset = def offset
  %result == buf
%end

%externalroutine discard packet buffer(%record(ether buffer fm)%name buf)
! Return message buffer back to system pool
  %returnif buf==nil
  return message buffer(buf_system part)
%end

%externalroutine ether request(%record(ether buffer fm)%name req)
! Send the request message REQ to the ether driver, and wait for
! the reply.  Point REQ at it (the reply may or may not come in the
! same message buffer) and B at the data part.  Check for errors.
  req_system part_reply == reply
  send message(req_system part,server)
%end

%externalrecord(ether buffer fm)%map ether reply
  %result == record(addr(receive message(reply)))
%end

! Old style interface

%ownrecord(ether buffer fm)%name req == nil

%routine get buffer(%integer context)
  req == acquire packet buffer %if req==nil
  req_code = 0; req_status = 0
  req_tag = 0; req_context = context
  req_timeout = 100; req_type = 0
  req_ra = 0; req_rp = 0; req_lp = 0
  req_bytes = 0; req_offset = def offset
%end

%routine put buffer
  discard packet buffer(req) %unless req==nil
  req == nil
%end
  
%routine make request(%integer code)
  req_code = code
  ether request(req)
  req == ether reply
  %signal 3,5,req_code,ether errors(req_status) %if req_status<0
%end

%externalroutine ether close port(%integer c)
  get buffer(c)
  make request(ether old undefine)
  put buffer
%end

%externalintegerfn ether open port(%integer ra,rp)
%integer c
  get buffer(0)
  req_ra = ra; req_rp = rp
  make request(ether old define)
  c = req_context
  %result = c
%end

%externalroutine ether reopen port(%integer c,rp)
  get buffer(c)
  req_rp = rp
  make request(ether old redefine)
%end

%externalroutine ether transmit block(%integer c,bytes,%name buffer)
  get buffer(c)
  req_bytes = bytes
  move(bytes,buffer,req_data(req_offset))
  make request(ether old write)
%end

%externalintegerfn ether receive block(%integer c,maxbytes,%name buffer)
%integer bytes
  get buffer(c)
  make request(ether old read)
  bytes = req_bytes
  maxbytes = bytes %if bytes<maxbytes
  move(maxbytes,req_data(req_offset),buffer)
  %result = bytes
%end

%externalintegerfn ether station address
%integer a
  get buffer(0)
  make request(ether station)
  a = req_context
  put buffer
  %result = a
%end

%externalroutine show 2meg stats
%record(ether stats fm)%name s
  %routine p(%string(255)s,%integer n)
    printstring(s); write(n,5); newline
  %end
  get buffer(0)
  make request(ether stats)
  s == new(s)
  s = record(addr(req_data(req_offset)))
  printstring("Statistics for ether station "); phex2(s_this station); newline
  p("buffer low water      =",s_buffer low water)
  p("unrecognised control  =",s_unrecognised control)
  p("inbound packets       =",s_inbound packets)
  p("inbound bytes         =",s_inbound bytes)
  p("outbound packets      =",s_outbound packets)
  p("outbound bytes        =",s_outbound bytes)
  p("dud destinations      =",s_dud destinations)
  p("dud types             =",s_dud types)
  p("old inbound packets   =",s_old inbound packets)
  p("old outbound packets  =",s_old outbound packets)
  p("old inbound no takers =",s_old inbound no takers)
  p("old retransmits       =",s_old retransmits)
  p("old ACK timeouts      =",s_old ACK timeouts)
  p("old user timeouts     =",s_old user timeouts)
  p("old defines           =",s_old defines)
  p("old redefines         =",s_old redefines)
  p("old undefines         =",s_old undefines)
  p("old reads             =",s_old reads)
  p("old writes            =",s_old writes)
  p("pended DTX            =",s_pended DTX)
  p("packets dropped       =",s_packets dropped)
  p("pendings discarded    =",s_pendings discarded)
%end
