/*   protocol.h,  /appletalk/ins,  Garth Conboy,  10/04/88  */
/*   Copyright (c) 1988 by Pacer Software Inc., La Jolla, CA  */

/*   GC - Initial coding.
     GC - (11/24/89): Many changes for AppleTalk phase II -- No more LAP
                      orientation.
     GC - (03/30/92): Altered comments to reflect new BufferDescriptor
                      transmit buffer scheme.

     *** Make the PVCS source control system happy:
     $Header$
     $Log$
     ***

     Definitions for AppleTalk and AARP.

*/

/* There are two routines used to send DDP datagrams: TransmitDdp() and
   DeliverDdp().  DeliverDdp takes arguments (amoungst others) of
   "socket" and "destinationAddress".  TransmitDdp, on the other hand, takes
   "sourceAddress" and "destinationAddress".

   Both of these routines operate on BufferDescriptors which a chain of
   buffer chunks.  These routines prepend link, 802.2 and Ddp headers as
   needed.

   DeliverDdp() can be used to deliver packets within the stack or router;
   it will call the router if needed and present.  TransmitDdp() will always
   place a packet on the network; it is called by DeliverDdp() when an actual
   network transmit is required.

   When the router is in operation, it may set a magic bit ("prependInPlace")
   in the BufferDescriptor to alter the function of header forumlation; see
   the comments in "buffdesc.h".

   The AppleTalk stack operates on two basic types of events: an incoming
   packet, and a timer going off.  Both of these events are likey to operate
   on the same databases (e.g. an incoming RTMP data packet and the RTMP
   validity timer going off).  These events are, no doubt, asynchronous within
   a single process; thus, if we're handing the RTMP validity timer expiration
   and an RTMP data packet comes in and we start handling that instead, the
   data structures could be in a bad state and we would crash and burn.  Some
   operating systems (i.e. VMS) avoid this problem by not allowing one of these
   events to interrupt the other (e.g. queuing of events happens for free).  If
   the target operating system for this implementation does not assure such
   behaviour, it must be implemented by hand.

   There exist four routines for moderating critical code paths:

         DeferIncomingPackets();
         HandleIncomingPackets();
         DeferTimerChecking();
         HandleDeferredTimerChecks();

   These routines maintain "defer counters" so calls will stack corrected.
   Thus, if five calls are made to "DeferIncomingPackets", file call to
   "HandleIncomingPackets" will also be required to get incoming packet
   handling enabled again.

   If the defer-incoming-packets counter is non-zero when a packet (from any
   of the various port types) comes into DdpPacketIn, it will be queued for
   later handling and processing will continue where it was before the
   untimely interruption.  Actually, when the defer-incoming-packets counter
   gets down to zero, via calls to HandleIncomingPackets, any queue of
   deferred packets will be fed back into DdpPacketIn at that time.

   On timers front, before a timer handler is invoked by the timer management
   code, a call to DeferTimerChecking is made, so that additional timers will
   not go off untill a call to HandleDeferredTimerChecks is made.  Thus, any
   timer handler MUST call HandleDeferredTimerChecks before it returns.

   Thus, if an incoming packet handler is about to change or examine databases
   that could be altered both by additional incoming packets and by timers
   going off, it should defer both incoming packets and timer interrupts.
   Timer handlers should defer incoming packets as needed.
*/

/* The two logical AppleTalk packet types that we need to know about: */

typedef enum {AppleTalk, AddressResolution} LogicalProtocol;

/* Maximum link access/hardware address lengths (Ethernet and TokenRing both
   set the same record): */

#define MaximumHardwareAddressLength   EthernetAddressLength
#define MaximumHeaderLength            (TokenRingMaxLinkHeaderLength +    \
                                        Ieee802dot2headerLength)
#define MaximumRoutingInfoLength       TokenRingMaxRoutingBytes

#define MaximumDdpDatagramSize     586
#define MaximumLongDdpPacketSize   600      /* Really 599, but even is nicer */
#define MaximumShortDdpPacketSize  592      /* Again, really 591 */

/* Define temporary buffer sizes, these must be big enough to hold both all
   of the packet data plus any link/hardware headers... */

#define MaximumPacketSize          (MaximumHeaderLength +      \
                                    MaximumLongDdpPacketSize)

/* Network number information. */

#define FirstValidNetworkNumber         0x0001
#define LastValidNetworkNumber          0xFFFE
#define FirstStartupNetworkNumber       0xFF00
#define LastStartupNetworkNumber        0xFFFE
#define NullNetworkNumber               0x0000
#define UnknownNetworkNumber            NullNetworkNumber
#define CableWideBroadcastNetworkNumber NullNetworkNumber

