Revision:      1.11
         Release date:  Thursday, June 02, 1994
         Print date:    Thursday, June 02, 1994
         Developed by:  FTP Software
                        2 High Street
                        North Andover, MA 01845
                        (508) 685-4000

         Copyright (c) 1986-1994 FTP Software, Inc. Permission is  granted
         to reproduce and distribute this document without restriction  or
         fee. This document  may be  re-formatted or  translated, but  the
         functional specification of  the programming interface  described
         herein may not be changed without FTP Software's permission.  FTP
         Software's name and this notice  must appear on any  reproduction
         of this document. This specification was originally developed  at
         FTP Software by John Romkey.

         Support of  a  hardware  interface or  mention  of  an  interface
         manufacturer  by  the  Packet   Driver  Specification  does   not
         necessarily  indicate   that  the   manufacturer  endorses   this
         specification.





         1. Document Conventions
                All  numbers  in  this  document  are  given  in  C-style
                representation. Decimal is  expressed as  11, hexadecimal
                is expressed  as 0x0B,  octal is  expressed  as 013.  All
                reference  to   network   hardware   addresses   (source,
                destination and multicast) and demultiplexing information
                for the packet  headers assumes  they are  represented as
                they would be in  a MAC-level packet header  being passed
                to the send_pkt() function.

         2. Introduction and Motivation
                This document describes the programming  interface to FTP
                Software Packet Drivers. Packet drivers provide a simple,
                common  programming   interface   that  allows   multiple
                applications to  share a  network interface  at the  data
                link  level.  The  packet  drivers  demultiplex  incoming
                packets among  the  applications  by  using  the  network
                media's standard  packet  type  or service  access  point
                field(s).

                The intent  of this  specification is  to allow  protocol
                stack implementations  to be  independent  of the  actual
                brand or  model of  the  network interface  in  use on  a
                particular  machine.   Different   versions  of   various
                protocol stacks  still must  exist for  different network
                media (Ethernet,  802.5 ring,  serial lines),  because of
                differences  in  protocol-to-physical   address  mapping,
                header formats, maximum transmission units  (MTUs) and so
                forth.

                The packet driver provides calls to  initiate access to a
                specific packet  type, to  end access  to it,  to send  a
                packet, to get statistics on the network interface and to
                get information about the interface.

                Protocol implementations that  use the packet  driver can
                completely coexist  on  a  PC and  can  make  use of  one
                another's services,  whereas multiple  applications which
                do not  use the  driver  do not  coexist  on one  machine
                properly. Through use of the packet  driver, a user could
                run   TCP/IP,   XNS,    and   a    proprietary   protocol
                implementation  such  as  DECnet,   Banyan's,  LifeNet's,
                Novell's or  3Com's without  the difficulties  associated
                with preempting the network interface.

                Applications which use the packet driver  can also run on
                new network  hardware  of the  same  class without  being
                modified; only a new packet driver need be supplied.

                Several levels of  packet drivers  are described  in this
                specification. The  first  is  the basic  packet  driver,
                which provides minimal functionality but should be simple
                to implement and which uses very  few host resources. The
                basic driver provides operations to broadcast and receive





                packets. The second driver is the extended packet driver,
                which is  a superset  of the  basic driver.  The extended
                driver supports  less  commonly  used  functions  of  the
                network interface  such as  multicast,  and also  gathers
                statistics on  use  of  the  interface  and  makes  these
                available to the application. The third  level, the high-
                performance functions,  support performance  improvements
                and tuning.

                Functions which are available in only the extended packet
                driver are noted as such in their descriptions. All basic
                packet driver  functions are  available  in the  extended
                driver. The high-performance  functions may  be available
                with either basic or extended drivers.

         3. Identifying network interfaces
                Network interfaces are  named by  a triplet  of integers,
                <class, type, number>. The  first number is the  class of
                interface.  The  class  tells  what  kind  of  media  the
                interface supports:  DEC/Intel/Xerox  (DIX  or  Bluebook)
                Ethernet, IEEE  802.3 Ethernet,  IEEE  802.5 Token  Ring,
                ProNET-10, Appletalk, serial line, etc.

                The  second  number  is  the  type   of  interface:  this
                specifies  a   particular   instance   of  an   interface
                supporting a class of network medium. Interface types for
                Ethernet might  name  these  interfaces:  3Com  3C503  or
                3C505, InterLan  NI5210,  Univation,  BICC Data  Networks
                ISOLAN, Ungermann-Bass NIC, etc. Interface types for IEEE
                802.5  might  name  these  interfaces:   IBM  Token  Ring
                adapter, Proteon p1340, etc.

                The  last  number  is  the  interface  number.  This  was
                orginally  intended   to   allow   support  of   multiple
                interfaces by a single Packet Driver. However, given that
                the send_pkt()  function  doesn't  get passed  either  an
                interface number or a  handle, this can't  be implemented
                in the spec as it presently exists.

                An appendix details constants for classes  and types. The
                class of an interface  is an 8-bit integer,  and its type
                is a 16 bit integer. Class and type constants are managed
                by FTP Software. Contact  FTP to register a  new class or
                type number. See the section  on Specific Characteristics
                of Classes for details  of packet header format,  MTU and
                demultiplexing information for the various classes.

                The type  0xFFFF is  a wildcard  type  which matches  any
                interface in the  specified class.  It is  unnecessary to
                wildcard interface numbers,  as 0 will  always correspond
                to the first interface of the specified class and type.

                This specification has  no provision  for the  support of
                multiple network  interfaces (with  similar or  different





                characteristics)  via   a   single   Packet  Driver   and
                associated interrupt.  We feel  that this  issue is  best
                addressed by  loading  several  Packet Drivers,  one  per
                interface, with different interrupts (although all may be
                included in a  single TSR software  module). Applications
                software must check  the class and  type returned  from a
                driver_info() call  in any  case, to  make sure  that the
                Packet Driver is for the correct media and packet format.
                This can easily be  generalized by searching  for another
                Packet Driver if the first is not of the right kind.

         4. Initiating driver operations
                The packet driver is invoked via  a software interrupt in
                the range 0x20 through  0xFF (in versions prior  to 1.10,
                the  low   and   high   limits   were  0x60   and   0x80,
                respectively).  This   document   does   not  specify   a
                particular  interrupt,  but  describes  a  mechanism  for
                locating which interrupt  the driver uses.  The interrupt
                must be configurable to avoid conflicts with other pieces
                of  software  that  also  use  software  interrupts.  The
                program which installs  the packet driver  should provide
                some mechanism for the user to specify the interrupt.

                The handler for the interrupt is assumed  to start with 3
                bytes of  executable code;  this can  either be  a 3-byte
                jump instruction, or a 2-byte jump followed  by a NOP (do
                not specify  "jmp  short"  unless  you  also  specify  an
                explicit  NOP).  This  must  be  followed  by  the  null-
                terminated ASCII text string

                   PKT DRVR  (ASCII: 0x50 0x4A 0x54 0x20 0x44 0x52 0x56
                0x52 0x00)

                To find  the  interrupt  being  used  by the  driver,  an
                application should scan through the  handlers for vectors
                0x20 through 0xFF until it finds one with the text string
                "PKT DRVR" in the proper location.

         5. Link-layer demultiplexing
                If a network  media standard  is to  support simultaneous
                use by different  transport protocols (e.g.  TCP/IP, XNS,
                OSI), it  must  define  some link-level  mechanism  which
                allows a  host  to  decide  which  protocol a  packet  is
                intended  for.  In  DIX  Ethernet,  this  is  the  16-bit
                Ethertype  field   immediately   following   the   6-byte
                destination and  source addresses.  In  IEEE 802.3  where
                802.2 headers  are  used,  this  information  is  in  the
                variable-length 802.2  header.  In  Proteon's  ProNET-10,
                this is  done via  the 8-bit  "type"  field. Other  media
                standards may demultiplex via  a method of their  own, or
                802.2 headers as in 802.3.

                Our access_type()  function    provides  access  to  this
                link-layer  demultiplexing.   Each  call   establishes  a





                destination for a  particular type of  link-layer packet,
                which remains  in effect  until release_type()  is called
                with   the   handle    returned   by    that   particular
                access_type(). The link-layer  demultiplexing information
                is passed via the type and typelen fields, but values and
                interpretation depend on the class of  packet driver (and
                thus on the media in use).

                A class  1 driver  (DIX Ethernet)  should expect  type to
                point at an Ethertype  value (in network byte  order, and
                greater  than  0x05EE),  and   might  reasonably  require
                typelen to equal either  2 (a 16-bit Ethertype)  or 0 (if
                it supports match all types mode). A class 2 driver could
                require  1  byte.  However,  a  class  3  (802.5)  or  11
                (Ethernet with 802.2  headers) driver should  be prepared
                for typelen values  between 1 (for  the DSAP  field only)
                and 8 (3 byte 802.2 header plus 3-byte Sub-Network Access
                Protocol  extension  header  plus   2-byte  Ethertype  as
                defined in RFC 1042).

         6. Programming interface
                All functions  are accessed  via  the software  interrupt
                determined to be the driver's via the mechanism described
                earlier. On entry, register  AH contains the code  of the
                function desired.

                Driver implementors are warned that a  number of protocol
                stacks  exist  that   support  multiple   active  network
                interfaces  simultaneously,  notably  Phil  Karn's  KA9Q,
                which can function as an IP Router. For this reason it is
                necessary to  use  coding  techniques  which  will  allow
                multiple drivers (possibly for the same type of board) to
                be active at once.  At a minimum, this  requires that the
                driver's  vector  be  configurable,  and  that  it  avoid
                issuing non-specific EOIs to the interrupt controller.

           6.1. Handles
                The  handle   is  an   arbitrary  16-bit   integer  value
                associated with each  MAC-level demultiplexing  type that
                has  been   established  via   the  access_type()   call.
                Internally to the  packet driver, it  will probably  be a
                pointer, or a table offset.

                As of  version  1.10 of  this  specification, the  handle
                values 0x0000 and 0xFFFF  (-1) has been reserved  for use
                by this specification  (and applications) as  an "invalid
                handle" indication. There  is reason  to believe  that no
                older Packet  Drivers  will  ever return  these  handles,
                because existing protocol stacks  already use one  or the
                other as an "invalid handle" indication.

                Other  than   the  reserved   values  named   above,  the
                application calling the packet driver cannot  depend on a
                handle  assuming  any  particular  range,  or  any  other





                characteristics. In  particular, if  an application  uses
                two or more packet drivers, handles returned by different
                drivers for the same or different types may have the same
                value.

           6.2. Levels of Functionality
                Note  that  some  of  the  functions  defined  below  are
                labelled  as   extended   driver   functions  and   high-
                performance functions. Because these are not required for
                basic network  operations,  their  implementation may  be
                considered optional.    Programs  wishing  to  use  these
                functions  should  use  the   driver_info()  function  to
                determine if they are available in a given packet driver.

           6.3. Entry conditions
                FTP Software  applications which  call the  packet driver
                are coded  in  Microsoft  C  and assembly  language.  All
                necessary registers  are saved  by FTP's  routines before
                the  INT  instruction  to  call  the   packet  driver  is
                executed. Our  current  receiver()  functions  behave  as
                follows: DS,  BP, SS,  SP  and the  flags  are saved  and
                restored.   All  other  registers  may be  modified,  and
                should be  saved  by  the  packet driver,  if  necessary.
                Processor interrupts may be enabled while  in the upcall,
                but the upcall doesn't assume interrupts  are disabled on
                entry. On entry,  receiver() switches  to a  local stack,
                and switches back before returning.

                Note that  some  older  versions  of  PC/TCP  may  enable
                interrupts during the upcall,  and leave them  enabled on
                return to the  Packet Driver. Note  also that  while some
                drivers (notably the Clarkson/Crynwr collection) save all
                registers on entry, others  don't. Application developers
                should take  care  save  their  own registers  to  ensure
                interoperability.

           6.4. Number of Handles Opened
                When using a class 1 driver, PC/TCP  will normally make 5
                access_type() calls for IP,  ARP and 3 kinds  of Berkeley
                Trailer encapsulation  packets (LANWatch  will only  make
                one, with typelen equal to 0). On other media, the number
                of handles we open will vary, but it  is usually at least
                two (IP and ARP).  Implementors should make  their tables
                large enough to allow two protocol stacks to co-exist. We
                recommend  support   for  at   least   10  open   handles
                simultaneously.

           6.5. Byte and Bit ordering
                Developers  should  note  that,  on   many  networks  and
                protocol families, the byte-ordering of 16-bit and 32-bit
                quantities on the  network is  different from  the native
                byte-order of integers on the PC. This means, among other
                things, that DEC-Intel-Xerox  Ethertype values  passed to
                access_type() must  be  byte-swapped  (passed in  network





                order).  The  IEEE  802.3  length   field  needs  similar
                handling, and care should be taken with packets passed to
                send_pkt(), so  all  fields  are  in  the  proper  order.
                Developers working  with 802.5  should be  aware that  it
                does not use the  same bit-order as Ethernet  - where the
                'group' bit is the most significant bit  of a MAC address
                on 802.5, it  is the least  significant bit of  the first
                byte   on   Ethernet.   IEEE    Organizationally   Unique
                Identifiers (Ethernet  manufacturer  codes)  also  change
                bit-order between the two media. FDDI  uses the same bit-
                order as  802.5  on  the  physical  medium,  but  current
                practice requires that it be converted  to match Ethernet
                by the MAC-layer  driver before presentation  to protocol
                stacks.

           6.6. Byte Alignment
                Because  some   packet   drivers   can  provide   greater
                performance if  packet buffers  are double  word aligned,
                protocol stack  developers should  double word  align the
                packet  buffers.   However  this   is  not   an  absolute
                requirement.

           6.7. driver_info()
                driver_info(handle)
                   AH   1
                   AL   255
                   BX   handle         /* Optional */

                error return:
                   carry     set
                   DH   error code

                   possible errors:
                        BAD_HANDLE   /* older drivers only */

                non-error return:
                   carry     clear
                   BX   version
                   CH   class
                   DX   type
                   CL   number
                   DS:SI     name
                   AL   functionality
                        1 == basic functions present.
                        2 == basic and extended present.
                        5 == basic and high-performance.
                        6 == basic, high-performance, extended.
                        255 == not installed.
                This function  returns information  about the  interface.
                The version is assumed to be  an internal hardware driver
                identifier. In earlier versions of this  spec, the handle
                argument   (which   must    have   been    obtained   via
                access_type()) was  required.  It  is now  optional,  but
                drivers developed  according  to  versions of  this  spec





                previous to 1.07 may  require it, so  implementers should
                take care.

           6.8. access_type()
                int  access_type(if_class,   if_type,  if_number,   type,
                typelen, receiver)
                   AH   2
                   AL   if_class
                   BX   if_type
                   DL   if_number
                   DS:SI     type
                   CX   typelen
                   ES:DI     receiver

                error return:
                   carry     set
                   DH   error code

                   possible errors:
                        NO_CLASS
                        NO_TYPE
                        NO_NUMBER
                        BAD_TYPE
                        NO_SPACE
                        TYPE_INUSE

                non-error return:
                   carry     clear
                   AX   handle

                receiver call:
                   (*receiver)(handle, flag, len [[, lah_len], buffer])
                        BX   handle
                        AX   flag

                        if AX == 0,
                             DX   lah_len
                             DS:SI     lah_buffer    /*  if DX != 0  */

                   Returns:
                        ES:DI     buffer         /*  If 0, no buffer  */
                        CX   buffer_len     /*  May not equal entry CX  */

                        if AX == 1,
                             DS:SI     buffer
                             CX   buffer_len          /*   Bytes  actually
                copied  */

                   error return:
                        ES:DI     0:0

                   non-error return:
                        ES:DI     buffer pointer
                        CX   buffer length






                Initiates access to  packets of  the specified  type. The
                argument  type   is   a   pointer   to  a   packet   type
                specification. The  argument  typelen  is the  length  in
                bytes of  the  type field.  The  argument  receiver is  a
                pointer to a subroutine which is called  when a packet is
                received. If the  typelen argument  is 0,  this indicates
                that the  caller wants  to match  all packets  (match all
                requests may be  refused by  packet drivers  developed to
                conform to versions of this spec previous to 1.07).

                When a packet  is received, receiver  is called  twice by
                the packet driver. The first time it is called to request
                a buffer from the application to copy the packet into. AX
                == 0 on this  call. The application may  return a pointer
                to a buffer to which  the packet should be  copied by the
                driver in ES:DI.  If the application  has no  buffers, it
                may return 0:0 in ES:DI, and the driver should throw away
                the packet and not perform the second call.

                It is important that  the packet length (CX)  be valid on
                the AX ==  0 call,  so that the  receiver can  allocate a
                buffer of the  proper size. This  length (as well  as the
                copy performed prior  to the AX  == 1 call)  must include
                the MAC  header  and  all  received  data,  but  not  the
                trailing Frame  Check Sequence  (if any),  except in  the
                case of asynchronous PPP, where space for the Frame Check
                Sequence may be included, even though  the protocol stack
                will make no  use of  the information.   The  driver must
                never copy more bytes than CX  specifies; if the hardware
                requires that  the copy  length be  even, the  initial CX
                value must be rounded  up to reflect this.  On the second
                call, AX == 1. This call indicates that the copy has been
                completed, and the application  may do as it  wishes with
                the buffer. The buffer that the packet was copied into is
                pointed  to  by  DS:SI.   As  discussed  in   the  "Entry
                Conditions" section, the driver  is expected to  save the
                registers  it  cares  about  before  calling  receiver().
                Protocol stacks  should  not expect  more  than about  20
                bytes of  stack to  be available,  and must  switch to  a
                stack  of  its  own   before  using  more,   or  enabling
                interrupts.

                Version 1.10  of  this  spec  (use  the  get_parameters()
                function to  determine the  version of  a given  driver),
                specifies three enhancements  to the  receiver mechanism:
                First, on the AX == 0 call, a non-zero value in DX is the
                length of the data in a "look-ahead buffer" pointed to by
                DS:SI. The application may inspect this data to determine
                where to put the  packet. Second, on the  return from the
                AX == 0 call, the value of CX is the actual length of the
                application's buffer. The driver must truncate the packet
                to fit as it copies it. Third, on the AX  == 1 upcall, CX





                contains the  number  of  bytes  actually copied  by  the
                driver.

                Note that  the  functionality  defined in  the  paragraph
                above must be present  in drivers which  indicate version
                1.10   or   greater    in   the   values    returned   by
                get_parameters(),  and  will  not  be  found  in  drivers
                indicating 1.09 or  previous. It is  advisable not  to be
                completely dependent on  the presence  of a  1.10 driver,
                given the number of older drivers in the field.

                Note that  many drivers  are not  re-entrant, and  so are
                unable to  process  functions  (particularly  send_pkt())
                while either receiver() upcall is in  progress. Queue any
                transmits or  other  packet  driver calls  for  execution
                later,  possibly via hooking the  int_num vector returned
                by get_parameters().

           6.9. release_type()
                int release_type(handle)
                   AH   3
                   BX   handle

                error return:
                   carry     set
                   DH   error code

                   possible errors:
                        BAD_HANDLE

                non-error return:
                   carry     clear

                This function ends  access to  packets associated  with a
                handle returned by access_type(). The handle is no longer
                valid.

           6.10. send_pkt()
                int send_pkt(buffer, length)
                   AH   4
                   DS:SI     buffer
                   CX   length

                error return:
                   carry     set
                   DH   error code

                   possible errors:
                        CANT_SEND

                non-error return:
                   carry     clear





                Transmits length bytes of  data, starting at  buffer. The
                application must  supply  the  entire  packet,  including
                local network headers. Any MAC or  LLC information in use
                for  packet  demultiplexing  (e.g.   the  DEC-Intel-Xerox
                Ethertype) must be filled in by  the application as well.
                This cannot be performed  by the driver, as  no handle is
                specified in a call to the send_packet() function.

                Note that when  transmitting to  a group  destination MAC
                address  (broadcast  or  multicast),   the  hardware  may
                receive the  packet itself.  Protocol stack  implementors
                are advised  to check  for this  in situations  where the
                stack would otherwise be confused by seeing a copy of its
                own  broadcast  (e.g.  RARP   or  broadcast  name-defense
                schemes).

           6.11. terminate()
                terminate(handle)
                   AH   5
                   BX   handle

                error return:
                   carry     set
                   DH   error code

                   possible errors:
                        BAD_HANDLE   /* older drivers only */
                        CANT_TERMINATE

                non-error return:
                   carry     clear

                Terminates  the   driver  associated   with  handle.   If
                possible, the  driver  will  exit  and  allow  MS-DOS  to
                reclaim the memory it  was using. In earlier  versions of
                this spec,  the  handle argument  (which  must have  been
                obtained via  access_type())  was  required.  It  is  now
                optional, but drivers developed according  to versions of
                this  spec   previous  to   1.10  may   require  it,   so
                implementers should take care.

           6.12. get_address()
                get_address(handle, buf, len)
                   AH   6
                   BX   handle      /*  Optional  */
                   ES:DI     buf
                   CX   len

                error return:
                   carry     set
                   DH   error code

                   possible errors:
                        BAD_HANDLE          /*  older drivers only  */





                        NO_SPACE

                non-error return:
                   carry     clear
                   CX   length

                Copies the  current local  net address  of the  interface
                into buf. The  buffer buf is  len bytes long.  The actual
                number of bytes copied is returned in CX. If the NO_SPACE
                error  is   returned,  this   indicates   that  len   was
                insufficient to  hold  the local  net  address.   If  the
                address has  been changed  by set_address(),  the station
                address  presently  in  effect  should  be  returned.  In
                earlier versions of this spec, the handle argument (which
                must have been obtained via  access_type()) was required.
                It is now  optional, but  drivers developed  according to
                versions of this spec previous to 1.10 may require it, so
                implementers should take care.

           6.13. reset_interface()
                reset_interface(handle)
                   AH   7
                   BX   handle      /*  Optional  */

                error return:
                   carry     set
                   DH   error code

                   possible errors:
                        BAD_HANDLE   /* older drivers only */
                        CANT_RESET

                non-error return:
                   carry     clear

                Resets the interface  associated with  handle to  a known
                state,   aborting   any   transmits    in   process   and
                reinitializing the  receiver. The  local  net address  is
                reset to the  default (from ROM),  the multicast  list is
                cleared, and the receive mode is set to  3 (own address &
                broadcasts). If multiple handles are  open, these actions
                might seriously  disrupt  other  applications  using  the
                interface, so CANT_RESET  should be returned.  In earlier
                versions of this  spec, the  handle argument  (which must
                have been obtained via access_type()) was required. It is
                now optional, but drivers developed according to versions
                of  this  spec  previous  to  1.10  may  require  it,  so
                implementers should take care.

           6.14. get_parameters()      high-performance driver function
                 get_parameters()
                   AH   10

                error return:





                   carry     set
                   DH   error code

                   possible errors:
                        BAD_COMMAND  /* No high-performance support */

                non error return:
                   carry     clear
                   ES:DI     param

                struct param {
                  unsigned char major_rev; /* Revision of Packet Driver
                spec */
                  unsigned char minor_rev; /* this driver conforms to. */
                  unsigned char length;    /* Length of structure in
                bytes */
                  unsigned char addr_len;  /* Length of a MAC-layer
                address */
                  unsigned short mtu;      /* MTU, including MAC headers
                */
                  unsigned short multicast_aval; /* Buffer size for
                multicast addr */
                  unsigned short rcv_bufs; /* (# of back-to-back MTU
                rcvs) - 1 */
                  unsigned short xmt_bufs; /* (# of successive xmits) - 1
                */
                  unsigned short int_num;  /* Interrupt # to hook for
                post-EOI
                                              processing, 0 == none */
                };

                The performance of an application may  benefit from using
                get_parameters() to obtain a number of driver parameters.
                This function was added  to v1.09 of  this specification,
                and  may  not   be  implemented   by  all   drivers  (see
                driver_info()).

                The major_rev  and  minor_rev fields  are  the major  and
                minor  revision   numbers   of   the  version   of   this
                specification the driver conforms to.  For this document,
                major_rev is 1 and minor_rev is 10.  The length field may
                be used  to determine  which values  are valid,  should a
                later revision of this  specification add more  values at
                the end of this structure.  For  this document, length is
                14. The addr_len field is the length of a MAC address, in
                bytes. Note the param structure is  assumed to be packed,
                such that these fields  occupy four consecutive  bytes of
                storage.

                In the param structure, the mtu  is the maximum MAC-level
                packet the driver can handle (on  Ethernet this number is
                fixed at 1514 bytes, but it may vary on other media, e.g.
                802.5 or FDDI). This  value should include  all MAC-layer
                data that  the application  must supply  to a  send_pkt()





                call (for class 1, source and  destination addresses, and
                Ethertype), but  not framing  normally  generated by  the
                hardware  (preamble, FCS, etc.). The multicast_aval field
                is  the  number  of  bytes  required  to  store  all  the
                multicast addresses  supported  by  any "perfect  filter"
                mechanism in  the hardware.  Calling set_multicast_list()
                with its len argument equal to this value should not fail
                with a  NO_SPACE  error.  A  value  of  zero  implies  no
                multicast support.

                The rcv_bufs and xmt_bufs indicate the number of back-to-
                back receives  or transmits  the card/driver  combination
                can accomodate,  minus 1.  The application  can use  this
                information   to   adjust   flow-control    or   transmit
                strategies.  A  single-buffered  card  (for  example,  an
                InterLan NI5010) would normally return 0  in both fields.
                A value of 0 in rcv_bufs  could also be used  by a driver
                author to  indicate  that  the hardware  has  limitations
                which prevent it from receiving as  fast as other systems
                can send, and to recommend that the upper-layer protocols
                invoke lock-step flow control to avoid packet loss.

                The int_num field should be set to  an interrupt that the
                application can hook  in order to  perform interrupt-time
                protocol processing after  the EOI has  been sent  to the
                8259 interrupt controller and the card  is ready for more
                interrupts. Because software adapter modules may not have
                a hardware interrupt  available, this value  is specified
                as corresponding to the  argument to an  INT instruction,
                rather than the specific hardware interrupt line. A value
                of zero indicates  that there is  no such  interrupt. Any
                application hooking this interrupt and finding a non-zero
                value in  the vector  must pass  the  interrupt down  the
                chain and  wait  for its  predecessors  to return  before
                performing any processing  or stack switches.  Any driver
                which  implements  this  function  via   a  separate  INT
                instruction  and  vector,  instead  of   just  using  the
                hardware interrupt, must  prevent any saved  context from
                being overwritten by a  later interrupt. In  other words,
                if the driver switches  to its own stack,  it must either
                support re-entrancy, or detect and prevent it.

           6.15. old_as_send_pkt()       high-performance driver function
                old_as_send_pkt()
                   AH   11

                error return:
                   carry     set
                   DH   error code

                   possible errors:
                        BAD_COMMAND





                This function was added in v1.09 of this specification in
                order to provide  an asynchronous version  of send_pkt().
                The specification  of  this  function  was  found  to  be
                deficient, and  no implementations  of  it were  created.
                This function was removed in v1.10  of this specification
                in favor of the new improved as_send_pkt() (AH = 12).

           6.16. as_send_pkt()         high-performance driver function
                int as_send_pkt(iocb)
                   AH   12
                   ES:DI     struct iocb far* iocb

                struct iocb {
                  char far *buffer;          /* Pointer to xmit buffer */
                  unsigned length;           /* Length of buffer       */
                  unsigned char flagbits;    /* Flag bits              */
                  unsigned char code;        /* Error code             */
                  void (far *transmitter)(); /* Transmitter upcall     */
                  char reserved[4];          /* Future gather-write    */
                  char private[8];           /* Driver's private data  */
                };

                flag bits (little endian encoding):

                   Name  Bit Value Meaning
                   DONE   0  0x01  the packet driver is done with this
                iocb.
                   UPCALL 1  0x02  the application requests an upcall
                when the
                                   buffer is re-usable.

                error return:
                   carry     set
                   DH   error code

                   possible errors:
                        CANT_SEND      /*    transmit  error,  re-entered,
                etc.  */
                        BAD_COMMAND    /*  Level 0 or level 1 driver  */

                non-error return:
                   carry     clear

                transmitter upcall:
                   void (*transmitter)(iocb)
                        ES:DI     struct iocb far *iocb

                as_send_pkt() provides an asynchronous  mechanism for the
                transmission  of  packets.   It  differs  from   the  the
                synchronous send_pkt()  in  two  major ways.  First,  all
                parameters  including  the   normal  length   and  buffer
                parameters are passed within an iocb  (I/O Control Block)
                structure rather than being passed directly in registers.
                Second, as_send_pkt()  never blocks  awaiting buffer  re-





                usability.    For  example,  send_pkt()  returns  to  the
                calling application only after the application's data has
                been copied  out of  the buffer  and the  application can
                safely modify or re-use the buffer. as_send_pkt() returns
                to the calling application immediately and signals buffer
                availability by setting  a bit in  the flagbits  field of
                the  iocb  and   optionally  by  making   an  application
                specified upcall.

                as_send_pkt() takes a single  argument, a far  pointer to
                an iocb structure.  The buffer and  length fields  of the
                iocb structure  have exactly  the same  meaning as  those
                passed to  send_pkt(). The  flagbits field  currently has
                two flag bits defined:  DONE and UPCALL. The  DONE bit is
                used by the  packet driver to  signal re-usability  of an
                iocb and associated buffer. It MUST be cleared to zero by
                the calling application  before passing  the iocb  to the
                packet driver.  Once the  packet driver  is done  with an
                iocb -- either because the buffer has been transmitted or
                because an  error was asynchronously  detected -- it will
                set the DONE bit  to one. The UPCALL  bit is used  by the
                calling application to request an upcall  from the packet
                driver after the DONE  bit is set  to one. If  the UPCALL
                bit is  set  to zero,  no  upcall will  be  made and  the
                application must poll the DONE bit  to determine iocb re-
                usability.  If  the UPCALL  bit is set  to one,  then the
                packet driver  will  call the  routine  specified in  the
                transmitter field of the iocb after  setting the DONE bit
                to one.  The  application may  change  the  state of  the
                UPCALL bit at any time, but care should be taken to avoid
                introducing   race   conditions.      Specifically,   the
                application  should   be  careful   when  examining   and
                modifying application  level  queues  of iocbs,  if  such
                queues exist. Depending  on the strategy  implemented, it
                may be  necessary  to  disable interrupts  while  testing
                queue lengths and  testing or  modifying iocb  flag bits.
                All other flag bits should be set to  zero by the calling
                application.

                If the driver  detects an  error on  the initial  call to
                as_send_pkt(),  it  will  return  the   error  using  the
                standard carry  flag/DH register  mechanism, the  iocb is
                left in an  indeterminant state  (in particular  the code
                field and  DONE bit  should not  be relied  on), and  any
                requested  upcall   will  not   be   made.  However,   if
                as_send_pkt() detects an  error later  asynchronously, it
                will return the  error in  the iocb  code field,  set the
                DONE bit, and  if requested,  make an  upcall. Successful
                packet transmission is indicated by a code of zero.

                The structure field iocb->reserved is for the purposes of
                implementing a  future  scatter/gather  capability.  This
                field must be set to zero.





                The final field in  the structure, iocb->private,  is for
                the private use of  the packet driver. It  will typically
                be used  to maintain  a queue  of iocbs.  The application
                must not reference or modify this field  in any way. This
                function was added  in v1.10  of this  specification, and
                may   not   be   implemented   by    all   drivers   (see
                driver_info()).

           6.17. drop_pkt()       high-performance driver function
                int drop_pkt(iocb)
                   AH   13
                   ES:DI     struct iocb far* iocb

                error return:
                   carry     set
                   DH   error code

                   possible errors:
                        BAD_COMMAND    /*  Level 0 or level 1 driver  */

                non-error return:
                   carry     clear

                Searches  the  as_send_pkt()   asynchronous  transmission
                queue for the specified iocb, and if found, drops it from
                the queue. To avoid  race conditions, if the  iocb is not
                found no error is signaled. After return from drop_pkt(),
                the calling application  may consider the  specified iocb
                and buffer to be safely re-usable. This function provides
                an application a way to implement  any desired congestion
                control algorithms (such as random drop).

           6.18. set_rcv_mode()        extended driver function
                set_rcv_mode(handle, mode)
                   AH   20
                   BX   handle
                   CX   mode

                error return:
                   carry     set
                   DH   error code

                   possible errors:
                        BAD_HANDLE
                        BAD_MODE

                non-error return:
                   carry     clear

                Sets the receive  mode on  the interface  associated with
                handle. The following values are accepted for mode:

                   mode meaning
                      1 turn off receiver (no packets)





                      2 receive only  packets  sent  to  this  interface's
                station address
                      3 mode 2 plus broadcast destination address
                      4 mode  3  plus  multicast  addresses  as  set   via
                set_multicast_list()
                      5 mode 3 plus all multicast packets
                      6 all packets
                      7 raw mode (new in 1.10 for serial line only)

                Note that  not  all  interfaces  support all  modes.  The
                receive  mode  affects  all  packets   received  by  this
                interface, not  just packets  associated with  the handle
                argument.   See    the    extended    driver    functions
                get_multicast_list()   and    set_multicast_list()    for
                programming hardware  hash  filters  to receive  specific
                multicast addresses.

                Most drivers do not allow set_rcv_mode() if more than one
                handle is open, to  avoid confusing a stack  with packets
                it doesn't expect. If  a driver does not  return BAD_MODE
                when more  than  one handle  is  open,  it must  maintain
                separate receive modes on a per-handle  basis, and filter
                incoming traffic as appropriate to each handle's mode.

                Note  that   mode  3   is  the   default,   and  if   the
                set_rcv_mode() function  is not  implemented,  mode 3  is
                assumed to be in  force as long  as any handles  are open
                (from   the    first    access_type()    to   the    last
                release_type()).

                The handle argument  (which must  have been  obtained via
                access_type()) is required on  this function in  order to
                allow drivers to limit the effect of this function to the
                handle specified. Accordingly,  protocol stacks  must not
                depend on a change effecting all handles.

           6.19. get_rcv_mode()        extended driver function
                 get_rcv_mode(handle, mode)
                   AH   21
                   BX   handle

                error return:
                   carry     set
                   DH   error code

                   possible errors:
                        BAD_HANDLE

                non-error return:
                   carry     clear
                   AX   mode

                Returns  the  current  receive  mode   of  the  interface
                associated with handle.






           6.20. set_multicast_list()       extended driver function
                 set_multicast_list(addrlst, len)
                   AH   22
                   ES:DI     char far* addrlst
                   CX   len

                error return:
                   carry     set
                   DH   error code

                   possible errors:
                        NO_MULTICAST
                        NO_SPACE
                        BAD_ADDRESS

                non-error return:
                   carry     clear

                The addrlst argument is  assumed to point to  an len-byte
                buffer  containing  a  number   of  multicast  addresses.
                BAD_ADDRESS is  returned if  len modulo  the  size of  an
                address is not  equal to 0,  or the data  is unacceptable
                for some reason. NO_SPACE  is returned (and  no addresses
                from the current  list are  set while  any previously-set
                addresses remain in effect)  if there are  more addresses
                than the hardware or driver supports.

                The recommended procedure for setting multicast addresses
                is to issue a get_multicast_list(),  copy the information
                to a local buffer, add any addresses desired, and issue a
                set_multicast_list(). This  should be  reversed when  the
                application exits. If the  set_multicast_list() fails due
                to NO_SPACE, use set_rcv_mode() to set mode 5 instead.

                Note that  most hardware  multicast  filters use  hashing
                techniques, and may pass  addresses not specified  in the
                addrlst. For  this reason,  stacks  using multicast  must
                check the destination MAC address if  there is any chance
                they'll  become  confused   by  a  packet   they  weren't
                expecting.


           6.21. get_multicast_list()       extended driver function
                 get_multicast_list()
                   AH   23

                error return:
                   carry     set
                   DH   error code

                   possible errors:
                        NO_MULTICAST
                        NO_SPACE






                non-error return:
                   carry     clear
                   ES:DI     char far* addrlst;
                   CX   len

                On a successful  return, addrlst points  to len  bytes of
                multicast addresses  currently  in  use. The  application
                program must  not  modify  this information  in-place.  A
                NO_SPACE error  indicates that  there wasn't  enough room
                for all active multicast addresses.

           6.22 get_statistics()       extended driver function
                get_statistics(handle)
                   AH   24
                   BX   handle         /* Optional */

                error return:
                   carry     set
                   DH   error code

                   possible errors:
                        BAD_HANDLE   /* older drivers only */

                non-error return:
                   carry     clear
                   DS:SI     char far* stats

                struct statistics {
                  unsigned long packets_in;   /* Totals across all
                handles */
                  unsigned long packets_out;
                  unsigned long bytes_in;     /* Including MAC headers */
                  unsigned long bytes_out;
                  unsigned long errors_in;    /* Totals across all error
                types */
                  unsigned long errors_out;
                  unsigned long packets_lost; /* No buffer from
                receiver(), card */
                                              /* out of resources, etc.
                */
                };

                Returns a  pointer  to  a  statistics structure  for  the
                interface.   The values  are stored  so as  to be  normal
                80x86 32-bit  integers. Stacks  should  assume that  this
                structure is dynamic, and  copy it to local  storage with
                interrupts disabled.  In earlier  versions of  this spec,
                the handle argument  (which must  have been  obtained via
                access_type()) was  required.  It  is now  optional,  but
                drivers developed  according  to  versions of  this  spec
                previous to 1.10 may  require it, so  implementers should
                take care.





           6.23 set_address()          extended driver function
                 set_address(addr, len)
                   AH   25
                   ES:DI     char far* addr
                   CX   len

                error return:
                   carry     set
                   DH   error code

                   possible errors:
                        CANT_SET
                        BAD_ADDRESS

                non-error return:
                   carry     clear
                   CX   length

                This call is used when the  application or protocol stack
                needs to use a specific LAN address. For instance, DECnet
                protocols on Ethernet encode the protocol  address in the
                Ethernet address,  requiring  that  it  be set  when  the
                protocol stack is  loaded. A BAD_ADDRESS  error indicates
                that the Packet Driver doesn't like the len (too short or
                too long),  or the  data itself  (a driver  may refuse  a
                station address with the 'group' bit  set, for instance).
                Note that  packet  drivers should  refuse  to change  the
                address (with a CANT_SET  error) if more than  one handle
                is open  (lest  it  be  changed  out from  under  another
                protocol stack).

           6.24 send_raw_bytes()       extended driver function
                send_raw_bytes(buffer, length)
                   AH   26
                   DS:SI     char far* buffer
                   CX   count

                error return:
                   carry     set
                   DH   error code

                   possible errors:
                        BAD_MODE       /* Not in raw mode */
                        BAD_COMMAND    /* Not a serial line driver */

                non-error return:
                   carry flag clear

                Transmits the  string of  bytes in  buffer for  the given
                count out the serial  port. This routine does  not return
                until the last  transmit interrupt for  the last  byte of
                the string has been successfully processed. It is assumed
                that the packet driver has been placed in raw mode before
                the call is made. If not, a BAD_MODE error is returned.






           6.25 flush_raw_bytes()      extended driver function
                flush_raw_bytes()
                   AH   27

                error return:
                   carry     set
                   DH   error code

                   possible errors:
                        BAD_MODE       /* Not in raw mode */
                        BAD_COMMAND    /* Not a serial line driver */

                non-error return:
                   carry     clear

                Flushes the receive ring buffer of  any characters it may
                have received. It is  assumed that the packet  driver has
                been placed in raw mode before the call  is made. If not,
                a BAD_MODE error is returned.

           6.26. fetch_raw_bytes()          extended driver function
                fetch_raw_bytes(buffer, buf_len, timeout)
                   AH   28
                   DS:SI     char far* buffer
                   CX   buf_len
                   DX   timeout

                error return:
                   carry     set
                   DH   error code

                   possible errors:
                        BAD_MODE
                        BAD_COMMAND

                non-error return:
                   carry     clear
                   CX   bytes copied

                Fetch bytes from the serial port until either the timeout
                expires,  or  the  specifed  count  of   bytes  has  been
                received.  The  timeout   is  measured  in   clock  ticks
                (~18/sec). It is assumed that the  packet driver has been
                placed in raw  mode before  the call is  made. If  not, a
                BAD_MODE error is returned.

           6.27. signal
                int signal (signal_number, data)
                   AH   29
                   AL   signal_number
                        = 1  REGISTER_UPCALL
                        = 2  UNREGISTER_UPCALL
                        = 3  THIS_LAYER_START





                        = 4  THIS_LAYER_FINISH
                        = 5  PHYSICAL_UP_EVENT
                        = 6  PHYSICAL_DOWN_EVENT
                   if AL = 1 or AL = 2, data is:
                        ES:DI     int (far *signal_handler)();

                error return:
                   carry     set
                   DH   error code

                   possible errors:
                        BAD_COMMAND    /* The command  is not  implemented
                */
                        BAD_SIGNAL          /*   The    signal   is    not
                implemented */
                    if AL = 2
                        BAD_ARGUMENT   /* The upcall was not registered */

                non-error return:
                   carry     clear

                signal handler upcall:
                   (*signal_handler)(event)
                        AX   event
                             = 1  THIS_LAYER_DOWN
                             = 2  THIS_LAYER_UP
                   No return value

                The  signal()  call  allows  the  client  application  to
                register an  upcall  which  can  be used  for  signalling
                events. This  mechanism was  designed  to accomodate  the
                requirements  of  a   PPP  packet  driver,   however  the
                mechanism was also designed to be  as generic as possible
                so that it hopefully may be used for other as yet unknown
                purposes in the future.

                Before a client application can expect event signals from
                the packet driver,  the client application  must register
                its signal_handler() upcall with the  packet driver. This
                is accomplished by calling signal()  with a signal_number
                of  REGISTER_UPCALL  and  also   supplying  the  function
                pointer of the signal_handler()  upcall as the  data. The
                packet driver then records this upcall pointer in a table
                and uses it to signal an event to the client application.

                Before  the   client   application   exits,  the   client
                application must unregister its  signal_handler() upcall.
                This  is   accomplished  by   calling  signal()   with  a
                signal_number of UNREGISTER_UPCALL and also supplying the
                function pointer of the upcall as the data. If the upcall
                is not  unregistered,  the  packet  driver may  call  the
                unloaded routine  with  unpredictable  results, (ie.  the
                machine will likely hang).





                For the purposes of a PPP packet driver, this call allows
                the NCP layers and the  LCP layer to send  signals to one
                another. An NCP layer  sends signals to the  LCP layer by
                calling signal(). The LCP layer sends  signals to the NCP
                layers by calling the signal_handler() upcall.

                For the purposes of PPP, the NCP  layers use the signal()
                call to send  the THIS_LAYER_START  and THIS_LAYER_FINISH
                signals  to  the  LCP   layer.  The  LCPlayer   uses  the
                registered   signal_handler    upcall    to   send    the
                THIS_LAYER_UP and  THIS_LAYER_DOWN  signals  to  the  NCP
                layers.

                In the case  where the LCP  layer is a  standalone packet
                driver seperate  from the  physical layer  packet driver,
                the  LCP  layer  uses  the  signal()  call  to  send  the
                THIS_LAYER_START and  THIS_LAYER_FINISH  signals  to  the
                physical layer.  The physical  layer uses  the registered
                signal_handler  upcall  to  send  the  THIS_LAYER_UP  and
                THIS_LAYER_DOWN signals to the LCP layer.

                See the description of PPP (Class  16/18) under "Specific
                Characteristics of Classes" for more detail.

           6.28. get_structure
                get_structure(structure_type)
                   AH   30
                   BX   structure_type

                error return:
                   carry     set
                   DH   error code

                   possible errors:
                        BAD_ARGUMENT        /*    structure_type     value
                unknown */

                non-error return:
                   carry     clear
                   DS:SI     char far* structure_ptr

                Returns a  pointer  to  the  structure indicated  in  the
                structure_type argument.  The  format  of  the  structure
                varies with the  value of  structure_type. Packet drivers
                should implement the structures which  are most relevant,
                and  must  return  BAD_ARGUMENT  for  any  structure  not
                implemented.

                The client application should assume  that the structures
                are  dynamic,  and  copy  them  to   local  storage  with
                interrupts disabled.

         7. Specific Characteristics of Classes





                Packet Drivers  have  been  developed for  the  following
                media  classes,  and  interpretations  of  demultiplexing
                criteria, MTU  etc.  have  stabilized.  If  you  wish  to
                implement a Packet Driver for a  class which isn't listed
                below, you should contact FTP Software  to make sure that
                your interpretation
                agrees with any other work we may be aware of.

           7.1. DIX Ethernet (Class 1)
                Class 1  is demultiplexed  by the  'ethertype', a  16-bit
                value (MSB  first)  transmitted  as  the  thirteenth  and
                fourteenth bytes of a frame.  typelen  is normally 2. The
                maximum length allowed by send_pkt() is  1514, 1500 bytes
                of data  preceded  by  the  14-byte  MAC  header  (source
                address, destination  address,  ethertype).  The  minimum
                "look-ahead buffer" length  allowed is  60 bytes.  If the
                typelen is  0, requesting  promiscuous  mode, the  driver
                should pass  both Class  1 and  Class 11  packets to  the
                protocol stack.

           7.2. 802.5 Token Ring (Class 3)
                Class 3 is demultiplexed according to the contents of the
                IEEE 802.2 header which  follows the 802.5 header  in the
                packet.  typelen   values  may   vary   between  1   (for
                demultiplexing on the  Destination SAP  only) and  8 (for
                demultiplexing on a complete  RFC 1042 header:  SNAP, OUI
                and 'ethertype'). In any comparison which, like RFC 1042,
                includes the 802.2 'control' field, the  driver must mask
                the 'poll/final' bit in  the 'control' byte prior  to the
                comparison.

                On  the   wire,   802.5   headers  are   variable-length,
                consisting of the 14-byte  802.5 MAC header,  an optional
                Routing  Information   Field   (used  by   source-routing
                bridges), and finally  the variable-length  802.2 header.
                Across the Packet Driver interface (in receiver() upcalls
                and in calls to  send_pkt()), the RIF  remains unmodified
                (unlike Class  17). The  802.2  header remains  variable-
                length.

                If an application needs to determine if a RIF is actually
                present  in  a  received  packet,  it  must  examine  the
                RIF_present bit in the source MAC  address (this occupies
                the same location  as the global  bit in  the destination
                MAC address). If an application needs to  send a RIF, the
                'RIF length'  and other  components of  the  RIF must  be
                inserted between the MAC addresses and  the 802.2 header.
                The user is responsible  for setting the  RIF_present bit
                in the source MAC address if necessary.

                The MTU  on  802.5  is  variable, negotiated  during  the
                initial    exchange    of    RIFs.    Several    existing
                implementations of IP over  802.5 require that  the value





                encoded in the RIF be 2052 bytes. The minimum "look-ahead
                buffer" length allowed is 100 bytes.

           7.3. Appletalk (Class 5)
                Class 5  provides  access  to  an ATALK.SYS  driver,  for
                forwarding IP packets to  and from an Internet  Router on
                an Appletalk  net. As  such, there  is no  demultiplexing
                taking place within the Packet Driver,  and typelen is 0.
                No header is prefixed to the IP datagram on transmission.
                The  MTU  is  568  bytes,  derived  from  the  underlying
                Appletalk DDP service.

           7.4. SLIP (Class 6)
                SLIP as defined in  RFC 1055 does not  include any packet
                demultiplexing information.  Thus, type  and typelen  are
                irrelevant,  and  all  open  handles   receive  the  same
                packets.  Many   implementations  assume   an  MTU   (not
                including any  byte-stuffing required  to escape  in-band
                control characters  found  in the  data  stream) of  1006
                bytes, but there are exceptions.

                Note that the get_address() function is not applicable to
                Class 6.

           7.5. AX.25 Amateur Radio (Class 9)
                The AX.25  frame structure  looks like  this (taken  from
                version 2.0 of the spec):

                U and S frame:
                   First Bit Sent
                   Flag     Address      Control FCS     Flag
                   01111110 112/560 Bits 8 Bits  16 Bits 01111110

                Information frame:
                Flag     Address      Control PID    Info.    FCS
                Flag
                01111110 112/560 Bits 8 Bits  8 Bits N*8 Bits 16 Bits
                01111110

                The Address  field has  a variable  length because  it is
                used to hold the source and  destination callsigns, and 0
                to seven callsigns  of radio stations  which are  used to
                repeat the packet.  The control  field contains  N(r) and
                N(s), a poll/final bit, and some other stuff not relevant
                to this discussion. The information field  is an integral
                number of octets long. AX.25 doesn't  specify the MTU; my
                driver will handle 2k.  The FCS is CRC-16.  The PID field
                specifies the  layer 3  protocol in  use,  such as  AX.25
                layer 3, IP, ARP, NET/ROM, etc.

                Phil Karn's KA9Q  implementation calls the  packet driver
                with typelen set to zero. It is  proposed that the driver
                should accept a pointer  to a PID field  with typelen set
                to 1 byte, in the future.






                Note that the get_address() function is not applicable to
                Class 9.

           7.6. 802.3 with 802.2 headers (Class 11)
                Class 11 is  demultiplexed according  to the  contents of
                the IEEE  802.2 header  which follows  the 14-byte  802.3
                header in the packet.  typelen values may vary  between 1
                (for demultiplexing on  the Destination  SAP only)  and 8
                (for demultiplexing on a complete RFC  1042 header: SNAP,
                OUI and 'ethertype'). The MTU is fixed at 1514 bytes, the
                same as DIX ethernet, but because of  the presence of the
                802.2 header, the usable data length is  at least 3 bytes
                shorter. The minimum  "look-ahead buffer"  length allowed
                is 60 bytes.

           7.7. FDDI with 802.2 headers (Class 12)
                Class 12 is  demultiplexed according  to the  contents of
                the IEEE 802.2  header which follows  the FDDI  header in
                the packet.  typelen  values  may  vary  between  1  (for
                demultiplexing on the  Destination SAP  only) and  8 (for
                demultiplexing on a complete  RFC 1042 header:  SNAP, OUI
                and 'ethertype'). In any comparison which, like RFC 1042,
                includes the 802.2 'control' field, the  driver must mask
                the 'poll/final' bit in  the 'control' byte prior  to the
                comparison. The MTU is  variable, The Packet  Driver must
                perform the bit-swap on all MAC  addresses, because while
                the bit order on  the physical FDDI media  matches 802.5,
                the bit order handled by the protocol stacks is specified
                as matching 802.3.

           7.8. Internet X.25 (Class 13)
                Class 13 is a special case: It is  designed to allow X.25
                to be used  as a  transport for  IP and  other datagrams.
                Each packet  of  data  sent  by  the  protocol  stack  is
                preceded by a protocol specific header; the first byte is
                protocol type and the  meaning of the rest  of the header
                varies with protocol type.  IP's protocol type is  1, and
                its header is defined as follows:

                struct x25_pd_hdr {
                  unsigned char type;  /* Type: 1 indicates IP
                */
                  unsigned char tos;   /* IP Type Of Service value to use
                */
                  unsigned long dest;  /* IP next hop address
                */
                  unsigned long src;   /* IP Source address
                */
                };

                Header layouts specific  to other protocol  families will
                be defined as the need arises.   The typelen value passed
                to access_type() is always 1, and the type pointer points





                at a byte defining the protocol to be  received; 1 for IP
                as above. On receiver() upcalls, the header specified for
                transmission is present, but only the  type value is set.
                The MTU is  variable, depending  on the  configuration of
                the attached  network.  The  minimum "look-ahead  buffer"
                length is 40 bytes.

           7.9. Northern Telecom LANSTAR encapsulating DIX (Class 14)
                Class 14 is  a "simulated ethernet"  class, and  the MTU,
                demultiplexing and other  characteristics are  similar to
                Class 1.

           7.10. Point to Point Protocol MAC layer driver (Class 16)
                Note:  Class  16 drivers are  obselete and should  not be
                used, with the exception for very  special cases (such as
                LANWatch).  PC/TCP uses a class 18 driver to do PPP.

                The MTU  of a  PPP  link is  determined  at link  startup
                through  the  negotiation  of   the  Maximum-Receive-Unit
                (MRU). The MRU of the link is the size  of the info field
                of a  PPP  frame,  and  does  not include  the  two  byte
                protocol field in the header. Thus, just as the MTU of an
                ethernet frame is 1500  for the data area,  plus 14 bytes
                for the header,  the MTU of  a PPP link  is equal  to the
                negotiated MRU plus 2 for its header.

                Class 16 is demultiplexed based on  the two byte protocol
                field in the PPP frame header.   The packet driver passes
                to the protocol stack the PPP protocol field, followed by
                the info  field.  The stack  can  examine  this field  to
                determine the protocol type of the incoming packet.

                In packets passed to send_packet, the protocol stack must
                set an appropriate value in the  PPP protocol field ahead
                of the PPP  info field.  The packet  driver will  add the
                flag, address,  control, and  FCS bytes  as it  sends the
                packet.

                During PPP frame  reception, the flag,  address, control,
                and FCS  bytes of  a PPP  frame are  all consumed  by the
                packet driver  before  the packet  is  passed  up to  the
                protocol stack.

                During PPP  frame reception,  the  total incoming  length
                cannot be determined at the time that only the PPP header
                has been successfully  parsed. The  entire frame  must be
                received before  the  actual  length can  be  determined.
                Since for performance reasons it is preferable to receive
                the incoming frame  into a  protocol stack  buffer rather
                than into a local buffer, the only recourse is to request
                a full size buffer from the protocol stack just after the
                frame header has been fully received, but before the info
                field has been received.





                The buffer size requested  from the protocol  stack would
                be at least MRU+2 where the two extra  bytes hold the two
                byte protocol field.  However, in  order to  simplify the
                implementation of an  async PPP  packet driver,  the size
                requested must be MRU+4, which allows  not only two bytes
                for the protocol field,  but also two more  bytes to hold
                the FCS field which occurs at the end  of the frame. Once
                the closing flag  has been received,  the length  must be
                decreased by 2 to adjust for the FCS field.

                Thus a  class  16  protocol  stack  must  be  capable  of
                supplying buffers  which  total  MRU+4  bytes, so  as  to
                accomodate  the  needs  of  an  asynchronous  PPP  packet
                driver.

           7.11. 802.5 Token Ring w/expanded RIFs (Class 17)
                Class 17 is demultiplexed in the same way as Class 3, and
                has the same MTU and minimum  "look-ahead buffer" length.
                The significant  difference  is  that across  the  Packet
                Driver interface (in receiver()  upcalls and in  calls to
                send_pkt()), the RIF  is padded to  its maximum  size, 18
                bytes, while  the 802.2  header remains  variable-length.
                This was defined this  way to streamline RIF  handling in
                protocol implementations where  fixed buffer  offsets are
                used to increase performance.

                If an application needs to determine if a RIF is actually
                present  in  a  received  packet,  it  must  examine  the
                RIF_present bit in the source MAC  address (this occupies
                the same location  as the global  bit in  the destination
                MAC address). If an application needs to  send a RIF, the
                'RIF length'  and other  components of  the  RIF must  be
                left-justified in the RIF  area. Because it  must perform
                RIF expansion, send_pkt() is responsible  for setting the
                RIF_present bit in the source MAC address if necessary.

                Note that  the  RIF  expansion  on  received  packets  is
                specified to  take place  during the  data  copy, so  the
                "look-ahead buffer" will contain a compressed  RIF on the
                AX == 0 receiver() upcall.

           7.12. Point to Point Protocol with LLC layer (Class 18)
                WARNING: The information presented on the class 18 packet
                driver is a documentation of how  FTP Software wrote it's
                PPP16550 packet driver  that shipped with  PC/TCP version
                3.0 and OnNet  version 1.1.   It is presented  purely for
                historical and/or  compatibility reasons,  and should  be
                implemented only when compatibility is desired with these
                versions of software.   Future drivers from  FTP Software
                will likely not  utilize the class  18 packet  driver for
                PPP communications.

                Note:  Much  of the text  below assumes  familiarity with
                the PPP RFC's, notably RFCs 1548 and 1549.






                Components
                All  class  18  packet  drivers  contain  an  LCP  option
                negotiation layer.  This  layer  allows them  to  perform
                common link  level option  negotiation on  behalf of  the
                client applications.  All NCP  option negotiation  layers
                are provided by the client applications.

                All class  18  packet drivers  except  type  1 contain  a
                physical link driver  in addition to  the LCP  layer. The
                class 18 type 1  packet driver contains an  LCP layer but
                no physical link level driver. The class 18 type 1 packet
                driver instead  relies on  a class  16  packet driver  to
                supply  the  physical  link   driver  functionality.  The
                purpose  behind   this  arrangement   is  to   avoid  the
                reimplementation of  the  LCP layer  in  each PPP  packet
                driver written.

                Because there  must be  only one  LCP entity  but perhaps
                multiple NCP entities, client  applications which provide
                network layer service such as IP/IPCP or IPX/IPXCP should
                avoid including an LCP layer.  Client applications should
                rely on and share the services of this LCP equipped class
                18 packet driver.

                Packet Processing
                PPP frames received  are demultiplexed  based on  the two
                byte protocol  field  found  in  the  PPP  header.  Valid
                protocol field  values  are defined  in  RFC1548. If  the
                sender used  protocol  field  compression to  reduce  the
                protocol field ot  one byte, the  field must  be expanded
                again to two bytes before demultiplexing.

                The info field of the PPP frame contains the higher layer
                protocol data. The length  of the info field  varies from
                frame to frame,  and is  not indicated  in the  PPP frame
                header. However the  maximum length  (called the  MRU) is
                negotiated at  link  startup  using  LCP packets  and  is
                guaranteed not to change for the duration of the link, or
                until LCP negotiation reoccurs. Thus, the MTU of the link
                is determined by the LCP layer during option negotiation.

                In packets passed  to send_pkt(), the  client application
                must set an appropriate  value in the PPP  protocol field
                ahead of the PPP  info field. The packet  driver will add
                the flag, address, control and FCS bytes  as it sends the
                packet.

                The packet driver  passes to  the client  application the
                PPP protocol field followed by the  info field. The flag,
                address, control and  FCS bytes  of a  PPP frame  are all
                consumed by the packet driver before the packet is passed
                up to the client application.





                The FCS is  verified by the  physical link driver  in the
                packet driver.  If the  FCS is  valid, the  packet driver
                passes  the   frame  to   the   client  application   for
                processing.  The  client  application   can  examine  the
                protocol field  to  determine the  protocol  type of  the
                packet. If the FCS is invalid, the frame is discarded and
                the packet  driver  returns  the  buffer  to  the  client
                application with a zero length.

                During receiver() upcall processing, a client application
                should be  prepared to  honor a  request from  the packet
                driver for  a packet  size of  up to  MRU+4. The  extra 4
                bytes include 2 for the protocol field, and 2 for the FCS
                field. Although the contents of the 2 byte FCS field will
                not be interesting to the client application, the extra 2
                bytes for the FCS are useful  in implementing async byte-
                oriented packet  drivers.  Because  there  is  no  length
                field,  a  byte-oriented  frame   parser  implemented  in
                software can only determine the position of the FCS field
                once it  has received  the end-of-frame  flag. Using  the
                default MRU size  of 1500  bytes, the  application should
                allocate 1504-byte buffers. If  the MTU is  negotiated to
                some size  smaller or  larger than  1500 bytes,  then the
                client application should take this  alternate MTU value,
                add 4 and use this number as the buffer size to offer the
                packet driver.

                Layer Signalling and Packet Type Registration
                The RFC1548  PPP option  negotiation automaton  specifies
                the following events for  use in driving  the negotiation
                process: START, FINISH,  UP, DOWN. Notification  of these
                events must be passed between the NCP and LCP layers (and
                between the LCP and physical link  driver layers, if they
                are different drivers). The signal() call defined in this
                spec is used to pass these  indications between the TSR's
                which implement the  NCP, LCP,  and physical  link driver
                layers.

                At startup, the NCP layer and  the network protocol layer
                should not  call access_type()  in the  packet driver  to
                hook their protocol types, but should make instead a call
                to the LCP  layer using  signal() with  a REGISTER_UPCALL
                signal in  order to  register  a signal_handler()  upcall
                with the LCP  layer. It should  then call  signal() again
                with a THIS_LAYER_START signal. Then it must wait for the
                LCP  layer  to  signal  a  THIS_LAYER_UP  event  via  the
                signal_handler() upcall. Once the THIS_LAYER_UP signal is
                received, the NCP layer can hook  its protocol type value
                (ie. 0x8021  for  IPCP) and  begin  negotiation with  the
                peer. Once  the  NCP has  reached  an  OPENED state  (see
                RFC1331) the  network layer  can hook  its protocol  type
                (ie. 0x0021 for IP) and begin passing packets.





                If at any point the NCP  layer receives a THIS_LAYER_DOWN
                event from the LCP  layer, the NCP layer  must notify the
                network layer,  and both  the NCP  layer and  the network
                layer   must   unhook   their    protocol   types   using
                release_type()  until  the  LCP  layer  again  signals  a
                THIS_LAYER_UP event.

                When the  NCP/network  layer exits,  it  must unhook  its
                protocol types, signal  a THIS_LAYER_FINISH event  to the
                LCP layer  using the  signal() call,  and unregister  the
                signal_handler()  using   the  signal()   call  with   an
                UNREGISTER_HANDLER signal.

                When a  class 18  packet  driver starts  up,  it must  be
                prepared to begin  negotiating LCP options  regardless of
                whether  any  client   applications  have  or   have  not
                registered a  signal_handler().  As  client  applications
                register    signal_handler()     upcalls     and     send
                THIS_LAYER_START signals, the packet driver must save the
                upcall routine pointers in  a table. After  registering a
                signal upcall for a new client  application in the table,
                the packet  driver  should check  the  LCP layer  current
                state. If the LCP layer is currently  in an OPENED state,
                the packet driver should  send a THIS_LAYER_UP  signal to
                the client application immediately before returning.

                Each time the LCP layer transitions into an OPENED state,
                it must traverse the table of registered signal_handler()
                upcalls and  send  a  THIS_LAYER_UP  signal  to  each  in
                succession. Each time the LCP layer transitions out of an
                OPENED state, it  must traverse  the table  of registered
                signal_handler()  upcalls  and  send   a  THIS_LAYER_DOWN
                signal to each in succession.   This corresponds with the
                PPP automaton table's tlu and tld events.

                In order to simplify the implementation  of the protocol-
                reject mechanism defined in RFC1548, the LCP layer of the
                class 18 to  class 16  converter will  call access_type()
                with typelen of zero to receive packets with unregistered
                protocol types. When the class 16  packet driver receives
                a access_type()  call with  a typelen  argument value  of
                zero, the receiver() upcall function must be passed every
                subsequently received  packet for  which there  is not  a
                registered protocol type receiver.  The LCP layer  in the
                converter  can  then   send  protocol-reject   frames  in
                response to packets with unrecognized protocols.

                LCP Option Configuration
                Before LCP layer option negotiation begins, the LCP layer
                must  be  configured  with   a  set  of   initial  option
                parameters. There may be a requirement that the values of
                these parameters vary  from one  connection to  the next.
                The get_structure() call is used to retrieve a pointer to
                a structure within the  LCP layer in the  class 18 packet





                driver. Using  this pointer,  the client  application can
                copy the desired  values into the  LCP layer  data space.
                See Appendix E for structure layout.

                After the LCP layer option negotiation completes, the LCP
                layer must reconfigure the physical link  driver with the
                final negotiated values. The get_structure() call is used
                to  retrieve  a  pointer  to  the  structure  within  the
                physical link  driver  in the  class  16  (or 18)  packet
                driver which holds the current operating  values. The LCP
                layer uses  this pointer  to copy  in  the new  operating
                values. See Appendix E for structure layout.

                When the LCP layer  transitions out of the  OPENED state,
                the LCP layer must reset the  current operating values in
                the  physical  link  driver  to  the  default  values  as
                specified in RFC1548. The get_structure() call is used to
                retrieve a pointer to  the structure within  the physical
                link driver in the  class 16 (or 18)  packet driver which
                holds the current  operating values.  The LCP  layer uses
                this pointer to copy in the default operating values. See
                Appendix E for structure layout.





         Appendix A. Interface classes and types
                The following are  defined as network  interface classes,
                with their individual types  listed immediately following
                the class.



                Class 1                DEC/Intel/Xerox "Bluebook" Ethernet



                3COM 3C500/3C501 ........................................1
                3COM 3C505 ..............................................2
                InterLan NI50103 ........................................3
                BICC Data Networks 4110 .................................4
                BICC Data Networks 4117 .................................5
                InterLan NP600 ..........................................6
                Ungermann-Bass PC-NIC ...................................8
                Univation NC-516 ........................................9
                TRW PC-2000 ............................................10
                InterLan NI5210 ........................................11
                3COM 3C503 .............................................12
                3COM 3C523 .............................................13
                Western Digital WD8003 .................................14
                Spider Systems S4 ......................................15
                Torus Frame Level ......................................16
                10NET Communications ...................................17
                Gateway PC-bus .........................................18
                Gateway AT-bus .........................................19
                Gateway MCA-bus ........................................20
                IMC Pcnic ..............................................21
                IMC PCnic II ...........................................22
                IMC PCnic 8bit .........................................23
                Tigan Communications ...................................24
                Micromatic Research ....................................25
                Clarkson "Multiplexor" .................................26
                D-Link 8-bit ...........................................27
                D-Link 16-bit ..........................................28
                D-Link PS/2 ............................................29
                Research Machines parallel .............................30
                Research Machines 16 ...................................31
                Research Machines MCA ..................................32
                Radix Microsys. EXM1 16-bit ............................33
                InterLan NI9210 ........................................34
                InterLan NI6510 ........................................35
                Vestra LANMASTER 16-bit ................................36
                Vestra LANMASTER 8-bit .................................37
                Allied Telesis PC/XT/AT ................................38
                Allied Telesis NEC PC-98 ...............................39
                Allied Telesis Fujitsu FMR .............................40
                Ungermann-Bass NIC/PS2 .................................41
                Tiara LANCard/E AT .....................................42
                Tiara LANCard/E MC .....................................43
                Tiara LANCard/E TP .....................................44





                Spider Comm. SpiderComm 8 ..............................45
                Spider Comm. SpiderComm 16 .............................46
                AT&T Starlan NAU .......................................47
                AT&T Starlan-10 NAU ....................................48
                AT&T Ethernet NAU ......................................49
                Intel smart card .......................................50
                Xircom Pocket Adapter / Credit Card Adapter ............51
                Aquila Ethernet ........................................52
                Novell NE-1000 .........................................53
                Novell NE-2000 .........................................54
                SMC PC-510 .............................................55
                AT&T Fiber NAU .........................................56
                NDIS to Packet Driver adapter ..........................57
                InterLan ES3210 ........................................58
                General Systems ISDN simulated Ether ...................59
                Hewlett-Packard ........................................60
                IMC EtherNic-8 .........................................61
                IMC EtherNic-16 ........................................62
                IMC EtherNic-MCA .......................................63
                NetWorth EtherNext .....................................64
                Dataco Scanet ..........................................65
                DEC DEPCA ..............................................66
                C-net ..................................................67
                Gandalf LANLine ........................................68
                Apricot built-in .......................................69
                David Systems Ether-T ..................................70
                ODI to Packet Driver adapter ...........................71
                AMD Am2110 16-bit ......................................72
                Intel ICD Network controller family ....................73
                Intel ICD PCL2 .........................................74
                Intel ICD PCL2A ........................................75
                AT&T LANPacer ..........................................76
                AT&T LANPacer+ .........................................77
                AT&T EVB ...............................................78
                AT&T StarStation .......................................79
                SLIP simulated ether (skl) .............................80
                InterLan NIA310 ........................................81
                InterLan NISE ..........................................82
                InterLan NISE30 ........................................83
                InterLan NI6610 ........................................84
                Ether over IP/UDP ......................................85
                ICL EtherTeam 16 .......................................86
                David Systems Ether-T AT Plus ..........................87
                NCR WaveLAN ............................................88
                Thomas Conrad TC5045 ...................................89
                Parallel Port driver ...................................90
                Intel EtherExpress 16 ..................................91
                IBMTOKEN simulated Ether on 802.5 ......................92
                Zenith Data Systems Z-Note .............................93
                3Com 3C509 .............................................94
                Mylex LNE390 ...........................................95
                Madge Smart Ringnode ...................................96
                Novell NE2100 ..........................................97
                Allied Telesis 1500 ....................................98





                Allied Telesis 1700 ....................................99
                Fujitsu EtherCoupler ..................................100



                Class 2                                          ProNET-10



                Proteon p1300 ...........................................1
                Proteon p1800 ...........................................2



                Class 3                   IEEE 802.5 without expanded RIF



                IBM Token ring adapter ..................................1
                Proteon p1340 ...........................................2
                Proteon p1344 ...........................................3
                Gateway PC-bus ..........................................4
                Gateway AT-bus ..........................................5
                Gateway MCA-bus .........................................6
                Madge ??? ...............................................7
                NDIS to Packet Driver adapter ..........................57
                ODI to Packet Driver adapter ...........................71



                Class 4                                            Omninet





                Class 5                                          Appletalk



                ATALK.SYS adapter .......................................1



                Class 6                                 Serial line (SLIP)



                Clarkson 8250-SLIP / PC/TCP's SLP16550.COM ..............1
                Clarkson "Multiplexor" ..................................2
                Eicon Technologies ......................................3







                Class 7                                          Starlan



                Note:   This class  was consumed  by  the Ethernet  class
                (class 1).



                Class 8                                             ArcNet



                Datapoint RIM ...........................................1



                Class 9                                              AX.25



                Ottawa PI card ..........................................1
                Eicon Technologies ......................................2



                Class 10                                              KISS





                Class 11                           IEEE 802.3 w/802.2 hdrs



                Types as given under Class 1 (DIX Ethernet)



                Class 12                                 FDDI w/802.2 hdrs





                Class 13                                     Internet X.25



                Western Digital .........................................1
                Frontier Technology .....................................2





                Emerging Technologies ...................................3
                The Software Forge ......................................4
                Link Data Intelligent X.25 ..............................5
                Eicon Technologies ......................................6



                Class 14                  N.T. LANSTAR (encapsulating DIX)



                NT LANSTAR/8 ............................................1
                NT LANSTAR/MC ...........................................2



                Class 15                            SLFP (MIT serial spec)



                MERIT ...................................................1



                Class 16                  Point to Point Protocol (no LCP)



                8250/16550 UART .........................................1
                Niwot Networks synch ....................................2
                Eicon Technologies ......................................3



                Class 17                     IEEE 802.5 with expanded RIFs



                Types as given under Class 3 (802.5 with verbatim RIFs)



                Class 18                Point to Point Protocol (with LCP)



                Class 16 to class 18 converter ..........................1
                PC/TCP's PPP16550.COM ...................................2





         Appendix B. Function call numbes
                The following decimal numbers  are used to  specify which
                operation the packet driver should perform. The number is
                stored in register AH on call to the packet driver.

                driver_info .............................................1
                access_type .............................................2
                release_type ............................................3
                send_pkt ................................................4
                terminate ...............................................5
                get_address .............................................6
                reset_interface .........................................7
                +get_parameters ........................................10
                +old_as_send_pkt .......................................11
                +as_send_pkt ...........................................12
                +drop_pkt ..............................................13
                *set_rcv_mode ..........................................20
                *get_rcv_mode ..........................................21
                *set_multicast_list ....................................22
                *get_multicast_list ....................................23
                *get_statistics ........................................24
                *set_address ...........................................25
                *send_raw_bytes ........................................26
                *flush_raw_bytes .......................................27
                *fetch_raw_bytes .......................................28
                *signal ................................................29
                *get_structure .........................................30

                + indicates a high-performance packet driver function
                * indicates an extended packet driver function

                AH values from  128 through 255  (0x80 through  0xFF) are
                reserved   for   user-developed   extensions    to   this
                specification. While  FTP  Software  cannot support  user
                extensions, we are willing to act as a clearing house for
                information about them. For more information, contact us.

                The following values  have been  allocated to  the listed
                organizations:
                   233  Crynwr Software          autoselect transceiver





         Appendix C. Error codes
                Packet driver calls indicate  error by setting  the carry
                flag on return. The error code is returned in register DH
                (a register not used to pass values  to functions must be
                used to return the error code). The following error codes
                are defined:

                1   BAD_HANDLE    Invalid handle number
                2   NO_CLASS      No interfaces of specified class found
                3   NO_TYPE       No interfaces of specified type found
                4   NO_NUMBER     No interfaces of specified number found
                5   BAD_TYPE      Bad packet type specified
                6   NO_MULTICAST  This   interface   does   not    support
                multicast
                7   CANT_TERMINATE     This packet driver cannot terminate
                8   BAD_MODE      An invalid receiver mode was specified
                9   NO_SPACE      Operation failed because of insufficient
                space
                10  TYPE_INUSE    The type had  previously been  accessed,
                and not released
                11  BAD_COMMAND   The command  was out  of range,  or  not
                implemented
                12  CANT_SEND     The packet  couldn't  be  sent  (usually
                hardware error)
                13  CANT_SET      Hardware  address  couldn't  be  changed
                (more than 1handle open)
                14  BAD_ADDRESS   Hardware  address  has  bad  length   or
                format
                15  CANT_RESET    Couldn't reset  interface (more  than  1
                handle open)





         Appendix D. 802.3 vs. Blue Book Ethernet
                An issue  concerning the  present  specification is  that
                there is no provision  for simultaneous support  of 802.3
                and Blue Book (the old DEC-Intel-Xerox standard) Ethernet
                headers via  a single  Packet Driver  (as defined  by its
                interrupt). The  problem is  that the  Ethertype of  Blue
                Book packets is in bytes 12 and 13 of  the header, and in
                802.3  the  corresponding  bytes  are  interpreted  as  a
                length. In 802.3, the field which would appear to be most
                useful to begin  the type check  in is the  802.2 header,
                starting at byte 14.  This is only a  problem on Ethernet
                and variants (e.g. Starlan), where 802.3 headers and Blue
                Book headers are likely  to need co-exist for  many years
                to come.

                One  solution  is  to  redefine  class  1  as  Blue  Book
                Ethernet, and  define  a parallel  class  for 802.3  with
                802.2 packet  headers. This  requires that  a 2nd  Packet
                Driver (as defined by its interrupt) be implemented where
                it is necessary to handle both kinds of packets, although
                they could both be part of the same TSR module.

                As of v1.07 of this specification,  class 11 was assigned
                to 802.3 using 802.2 headers, to implement the above.

                Note: According to this scheme, an application wishing to
                receive IP  encapsulated with  an 802.2  SNAP header  and
                Ethertype of  0x800,  per  RFC  1042,  would  specify  an
                typelen argument of 8, and type would point to:

                  char ieee_ip[] = {0xAA, 0xAA, 3, 0, 0, 0, 0x08, 0x00};

                                            James B. VanBokkelen





         Appendix E. Structure layout for get_structure call
                The packet  driver structures  detailed  below have  been
                created to allow a client application to access data held
                within the packet driver  in a generalized manner.   Each
                structure  has  a  structure_type  which   serves  as  an
                identifying tag.  This tag is used in the get_structure()
                call to specify the structure requested.

                The following  structure_types have  been  defined.   The
                corresponding structure layouts are also detailed.

                STRUCT_IO_STATS    1
                  struct io_statistics {
                      unsigned long  packets_in;
                      unsigned long  packets_out;
                      unsigned long  bytes_in;
                      unsigned long  bytes_out;
                      unsigned long  errors_in;
                      unsigned long  errors_out;
                      unsigned long  packets_lost;
                  };

                STRUCT_LCP_INITIAL_CONFIG  2
                  struct lcp_options {
                      unsigned mru;
                      unsigned long int rcvaccm;
                      unsigned long int sndaccm;
                      unsigned long int magic;
                      unsigned char acfc;
                      unsigned char pfc;
                      unsigned authprot;
                  };

                STRUCT_LCP_CURRENT_CONFIG  3
                  struct lcp_options {
                      unsigned mru;
                      unsigned mtu;
                      unsigned long int rcvaccm;
                      unsigned long int sndaccm;
                      unsigned long int magic;
                      unsigned char acfc;
                      unsigned char pfc;
                      unsigned authprot;
                  };

                STRUCT_LCP_PARAMS    4
                  struct lcp_params {
                      unsigned restart_ctr;
                      unsigned restart_timer;
                      unsigned timeout_period;
                      unsigned max_configure;
                      unsigned max_terminate;
                  };





                STRUCT_LCP_PKT_STATS  5
                  struct lcp_pkt_stats {
                      unsigned pkts_rcvd;
                      unsigned pkts_sent;
                      unsigned pkts_discarded;
                      unsigned code_unknown;
                      unsigned cnfg_req_rcvd;
                      unsigned cnfg_ack_rcvd;
                      unsigned cnfg_nak_rcvd;
                      unsigned cnfg_rej_rcvd;
                      unsigned term_req_rcvd;
                      unsigned term_ack_rcvd;
                      unsigned code_rej_rcvd;
                      unsigned prot_rej_rcvd;
                      unsigned echo_req_rcvd;
                      unsigned echo_rep_rcvd;
                      unsigned disc_req_rcvd;
                      unsigned prot_rej_sent;
                      unsigned rcvq_oflow;
                      unsigned sendq_oflow;
                  };

                STRUCT_LCP_EVENT_STATS  6
                  struct lcp_event_stats {
                      unsigned event_up;
                      unsigned event_down;
                      unsigned event_open;
                      unsigned event_close;
                      unsigned event_timeout_plus;
                      unsigned event_timeout_minus;
                      unsigned event_rcr_plus;
                      unsigned event_rcr_minus;
                      unsigned event_ruc;
                      unsigned event_rxj_plus;
                      unsigned event_rxj_minus;
                      unsigned event_rxr;
                      unsigned event_illegal;
                      unsigned event_ignored;
                  };

                STRUCT_LCP_STATE    7
                    struct lcp_state {
                      unsigned char status;
                      unsigned char lcp_state;
                      unsigned char state_history[10];
                      unsigned char state_history_num[11];
                      unsigned char padding;
                  };

                STRUCT_PAP_CONFIG    8
                  struct pap_config {
                      char *identity;
                      char *password;
                      char *message;





                  };

                STRUCT_PAP_STATS    9
                  struct pap_stats {
                      unsigned pkts_sent;
                      unsigned pkts_rcvd;
                      unsigned auth_req_sent;
                      unsigned auth_req_rcvd;
                      unsigned auth_ack_sent;
                      unsigned auth_ack_rcvd;
                      unsigned auth_nak_sent;
                      unsigned auth_nak_rcvd;
                      unsigned status;
                  };

                STRUCT_UART_CONFIG    10
                  struct uart_conf {
                      unsigned uart;
                      unsigned port;
                      unsigned io8250;
                      unsigned char irq;
                      unsigned char pattr;
                      unsigned char clrbda;
                      unsigned char rtscts;
                      unsigned long baud;
                      unsigned baudiv;
                  };

                STRUCT_UART_STATS    11
                  struct uart_stats {
                      unsigned long int rcv_ints;
                      unsigned long int xmt_ints;
                      unsigned long int modem_ints;
                      unsigned long int line_ints;
                      unsigned long int fifo_ints;
                      unsigned xmt_tmo;
                      unsigned breaks;
                      unsigned framing;
                      unsigned parity;
                      unsigned overruns;
                      unsigned rb_overflow;
                      unsigned char modem_status;
                  };

                STRUCT_HDLC_STATS    12
                  struct hdlc_stats {
                      unsigned long int mode1_bytes_rcvd;
                      unsigned long int mode6_bytes_rcvd;
                      unsigned long int mode7_bytes_rcvd;
                      unsigned over_mtu;
                      unsigned pkts_disc_no_bufs;
                      unsigned over_buffer;
                      unsigned max_len_pkt;
                      unsigned pkts_disc_no_lcp_bufs;





                      unsigned fcs_failures;
                      unsigned runt;
                      unsigned protocol_unknown;
                      unsigned char state;
                      unsigned char padding[3];
                  };

                STRUCT_TYPE_TABLE    13
                  struct type_table {
                      short maxentries;
                      short currentmode;
                      struct {
                        unsigned short handle;
                        unsigned short type;
                        void far* upcall;
                      } [maxentries];
                  };

                STRUCT_SIGNAL_TABLE  14
                  struct signal_table {
                      short maxentries;
                      struct {
                        unsigned short type;
                        void far* signal_upcall;
                      } [maxentries];
                  };