#if not InitializeData
  extern
#endif
AppleTalkNetworkRange startupNetworkRange
#if InitializeData
  = {FirstStartupNetworkNumber, LastStartupNetworkNumber};
#else
  ;
#endif

/* DDP packet offsets (skipping Link/Hardware headers): */

#define ShortDdpHeaderLength           5

#define ShortDdpLengthOffset           0
#define ShortDdpDestSocketOffset       2
#define ShortDdpSourceSocketOffset     3
#define ShortDdpProtocolTypeOffset     4
#define ShortDdpDatagramOffset         5

#define LongDdpHeaderLength            13

#define LongDdpLengthOffset            0
#define LongDdpChecksumOffset          2
#define LongDdpDestNetworkOffset       4
#define LongDdpSourceNetworkOffset     6
#define LongDdpDestNodeOffset          8
#define LongDdpSourceNodeOffset        9
#define LongDdpDestSocketOffset        10
#define LongDdpSourceSocketOffset      11
#define LongDdpProtocolTypeOffset      12
#define LongDdpDatagramOffset          13

#define LeadingUnChecksumedBytes       4

#define LongDdpHopCountMask            0x3C

/* Offsets within a DDP datagram: */

#define RtmpRequestCommandOffset       0
#define RtmpSendersNetworkOffset       0
#define RtmpSendersIdLengthOffset      2
#define RtmpSendersIdOffset            3
#define RtmpRangeStartOffset           4
#define RtmpRangeEndOffset             7

#define ZipCommandOffset               0
#define ZipNetworkCountOffset          1
#define ZipFlagsOffset                 1
#define ZipFirstNetworkOffset          2   /* For ZIP query/reply */
#define ZipFirstZoneLengthOffset       4
#define ZipLastNetworkOffset           4   /* For ZIP query/reply */
#define ZipFirstZoneNameOffset         5
#define ZipRequestedZoneLengthOffset   6   /* For ZIP query/reply */
#define ZipRequestedZoneNameOffset     7   /* For ZIP query/reply */

#define ZipCableRangeStartOffset       2   /* AppleTalk phase II offsets */
#define ZipCableRangeEndOffset         4
#define ZipZoneLengthOffset            6
#define ZipOldZoneLengthOffset         6
#define ZipZoneNameOffset              7
#define ZipOldZoneNameOffset           7

#define AtpCommandControlOffset        0
#define AtpBitmapOffset                1
#define AtpSequenceNumberOffset        1
#define AtpTransactionIdOffset         2
#define AtpUserBytesOffset             4
#define AtpDataOffset                  8
#define AtpHeaderSize                  AtpDataOffset

#define EpCommandOffset                0

#define NbpControlOffset               0
#define NbpIdOffset                    1
#define NbpFirstTupleOffset            2

/* DDP protocol types: */

#define DdpProtocolRtmpResponseOrData 1
#define DdpProtocolNbp                2
#define DdpProtocolAtp                3
#define DdpProtocolEp                 4
#define DdpProtocolRtmpRequest        5
#define DdpProtocolZip                6
#define DdpProtocolAdsp               7

/* AppleTalk node number info: */

#define AnyRouterNodeNumber          0
#define UnknownNodeNumber            0
#define MaximumAppleTalkNodes        256
#define MinimumUsableAppleTalkNode   1
#define MaximumUsableAppleTalkNode   254
#define MaximumExtendedAppleTalkNode 253
#define HighestWorkstationNodeNumber 127
#define LowestServerNodeNumber       128
#define AppleTalkBroadcastNodeNumber ((unsigned char)0xFF)

/* A few structures for implementing AppleTalk addresses (for lack of any
   better place to put them): */

typedef struct {short unsigned networkNumber;
                char unsigned nodeNumber;
               } ExtendedAppleTalkNodeNumber;

/* Hashing algorithum for various uses.  Make sure we're positive [thus the
   shift by 7 rather than 8].  Only hash node and socket; due to the "zero
   matches all" for non-extended network numbers. */

#define HashAppleTalkAddress(address)                                \
  ((short unsigned)((address.nodeNumber << 7) +                      \
                     (address.socketNumber & 0x7F)))

/* Hash for an extended node number. Again, always positive. */

#define HashExtendedAppleTalkNode(address)                           \
  ((short unsigned)((address.networkNumber & 0x3FFF) +               \
                    address.nodeNumber))
