3Com/Microsoft LAN Manager Network Driver Interface Specification Version 2.0.1 Final

Chapter 1 - Introduction
This document describes the LAN Manager network driver architecture and interfaces that let a DOS or OS/2 system support one or more network adapters and protocol stacks. This architecture provides a standardized way for writing drivers for network adapters and communications protocols. It also solves the problem of how to configure and bind multiple drivers into the desired set of layered protocol stacks.

Drivers written to the interfaces defined here will function concurrently in a system with other networking and protocol drivers, and will operate correctly with the LAN Manager software for DOS and OS/2.

Definition of Terms
To simplify the job of supporting multiple adapters and protocols, the architecture defines four kinds of drivers:
 * Media access control (MAC) drivers, which provide low-level access to network adapters. The main function of a MAC driver is to support transmitting and receiving packets, plus some basic adapter management functions. MAC drivers are device drivers that are loaded during system initialization and remain permanently in memory. Since they cannot be unloaded, they are called "static."
 * Protocol drivers, which provide higher-level communication services from data link to application (depending on the driver). An example is a NetBIOS driver that provides a NetBIOS interface at the top and communicates with a MAC driver at the bottom. Protocol drivers can be device drivers, TSRs, or transient DOS applications. A protocol driver is called "static" if it cannot be unloaded. A protocol driver is called "dynamic" if it can be loaded and unloaded on demand.
 * MAC-layer entities, which bind to real MAC drivers and expose a new MAC-like layer interface on top. Possible examples are MAC bridges, test tools, or interface mappings that change the NDIS interface to meet some environment-specific administrative requirement.
 * The Protocol Manager driver, which is a special driver that provides a standardized way for multiple MAC and protocol drivers to get configuration information and bind together into the desired protocol hierarchy. The Protocol Manager gets all configuration information from a central file, PROTOCOL.INI.

Scope of This Document
This document defines
 * Protocol Manager functions and interfaces for configuration and binding of MAC and protocol drivers
 * The software interface between MAC and protocol drivers

Separate documents will specify the configuration and interface for other kinds of protocol drivers, including data link and transport drivers.

Changes for This Version
The major highlights of this version compared to the last (1.0) are
 * Support for dynamic binding/unbinding of protocol modules, allowing protocols to be swapped in and out of memory as needed. No changes are required of MAC drivers to support the dynamic bind/unbind features. In particular, NDIS 1.0.1 conformant MACs will support dynamically binding protocol modules.
 * Additional Protocol Manager functions to support dynamic binding and future administrative requirements.
 * Some adjustments to the ResetMAC function, and to the StartReset and EndReset primitives, were made to correct some inconsistencies and keep the logic out of critical paths.
 * Additional fields was added to certain tables to provide additional information. The presence or absence of these fields can be determined by examining the length field in each table.
 * Some new recommendations and clarifications on issues such as double-word alignment of data blocks, the use of the permanent station address, the copying of DS and Entry points, the use of 80386 32-bit registers, the release of internal resources before confirmations, the handling of zero-length data blocks, the formatting of MAC headers, the use of zero handles, and new transmit error codes for Token-Ring to support source routing.
 * A standard for protocol service-specific characteristics tables.
 * The inclusion of additional 802.3 and 802.5 specific information and added statistics definitions.
 * Additional information and caveats to help developers.
 * The Protocol Manager now has a transient component (in some configurations) called PROTMAN.EXE. This is now described with certain restrictions imposed on Protocol Manager primitives.
 * Some new error response codes were defined.
 * Appendix E, "Utilities Provided with the Protocol Manager," was added to describe some helpful bind and configuration management utilizes.
 * Selected statistics designated as mandatory for both service-specific and media-specific statistics (802.3 and 802.5).
 * Extended 802.3 statistics to include Number_of_Underruns.
 * OpenAdapter function expanded to permit driver return of vendor-specified warning errors and/or hardware error codes.

It is not expected that any of these changes will result in incompatibilities with protocol and MAC drivers written to previous versions of this specification. Great care was taken to avoid creating incompatibilities. It is the protocol's responsibility to identify and interoperate with older NDIS version driver implementations that may not have implemented support for statistics Older network drivers will co-exist with network drivers written to this specification. However, to take advantage of new features (such as dynamic binding), developers may wish to update their protocol drivers to be NDIS 2.0.1 compliant.

Chapter 2 - Configuration and Binding
A network server or workstation includes at least one MAC and one protocol driver, plus the Protocol Manager driver. More complex configurations can have multiple MAC and protocol drivers.

The Protocol Manager is always defined in CONFIG.SYS to load before any MAC or protocol drivers. Its job is to read the configuration information out of the PROTOCOL.INI file and make this available to MAC and protocol drivers that load later.

MAC and protocol drivers use this information to set initialization parameters and allocate memory appropriately. For example, a NetBIOS driver may use the configuration information provided by the Protocol Manager to determine its maximum number of names and sessions.

As each driver configures and initializes itself, it identifies itself to the Protocol Manager using a driver- defined "module name" and "characteristics table." The module name defines a kind of logical name for the communication service provided by the driver. The characteristics table provides specific parameters about the service and the set of entry points the driver uses to communicate with other drivers. A single driver may identify itself to the Protocol Manager as multiple logical modules if, for example, it implements more than one layer of protocol interface (such as transport and data link).

Before two modules can communicate, they must be bound together. Binding is the process of two modules exchanging characteristics tables so that they can access each others entry points. This establishes the linkage they need to make requests of one another and indicate asynchronous request completion. Binding is controlled by the Protocol Manager based on information from PROTOCOL.INI. Binding can be either static or dynamic for protocol drivers. If a protocol driver is static, then its binding is static. If it is dynamic, then its binding is dynamic. A dynamic protocol driver can be unbound from its bound drivers prior to unloading itself from memory. This unbinding process is also controlled through the Protocol Manager.

Configuration and Binding Process
In the typical case of a system with one MAC driver and a NetBIOS driver, the set of drivers loads and initializes as follows:
 * 1) Protocol Manager loads, initializes, and reads PROTOCOL.INI.
 * 2) MAC driver loads and calls GetProtocolManagerInfo to get any needed configuration information, such as its DMA channel.
 * 3) MAC driver initializes and calls RegisterModule to identify itself as the module named, for example, "ETHERCARD." This call passes ETHERCARD's characteristics table to the Protocol Manager.
 * 4) NetBIOS driver loads and calls GetProtocolManagerInfo to get any needed configuration information, such as the maximum number of names, sessions, and commands to support.
 * 5) NetBIOS driver initializes and calls RegisterModule to identify itself as the module named "NetBIOS." This call passes NetBIOS's characteristics table to the Protocol Manager and indicates that NetBIOS wants to bind to ETHERCARD.
 * 6) After all device drivers have loaded, the Protocol Manager determines from the information supplied on previous RegisterModule requests that NetBIOS must bind to ETHERCARD. Using a defined dispatch address in the characteristics table for NetBIOS, the Protocol Manager calls NetBIOS and instructs it to bind to ETHERCARD. The call, InitiateBind, includes the characteristics table for ETHERCARD.
 * 7) NetBIOS calls ETHERCARD requesting to bind. The modules exchange characteristics tables with each other. They now have each other's entry points and are bound.
 * 8) NetBIOS may now call ETHERCARD at its defined entry points for transmitting and receiving packets.

If the example NetBIOS driver was dynamically loadable, the binding to the ETHERCARD MAC would be done through the Protocol Manager's VECTOR facility (see Chapter 7). The VECTOR shields the static MAC driver from the details of dynamic binding.

Chapter 3 - Protocol to MAC Interface Description
The interface between a protocol and MAC driver provides for the transmission and reception of network packets, called frames. The interface includes other functions for controlling and determining the status of the network adapter controlled by the MAC.

To allow for efficient use of memory and to minimize buffer copies, frames being transmitted and received are passed between protocol and MAC using a scatter/gather buffer description convention. This passes an array of pointers/lengths called a frame buffer descriptor. There are three types of these descriptors, one for describing frames being transmitted (TxBufDescr) and two for frames being received (RxBufDescr and TDBufDescr).

Overall, the calls at the protocol/MAC interface are grouped into categories of transmission, reception, indication control, status indications, and general requests. An additional category of function, system requests, is generic to all drivers.

Transmission
Transmitting data can work either synchronously or asynchronously, at the option of the MAC. Protocols must be able to handle both cases. Primitives are TransmitChain and TransmitConfirm. Protocol     MAC TransmitChain ---CALL---> Call passes TxBufDescr and unique handle. MAC can copy data now or later <---RETURN--- Return indicates if data has been copied. If not, MAC now owns frame data blocks and will copy them asynchronously.

Later on, after data is copied by MAC: TransmitConfirm <---CALL---

Call supplies unique handle from TransmitChain. ---RETURN---> Data block ownership returned to protocol.

NOTE: If the MAC transmits the frame synchronously, it indicates this on the return from TransmitChain and will not generate a TransmitConfirm.

Reception
Receiving data can work in either of two ways, depending on the MAC. Protocols must be able to handle both cases:
 * The MAC generates a ReceiveLookahead indication that points to part or all of the received frame in contiguous storage. This is called the "lookahead" data. The protocol may issue a TransferData call back to the MAC if it wants the MAC to copy all or part of the received frame to protocol storage. The protocol can, of course, copy the lookahead data itself. In some implementations, this can be the entire frame.
 * The MAC generates a ReceiveChain indication that points to a RxBufDescr that describes the entire frame received. The protocol can copy the data immediately or later. If later, it releases the frame buffer areas back to the MAC via a call to ReceiveRelease.

Generally, the first approach will be implemented by MAC drivers for non-host-buffered network adapters, while drivers for host-buffered network adapters will implement the second. Non-host-buffered adapters that use programmed I/O or DMA will generally provide a small leading portion of the received frame as lookahead data, whereas those that use a single memory mapped buffer will usually provide the whole frame.

In either case, the protocol must validate the received packet very rapidly (within a few instructions) and reject it if necessary. This is very important to performance in a multiprotocol environment.

The following sections illustrate the non-host-buffered adapter versus host-buffered adapter receive scenarios.

Indication Control
Two primitives let a protocol selectively control when it can be called with indications from the MAC. These primitives are IndicationOn and IndicationOff.

Before calling an indication routine, the MAC implicitly disables indications. This means, for example, that if another frame arrives while the protocol is processing the indication for the previous one, the protocol will not be reentered. Likewise, if the protocol issues a TransmitChain for loopback data from within the ReceiveLookahead indication routine, it will not be reentered to process the loopback data reception.

Protocols can reenable indications upon returning from ReceiveLookahead, ReceiveChain, or Status indications or by calling IndicationOn within the IndicationComplete routine.

Status Indication
Status indications are calls from a MAC to protocol that convey a change in adapter or network status.

A status indication works much like a reception indication. The status indication handler is catered with indications disabled, and there is a mechanism that will leave indications disabled.

General Requests
General requests are calls from a protocol to a MAC, asking it to do a general function such as open or close the network adapter or change the station address.

General requests work much like a TransmitChain request, except the primitives are Request and RequestConfirm.

MAC Protocol

Request

---CALL--->

Issue request to MAC with unique handle.

<---RETURN---

Return indicates if request completed.

Later, if request completed asynchronously:

<---CALL---

RequestConfirm. The call supplies unique handle from Request.

---RETURN--->

If the MAC satisfies the request synchronously, it indicates this on the return from Request and will not generate a RequestConfirm.

System Requests
System requests support module binding and management functions. They are usually made by the Protocol Manager to a MAC or protocol module, but can also be made by a protocol to another protocol or MAC module.

System requests work much like general requests except that all are synchronous and the requests are not module specific.

Protocol Manager Primitives
Protocol Manager primitives are requests from protocol or MAC modules to the Protocol Manager for venous Protocol Manager services. These requests are always synchronous.

Module Characteristics
Protocol and MAC modules are described by a data structure called a characteristics table. Each characteristics table consists of several sections: a master section called the common characteristics table, and four subtables. The common characteristics table contains module independent information, including a dispatch address for issuing system commands like InitiateBind to the module. The four module- specific subtables are chained off the common characteristics table. These subtables define module- specific parameters and the entry points used for inter- module communication (such as the MAC/protocol interface functions). When two modules bind together, they exchange pointers to their common characteristics tables, so that each gets access to the other's descriptive information and entry points.

NOTE: NDIS drivers must copy the module DS and entry point addresses (from the common characteristics and upper/lower dispatch tables) to their local data segment at bind time. In future versions of this specification, this information may be volatile. Having this information directly accessible will also improve performance. This information must not be copied prior to the bind call and must not be used unless the bind completes successfully.

NOTE: The information in the characteristics table for a module is primarily informational, in support of network management and configuration tools. Upper modules binding to lower ones will NOT need to parse this information to adapt their behavior at the interface. They will generally just use the information to validate that they have been bound to the correct type of module. Most of the other information is provided in the structure to support information utilities.

Some new fields have been added to some of the characteristics tables for version 2.0.1. The size/length fields at the start of the tables can be checked to see if the new fields are available in the table.

Common Characteristics
The format of this information is identical for all modules. Note that all information in this section of the table is static.

In version 1.0.1, the two bytes after the first WORD were required to be set to zero. For compatibility with version 1.0.1, an NDIS spec major version number of 00 is interpreted the same as major version number 01.

The module function flags bitmask must accurately specify the capabilities of the module. The Protocol Manager uses these fields; for example, the dynamically bound (bit 2) flag when set indicates that this module is a dynamically loadable and unloadable module. Such a module can only be used in the Protocol Manager dynamic mode.

The upper and lower boundary protocol level and interface type bytes must accurately specify the protocol level and interface type. The Protocol Manager uses these fields. If an interface does not support NDIS bindings or a protocol level is undefined at the interface, a value at 0xFF must be used. In this case the corresponding interface type is undefined.

In addition to the preceding common characteristics table, a given module will typically have a set of subtables that are chained off the common table: This table contains descriptive information and parameters about the module. This table contains run-time operating status and statistics for the module. This table contains dispatch addresses for the upper boundary of the module - that is, the entry points it exports as a service provider. This table contains dispatch addresses for the lower boundary of the module - that is, the entry points it exports as a service client.
 * Service-specific characteristics table:
 * Service-specific status table:
 * Upper dispatch table:
 * Lower dispatch table:

NOTE: Under OS/2, dispatch addresses and data segments are Ring 0 selectors. This field is usually set at Ring 3 INIT time even though the selector set must be Ring 0.

MAC Service-Specific Characteristics
All MACs use the following format for the service-specific characteristics table. This table contains volatile information (like the current station address) that can be updated by the MAC during the course of operation. Other modules may read this table directly during execution. The remaining bytes in the table (based on length) are vendor specific.

In interpreting these tables, the implementor must always bear in mind that additional functions may be added to future MACs and that the support of functions that the protocol does not need must not prevent the protocol from accepting a bind for the MAC.

The type name describes to the protocol the type of MAC protocol header that the MAC driver supports. In general, protocol stacks must be prepared to support the types "802.3," "802.5", "DIX," and "DIX+802.3." If the native media of the MAC is not one of these types (for example, ARCNET), then it is recommended that the MAC developer consider claiming support for one of the above types and doing a transparent internal mapping between the private header format of the media and the public header format being claimed. Without support for one of the above header formats, general protocol compatibility cannot be guaranteed. The list specified above is not exhaustive. New names may be added in the future or a vendor may provide special MAC type names for use with protocols that interoperate with special MACs provided by that vendor. In the latter case it is recommended that a vendor use a MAC type name that does not start with an alphanumeric character to avoid conflicts with NDIS MAC type names that might be used in future versions of this specification.

In the various parts of this specification, all station and multicast addresses for a given MAC have the length specified in the "Length of station addresses" field.

The permanent station address must be obtained from the hardware if at all possible, as it may be used by LAN Manager for security or administrative purposes. If a PROTOCOL.INI entry is used to override the current station address, the permanent station address must not be affected. Only if there is no hardware-based addressing scheme will it be possible to override the permanent station address by configuration parameters. The current station address will always reflect the currant address as set via parameter or by calling Request SetStationAddress.

The functional address DWORD represents the functional address bit pattern present in the last four bytes of an IBM-compatible functional address. This excludes the first two bytes, 0xC0 and 0x00. The functional address DWORD represents the logical OR of all functional addresses currently registered to the adapters.

The multicast address list is a buffer formatted as follows: The multicast address list is kept packed by the MAC so that the current multicast addresses occur first in the list.

Service flags indicate which optional functions are supported by an NDIS driver. If a particular function bit is set, that function is supported. When attempts are made to invoke unsupported functions, NDIS MAC drivers must respond properly by returning INVALID_FUNCTION (0x0008).

If loopback is supported in the network adapter hardware, then bit 7 of the MAC service flags must be set.

If loopback is not supported in the hardware (bit 7 of the MAC service flags is not set), the protocol driver must handle this function itself by some loopback delivery of the frame to be transmitted.

The following criteria must be met for loopback: The loopback mechanism must cause the Receive indication to occur at interrupt time (and it must be delayed by IndicationOff.
 * The destination address is the same as the local station's current station address or the destination is a broadcast, multicast, or functional address that would have been received by this station if sent by another.
 * The frame must qualify for reception according to the current packet filter.

If IBM source routing is used (bit 9 is set), it is the protocol module's responsibility to encode and interpret appropriate source routing information. This bit merely implies that the device is capable of sending packets with the source routing bit set in the source address so that a protocol can recognize such a packet.

While the ResetMAC function (bit 10) is optional, it is strongly recommended that those implementing the NDIS MAC driver support this function. Some protocol drivers may rely on this function to recover from hardware error conditions.

If the service flags indicate that OpenAdapter is supported (bit 11 is set), then the protocol driver must ensure that the adapter is open. The open status of an adapter can be determined by examining bit 4 of the MAC status in the MAC service-specific status table. If the adapter is not open, then the protocol must issue an OpenAdapter Request (normally during bind-time processing).

If source routing bridge is set (bit 13), it is implied that the MAC is capable of receiving all packets on the network that have the source routing bit set.

If GDT virtual addresses are supported (bit 14 is set), then Ring 0 GDT virtual addresses can be used to describe frames. All MACs must support the use of physical addresses to describe frames; however, for some MACs it is preferable to supply a GDT address if one is readily available. The GDT address must remain valid throughout the scope of its use by the MAC.

If bit 16 of the service flags field is set, the MAC driver does not normally provide the total frame size of received data. In this case the MAC normally calls ReceiveLookahead with the FrameSize parameter equal to zero. Setting this bit is optional. It is left to the MAC implementor to determine how frequency returning FrameSize equals zero constitutes sufficient grounds to set this bit. However, this bit must be reset if the MAC always calls ReceiveLookahead with the FrameSize parameter nonzero or if a zero FrameSize parameter is returned only for intermittent erroneous packet reception. For version 1.0.1 compatibility, bit 16 reset gives no indication whether the MAC will return a zero FrameSize parameter or not. Some MAC and higher layer protocols do not support "length" fields within Their encoding. Such protocols rely on knowing the size of valid frame data received at the MAC interface and then deduce the amount of data at their layer by stripping off the lower layer protocol headers. This bit warns such protocols that the required received frame size is not normally available at the MAC interface and that receive frames might not be able to be processed. Such protocol scan refuse to bind to such MACs.

The maximum frame size must reflect the maximum size packet chat can be both transmitted and received by the MAC client. This size must reflect only the bytes chat actually cross the NDIS boundary. For EtherNet, this value is typically 1514, since the client does not specify the CRC bytes. Token-Ring values vary but do not include The nondata SD, ED, and FS bytes or the FCS.

The network adapter RAM is characterized by four parameters. The first is the number of bytes available for storing packets to be transmitted, usually one or two full-size packets in size. The second parameter is the allocation granularity, typically about 256 bytes, indicating how much memory would be occupied by a one-byte packet pending transmission. The third and fourth parameters are the number of bytes available for storing received packets and the receive packet granularity. Often These parameters will be affected by PROTOCOL.INI keywords (for example, specifying two transmit buffers rather than one), and it is required that These numbers accurately reflect the current adapter configuration. Protocol drivers may use these numbers to determine reasonable window sizes, and incorrect values can impact performance.

The intent of the IEEE vendor and vendor adapter codes is that, when used in combination, they uniquely identify this MAC driver for this adapter. The IEEE vendor code uniquely defines the vendor providing the MAC driver. The use of the if vendor code avoids the need for any global registry of vendor adapter codes. The IEEE vendor code is assigned by the IEEE and becomes the first three bytes of a six-byte IEEE 802 address. The vendor adapter code specifies a particular MAC driver provided by the vendor for an adapter. If the IEEE vendor code is assigned to the vendor, the vendor assigns a unique vendor adapter code to each MAC driver provided. For those without an IEEE vendor code, a value of 0xFFFFFF is required. In this case, the vendor adapter code is undefined.

The vendor adapter description string is an ASCIIZ string containing a description of the adapter that could be used to format an error message (for example, "3Com EtherLink II adapter").

The transmit queue depth specifies the maximum number of TransmitChain requests the MAC can buffer internally. This number must be set to one if the TransmitChain implementation in the MAC is synchronous. Each queued TransmitChain request requires that the MAC driver copy at least the chain descriptor and immediate data, so this parameter is generally configurable through a PROTOCOL.INI keyword called MAXTRANSMITS. The protocol driver can use this queue depth to compute the amount of time a transmit might be queued up within the MAC.

The maximum number of data buffer blocks is the maximum number of blocks supported in Transmit, TransferData, and ReceiveChain buffer descriptors. For version 1.0.1 backward compatibility this must be a minimum of eight. For version 1.0.1 - compatible MACs for which this field is absent, the maximum number assumed is eight.

The size of the NDIS defined part of the MAC specific characteristics table may increase in subsequent versions of the specification. If vendor specific information follows the NDIS defined information, a protocol using it must check the NDIS spec version number in the common characteristics table to determine where the NDIS specified information ends and the vendor specified information begins.

MAC Service-Specific Status Table
The MAC service-specific status and media-specific statistics tables provide information about the status of and traffic through a MAC. Since these tables can be updated by the MAC driver at interrupt time, a protocol must ensure that these tables are read with interrupts disabled. The MAC must update this table (and the media-specific statistics table if present) atomically.

Statistics for MACs Remaining bytes (based on length) in the table are vendor specific.

All statistics counters are 32-bit unsigned integers that wrap to zero when the maximum count is reached, after which the counters will continue to count. When updating these counters, a frame is counted in all the supported counters that apply. The case of an unsupported counter (0xFFFFFFFF) can be distinguished from the situation whereby a county is about to wrap around if the values of the counters are checked at bind times. If the initial value of the counter is 0xFFFFFFFF, then the counter is not supported. Otherwise the counter is supported and 0xFFFFFFFF at a later time means the counter is about to wrap around.

Service-Specific Statistics Definitions
Total frames received OK (NumberOfFramesReceivedOK)- corresponding 802.3 statistics

Total frames with CRC error (NumberOfFramesReceivedWithFrameCheckSequenceErrors)

Total bytes received

Total frames discarded - no buffer space

Total multicast frames received OK (NumberOfMulticastFramesReceivedOK)

Total broadcast frames received OK (NumberOfBroadcastFramesReceivedOK)

Total frames discarded - hardware error

Total frames transmitted OK (NumberOfFramesTransmittedOK)

Total bytes transmitted OK

Total multicast frames transmitted (NumberOfMulticastFramesTransmittedOK)

Total broadcast frames transmitted (NumberOfBroadcastFramesTransmittedOK)

Total broadcast bytes transmitted

Total frames not transmitted - time-out

Total frames not transmitted - hardware error

MAC Upper Dispatch Table
The number and meaning of dispatch addresses provided here apply to the boundary between a MAC and a protocol. This may differ at other protocol boundaries. Note that each upper/lower module binding may have its own unique set of dispatch addresses that is set up when the modules exchange characteristics tables. This can be achieved by exchanging copies of the common characteristics table, where the copy has the desired pointers to the specific dispatch tables for the binding. NOTE: No dispatch address is allowed to be NULL.

Protocol Service-Specific Characteristics Table
For compatibility with future versions of this specification, all protocols must provide a protocol service-specific characteristics table that starts with the following fields:

This can be followed by protocol-specific information.

The protocol type name will be used in future versions of this specification. Specific type names for different protocol types will be defined later. Protocol type codes will also be defined later. For now, these two fields are simple placeholders and must be set to null string and zero, respectively.

Protocol Lower Dispatch Table
The protocol lower dispatch table is specified in the characteristics table for the protocol binding to the MAC. The characteristics table for the MAC actually does not supply a lower dispatch table (the pointer to it is NULL). NOTE: No dispatch address is allowed to be NULL.

Characteristics Tables for NetBIOS Drivers
NetBIOS drivers written to the existing LAN Manager Ring 0 NetBIOS specification can be adapted to fit into the Protocol Manager structure by defining a common characteristics table for them. Note that such a NetBIOS driver must still respond to the existing LAN Manager NetBIOS linkage binding mechanism; these drivers will only use Protocol Manager binding at their lower boundary (to the MAC). A variant kind of NetBIOS module will be defined in the future that takes advantage of Protocol Manager binding at both boundaries.

Common characteristics for NetBIOS drivers: Upper dispatch table for a NetBIOS module:

Lower dispatch table for a NetBIOS module:

Service-specific characteristics for a NetBIOS module: This can be followed by module-specific information.

The protocol type name will be used in future versions of this specification. Specific type names for different protocol types will be defined later. Protocol type codes will also be defined later. For now, these two fields are simple placeholders and must be set to null string and zero, respectively.

Frame Data Description
The MAC describes frame data with a data structure called a buffer descriptor. The descriptor is composed of pointers and lengths that describe a logical frame. Buffer descriptors are ephemeral objects. A descriptor is valid only during the scope of the call that references it as a parameter. The called routine must not modify the descriptor in any way. If the called routine needs to refer to the described data blocks after returning from the call, it must save the information contained in the descriptor.

Data blocks described by descriptors are long-lived. Ownership of the data blocks is implicitly passed to the module that is called with the descriptor. The called module relinquishes ownership back to the caller either via setting a return argument or by later issuing a call back to the supplying module. Under OS/2, some pointers may be either GDT virtual addresses or physical addresses. In this case, the pointer has an associated pointer type opcoded field. Defined values are zero for physical addresses and two for GDT virtual addresses. GDT virtual addresses can be supplied to the MAC only if bit 14 of the service flags in the MAC service-specific characteristics table is set. The GDT address must remain valid throughout the scope of its use by the MAC.

Under DOS, there is no distinction between physical and virtual addresses. All addresses in this case are segment:offset. Care must be taken to ensure that the segment offset plus data length do not exceed the 64K segment boundary. The pointer type field, if present, is always encoded as a zero.

For performance reasons, it is recommended that data blocks used for transmission and reception be double-word aligned where possible. Both MAC and protocol NDIS drivers may choose to perform byte, word, or dword memory movement without first ensuring proper alignment. This will result in reduced performance in combination with drivers that do not guarantee such alignment.

A buffer descriptor can contain one or more data blocks of length zero. In this case, the other fields in the data block (Data Ptr and Data Type) may not be valid and must be ignored.

Transmit Buffer Descriptor
All transmit data is passed using a far pointer to a transmit buffer descriptor, TxBufDescr. The format of transmit buffer descriptors is

Followed by TxDataCount instances of In a TxBufDescr structure, the immediate data described by the first two fields is ephemeral and may be referenced only during the scope of the call that supplies it. Such immediate data is always transmitted before data described by TxDataLen and TxDataPtr pairs. If the called routine needs to refer to the immediate data after returning from the call, it must copy the data. The maximum size of immediate data is 64 bytes. For version 7.0.1 MACs or later, the maximum TxDataCount is specified in the MAC specific characteristics table. For version 1.0.1 MACs, the maximum count is eight.

Transfer Data Buffer Descriptor
Transfer data can be described by a far pointer to a transfer data buffer descriptor, TDBufDescr. The format of transfer data buffer descriptors is

Followed by TDDataCount instances of

For version 2.0.1 MACs or later, the maximum TDDataCount is specified in the MAC specific characteristics table. For version 1.0.1 MACs, the maximum count is eight.

Receive Chain Buffer Descriptor
Receive chain data can be passed by a far pointer to a receive chain buffer descriptor,

RxBufDescr. The format of receive chain buffer descriptors is

Followed by RxDataCount instances of

For version 2.0.1 MACs or later, the maximum receive data block count is specified in the MAC specific characteristics table. For version 1.0.1 MACs, the maximum count is eight.

For received frames that are larger than 256 bytes, the first data block of the frame must be at least 256 bytes long. Frames less than or equal to 256 bytes will be passed up with RxDataCount equal to one.

PROTOCOL.INI
The PROTOCOL.INI file stores configuration and binding information for all the protocol and MAC modules in the system. The file uses the same general format as the LANMAN.INI file. It consists of a series of named sections, where the section name is in fact the module name from a module characteristics table. Below the bracketed module name is a set of configuration settings for the module in name = value format. For example: [MYNetBIOS] Drivername = NetBIOS$ Bindings = ETHERCARD MaxNCBs = 16 MaxSessions = 32 MaxNames = 16 The rules for PROTOCOL.INI contents are The Protocol Manager supports an optional section with optional keywords defined as follows: [PROTMAN] Drivername = PROTMAN$ Dynamic = YES or NO PRIORITY = prot1, prot2, ... Bindstatus = YES or NO The bracketed module name can be any valid name as long as it is unique within this PROTOCOL.INI. Drivername is required and must be assigned PROTMAN$, identifying the section as belonging to the Protocol Manager. None of the entries are case sensitive.
 * Bracketed module name. This must be the name of a protocol or MAC module, for example, [MYNetBIOS]. This is the name of the module as defined in that module's characteristics table. The name must be 15 characters or less (not counting the brackets). Mixed case can be used, but the Protocol Manager will convert it to uppercase when it reads the file into memory.
 * Drivername = . This parameter is required for all device driver modules. It defines the name of the OS/2 or DOS device driver that the module is contained in. Note that a single device driver name can be mentioned by several sections of the PROTOCOL.INI file, if the driver contains multiple logical modules. The drivername parameter is the recommended method by which a module searches for its module section in the PROTOCOL.INI file to get its configuration parameters. This allows the module to find all relevant module sections based on a single name intrinsic to the module and independent of the particular bracketed module name used in the PROTOCOL.INI file. This keyword is also required for DOS dynamic modules like TSRs or transient application modules. Although there is no driver name intrinsically assigned to such modules, it is required that a unique name be assigned to this keyword for such modules anyway. In this way, the same search mechanism used by device drivers can be used by dynamic DOS modules to find their relevant module sections in PROTOCOL.
 * Bindings = |, , ... This parameter is optional for protocol modules. It is not valid for MAC modules. If present, it is used by the protocol module to determine which MAC modules it will ask to bind to. (In other words, changing this parameter in the PROTOCOL.INI file can reconfigure a protocol to bind to a different MAC.) The bindings parameter can be omitted if the protocol driver software is preconfigured to bind to a particular MAC, or if the system will only contain one MAC and one static protocol module. In the latter case (only in static mode), the Protocol Manager by default will ask the one static protocol to bind to the one MAC.
 * Other keywords and parameters. Any other keyword = value statements are module specific. Keyword names must be 15 characters or less. They can be mixed case but are converted to uppercase when read by the Protocol Manager. Note that keyword names are unique within the scope of each section and can appear within the section In any order.
 * White space around the equal sign is not significant, nor is trailing white space on the line. Except for this leading and trailing white space, all other characters of the value string are taken verbatim.
 * A list of parameters can appear to the right of the equal sign. If there are no parameters, the equal sign can be optionally omitted. A parameter is terminated by a space, tab, comma, or semicolon. No parameters are interpreted by the Protocol Manager.
 * A parameter can either be up to a 31-bit signed numeric value or a string of any length.
 * A numeric parameter can be expressed either in decimal or hexadecimal format. All numeric parameters must start with the characters '0' through '9' or by a + or - followed by the '0' to '9' character. A hexadecimal parameter must start with '0x' or '0X' and use valid hexadecimal digits. A nonhexadecimal numeric parameter is treated as a decimal integer. A parameter not surrounded by quotes and starting with 0 to 9 or + or - followed by 0 to 9 will be assumed to be a numeric parameter.
 * A string is a parameter that either starts with a nonnumeric character or is surrounded with quotes ("...."). The string is preserved in the memory image as it appears in PROTOCOL.
 * A line starting with a semicolon in column one is a comment and is ignored. Blank lines are ignored too.
 * Lines can be as long as required. Continuation lines are not supported. Lines end with CR LF.
 * Tabs, formfeeds, and spaces are considered to be white space.

The dynamic keyword is optional. It defaults to NO if not present. If set to NO, the Protocol Manager operates only in the static mode and does not support dynamic protocol drivers. If set to YES, the Protocol Manager operates in the dynamic mode and supports both static and dynamic binding.

The PRIORITY keyword is optional. If absent, the VECTOR uses default demultiplexing priority if multiple protocol drivers are bound to the same MAC (see the "VECTOR Demultiplexing" section in Chapter 7). If present, the parameters on the right-hand side are presumed to be a list of protocol module names, highest priority first. The VECTOR prioritizes protocol drivers for demultiplexing (if necessary) according to their order in the list, and packets are offered first to the first protocol driver listed. Protocol drivers not listed are assigned default priority AFTER those listed. It is not necessary that a protocol driver ever bind for it to be listed here.

The bindstatus keyword is optional. If absent, the BindStatus command is not supported by the Protocol Manager. If set to YES, BindStatus is supported by the Protocol Manager. The default disable condition is a memory optimization feature primarily for DOS environments.

When syntax errors are detected in processing the PROTOCOL.INI commands, by convention, all NDIS drivers should
 * Display an error message detailing the exact syntax problem
 * Assume some non-fatal value for the parameter associated with the error and complete processing

Configuration Memory Image
When the Protocol Manager initializes, it reads PROTOCOL.INI and parses it into a memory image that it makes available to MAC and protocol modules via the GetProtocolManagerInfo call. The parsed image is formatted to make it easy for run-time modules to interpret. All information contained in PROTOCOL.INI is present in the memory image in the same order as in the file. (Comments and white space are of course not present in the image.) Note that in static mode the image is only available during device driver initialization time. In dynamic mode the image may additionally be created by a utility that then registers it with the Protocol Manager.

The structure definitions defined in the following section do not conform rigorously to C language syntax They provide a pseudo C-like language to define the data structures encoded in the configuration memory Image.

ConfigMemorylmage
The ConfigMemoryImage data structure defines the complete memory image for all logical devices read from the PROTOCOL.INI configuration file. It is a doubly linked list of ModuleConfig structures. Each ModuleConfig structure corresponds to one module. The ConfigMemoryImage structure is defined as follows:

struct ConfigMemoryImage {       struct ModuleConfig(l) Module(l); struct ModuleConfig(2) Module(2); . . .       struct ModuleConfig(N) Module(N); }; where

N = the number of modules encountered by the Protocol Manager when parsing the configuration file PROTOCOL.INI.

ModuleConfig
The ModuleConfig(i) structure defines the memory image for configuration parameters corresponding to one (bracketed name) module. The (i)th module specified in PROTOCOL.INI is defined as follows:

struct ModuleConfig(i) {       struct ModuleConfig(i+l) far *NextModule; struct ModuleConfig(i-1) far *PrevModule; unsigned char ModuleName [16]; struct KeywordEntry(l) KeywordEntry(l); struct KeywordEntry(2) KeywordEntry(2); . . .       struct KeywordEntry(N) KeywordEntry(N); }; where

N = the number of keyword entries encountered in the PROTOCOL.INI file for this module.

NextModule = a FAR pointer to the next module configuration structure. This is NULL if it is the structure for the last module. For OS/2 the selector is a Ring 3 selector. For DOS the pointer is a segment:offset pair.

PrevModule = a FAR pointer to the previous module configuration structure. This is NULL if it is the structure for the first module. For OS/2 the selector is a Ring 3 selector. For DOS the pointer is a segment:offset pair.

ModuleName = an array containing the characters of the module name (given in brackets in the configuration file). This is an ASCIIZ string consisting of a maximum of 15 nonnull uppercase characters.

Keyword Entry
For each keyword line in the configuration file for the module, a memory image structure is created specifying the keyword and the parameter values. The (j)th keyword encountered in the PROTOCOL.INI file for the module is defined as follows:

struct KeywordEntry(j) {       struct KeywordEntry(j+1) far *NextKeywordEntry; struct KeywordEntry(j-1) far *PrevKeywordEntry; unsigned char Keyword[16]; unsigned NumParams; struct Param(1) Param(1); struct Param(2) Param(2); . . .        struct Param(N) Param(N); }; where

N = the number of parameters entered with the keyword. If N= 0, the parameters are not present.

NextKeywordEntry = a FAR pointer to the next keyword entry structure in the memory image. This is NULL if it is the last keyword entry. For OS/9 the selector is a Ring 3 selector. For DOS the pointer is a segment:offset pair.

PrevKeywordEntry = a FAR pointer to the previous keyword entry structure in the memory image. This is NULL if it is the first keyword entry. For OS/2 the selector is a Ring 3 selector. For DOS the pointer is a segment:offset pair.

Keyword = the array containing the characters of the keyword found in the configuration file. This is an ASCIIZ string consisting of a maximum of 15 nonnull characters. Alphabetic characters will be uppercase in the memory image.

NumParams = the number (N) of parameters entered with the keyword for each parameter described by a param structure. The value is zero if no parameters were present.

Param(k) = the (k)th parameter structure to specify the value of one parameter in a list of parameters for a keyword. Param(k+1) follows Param(k) in sequence within the memory image. Each parameter is delimited by a length field for the parameter. It is assumed that a keyword's fields will be parsed sequentially.

Param
For the (k)th parameter defined in a parameter list for a specific keyword, the following structure defines its value and attributes:

struct Param(k) {       unsigned ParamType; unsigned ParamLen; union ParamValue {               long Numeric; unsigned char String[STRINGLEN]; }; }; where

STRINGLEN = the length of the ASCIIZ parameter string (including the terminating NULL) for string parameters.

ParamType = the type of parameter. The following types are supported: = 0 a signed integer supporting up to 31-bit values with the least significant byte first = 1 a string of characters

ParamLen = the length of the parameter value. The length could either be 4 for numeric parameters or STRINGLEN for string parameters, where STRINGLEN is the length of the string (including the terminating NULL).

Numeric = a 31-bit signed numeric value.

String = an ASCIIZ character string. The case of alphabetic characters in the string is preserved from that in PROTOCOL.INI.

The size of the Param(k) structure is thus ParamLen + 4.

BindingsList
For each module that registers with the Protocol Manager, a BindingsList structure may be given to the Protocol Manager specifying the set of modules that the given module wishes to bind to. The current module will require services from these other modules. This structure is defined as follows:

struct BindingsList {       unsigned NumBindings; struct Module {               char ModuleName[16];

} BoundDriver[NUMBINDINGS]; }; where

NUMBINDINGS = the number of modules that the specified module wants to be bound to it from below. In the static default binding mode of one static protocol and one MAC, a value of zero in this field means for the protocol that it will bind to the MAC. Otherwise, in the nondefault binding mode, a value of zero in this field means that the module has no lower bindings.

ModuleName = an ASCIIZ string specifying the logical name of a module that the current module wishes to have bound to it from below. The string can be a maximum of 15 nonnull characters. The Protocol Manager will convert all alphabetic characters to uppercase.

BoundDriver = an array of NUMBINDINGS module names specifying the list of modules to which the current module wants to be bound.

The order of the modules in the list is significant in that InitiateBind requests will be issued to the protocol module in this order.

Specification of Primitives
Implementors should obey the following general guidelines: For example, multibyte fields (802.3 length, for instance) may not be received in the byte order that is normally used by the CPU for storing multibyte parameters. For exact format of the MAC header, refer to the appropriate standards document (see Appendix B).
 * All primitives specified in this section can be called in protected mode in either interrupt or task context under OS/2. Since any primitive can be called in interrupt context, it is illegal to block during the execution of a primitive.
 * All routines must run (as much as possible) with interrupts enabled. Interrupt handlers must dismiss the interrupt at the 8259 as soon as possible.
 * An indication handler will nominally be entered with interrupts enabled. The handle may enable or disable interrupts if it chooses, and on return the MAC must assume that the interrupt state may have been changed.
 * Under DOS, indication handlers must assume they have only 200 bytes of stack space. If more stack space is needed, then the handler must supply a stack.
 * Confirmation and IndicationComplete handlers must be fully reentrant and are always entered with interrupts enabled. Under DOS, Confirmation and IndicationComplete handlers must assume they are entered on whichever stack the interrupt occurred on.
 * A confirmation handler may be entered with the confirmation for a request before the request has resumed.
 * It is recommended that a MAC release the internal resources associated with either TransmitChain or a request before calling the confirmation handler. This allows the protocol to submit a new TransmitChain or request from the confirmation handler. Failing to do so may have a significant impact on performance.
 * A protocol must assume whenever it gives control to a MAC that interrupts may be enabled by the MAC unless otherwise explicitly specified.
 * When passing a virtual address to one of these primitives under OS/2, the address must be a Ring 0 GOT address unless otherwise specified. The interrupt service routine portion of the MAC must handle the fact that this address may not be valid if an interrupt occurs in real mode.
 * All primitives have a set of specific error codes defined. In general, MACs and protocols must return these specific codes. However, it is acceptable to return GENERAL_FAILURE for any nonrecoverable failure. NDIS developers must be aware that new error codes may be added in the future and must design their code to allow for this.
 * If a particular entry point or function is not supported by an NDIS protocol or MAC driver, the entry point must still be exposed and an error (INVALID FUNCTION 0x0008) resumed if it is called. Crashing when an unsupported request is made is unacceptable.
 * Parameters are passed on the stack compatible with Microsoft C FAR Pascal calling conventions. On entry to any routine the called module must save the caller's DS before setting its DS from the dataseg parameter. At exit the caller's DS must be restored. Furthermore, the called module must follow standard Microsoft C conventions about saving "register variable" SI and DI registers if these are used. Modules that use the 80386 registers EDI, ESI, and EBP must preserve these registers also. The direction bit is assumed to be clear on entry and must be clear upon exit. These conventions apply for calls in both directions across the NDIS MAC interface.
 * Direct calls return in AX a return code specifying the status of function invocation. Those functions specified as using IOCTLs return this in the status field of the request block.
 * Before calling a module in OS/2, it is the caller's responsibility to ensure that it is currently executing in protected mode. If it is running in real mode it must do an OS/2 RealToProt DevHlp call before calling the inter- module interface function. Furthermore, in OS/2 the inter-module call can only be made at post-CONFIG.SYS INIT time since all selectors are Ring 0 selectors.
 * A MAC starts with packet reception disabled. A protocol must call SetPacketFilter to enable reception of packets.
 * It is recommended that the number of request commands that can be simultaneously queued by the MAC be configurable. The suggested keyword in the configuration file is MaxRequests. The recommended default is 6. The suggested range is 1 through 10.
 * The number of TransmitChain commands that can be simultaneously queued by the MAC must be configurable. The suggested keyword in the configuration file is MaxTransmits. The recommended default is 6. The suggested range is 1 through 50.
 * On a DIX or 802.3 network, packet buffers received may have been padded to the minimum packet size for short packets. It is the responsibility of the MAC client to examine the length field if present and strip off the padding.
 * For DIX or 802.3 networks, the MAC client can transmit a buffer with packet length smaller than the minimum. It is the responsibility of the MAC to provide the required padding bytes before transmission to the wire. The content of the padding bytes is undefined.
 * Protocol drivers conforming to this specification are expected to format and interpret MAC headers for the MAC driver types supported. Generally, protocols are expected to support 802.3, DIN and 802.5 MAC headers. It is recommended that MAC drivers for other media types consider claiming to be one of the above types and doing a transparent internal mapping between that and its own private MAC header format. In doing so, the MAC will be able to claim interoperability (assuming the appropriate testing is done) with most protocol drivers developed for LAN Manager.
 * In the absence of any such conversion, the MAC header is passed protocol-to-MAC or MAC-to-protocol in exactly the format in which it exists on the medium. The CRC and nondata fields are not passed across this boundary. Therefore, the EtherNet CRC and the Token-Ring SD, FCS, ED, and FS fields are not passed and will not be included in the packet length. The protocol must convert header fields found in the header buffer passed up to whichever format is required to conveniently store them in local memory.
 * For performance reasons, it is recommended that PhysToGDT be used whenever possible instead of PhysToVirt.
 * Commonly used parameters:

TransmitChain
Purpose: Initiate transmission of a frame. PUSHWORD  ProtID;Module  ;ID of protocol PUSHWORD  ReqHandle      ;Unique handle for this request or zero PUSHLPBUF TxBufDescr     ;Pointer to frame buffer descriptor PUSHWORD  MACDS          ;DS of called MAC module CALL TransmitChain

Returns:
 * 0x0000 SUCCESS
 * 0x0002 REQUEST_QUEUED
 * 0x0006 OUT_OF_RESOURCE
 * 0x0007 INVALID_PARAMETER
 * 0x0008 INVALID_FUNCTION
 * 0x000A HARDWARE_ERROR
 * 0x000B TRANSMIT_ERROR
 * 0x000C NO_SUCH_DESTINATION
 * 0x00FF GENERAL_FAILURE


 * TxBufDescr:Far pointer to the buffer descriptor for the frame.

Description:

This call asks the MAC to transmit data. The MAC can either copy the data described by TxBufDescr before resuming or queue the request for later (asynchronous) processing. The MAC indicates which option it is taking by setting the appropriate return code.

In the asynchronous case, ownership of the frame data blocks passes to the MAC until the transmission is complete; the protocol must not modify these areas until then. Ownership of the data blocks is resumed to the protocol when the MAC either returns a status code that implies completion of the original request or calls its TransmitConfirm entry with the ReqHandle from TransmitChain. If a request handle of zero is used and, therefore, TransmitConfirm is not called, then ownership must not be considered resumed until the protocol receives a message that implies the transmission has occurred (for example, receiving an ACK to the transmitted message).

Note that when doing asynchronous transmission the MAC must retain any needed information from TxBufDescr, since the pointer to that structure becomes invalid upon resuming from TransmitChain. Also, if the TxImmedLen of the descriptor is nonzero, the MAC must retain a copy of the immediate data at TxImmedPtr, since the immediate data area becomes invalid upon resuming from TransmitChain.

The MAC header must fit entirely in the immediate data, if present, or in the first nonimmediate element described in TxBufDescr if there is no immediate data.

A MAC must be prepared to handle a TransmitChain request at any time, including from within interrupt-time indication routines.

The return code REQUEST_QUEUED causes a TransmitConfirm to be called from the MAC back to the protocol if the ReqHandle on the TransmitChain call is not zero. All other return codes from TransmitChain imply that no TransmitConfirm will occur.

The TRANSMIT_ERROR and NO_SUCH_DESTINATION error codes are intended to allow a protocol to recreate the frame status byte on a Token-Ring network. Thus, NO_SUCH_DESTINATION implies that the address-recognized bits were not set (and therefore the frame was not copied), while TRANSMIT_ERROR merely means that the frame was not copied. Protocols that make use of source routing may need the NO_SUCH_DESTINATION error code to be completely conformant. Token-Ring MAC driver writers must make every attempt to return these error codes properly.

TransmitConfirm
Purpose: Imply the completion of transmitting a frame. PUSH WORD  ProtID    ;Module ID of protocol PUSH WORD  MACID     ;Module ID of MAC PUSH WORD  ReqHandle ;Unique handle from TransmitChain PUSH WORD  Status    ;Status of original TransmitChain PUSH WORD  ProtDS    ;DS of called protocol module CALL TransmitChain Returns:
 * 0x0000 SUCCESS
 * 0x0007
 * 0x00FF

Description:

This routine is called by a MAC to indicate completion of a previous TransmitChain. The purpose of this is to return ownership to the protocol of the transmitted data blocks.

The ProtID parameter must be the value passed by the protocol on the previous TransmitChain that identifies the requester.

The ReqHandle is the value passed by the protocol on the previous TransmitChain that identifies the original request.

TransmitConfirm does not necessarily imply that the packet has been transmitted, though it generally will have been (with the exception of some intelligent adapter implementations). If the packet has been transmitted, Status must indicate the final transmit status: For more details, see the preceding section, "TransmitChain."

ReceiveLookahead
Purpose: Indicate the arrival of a received frame and offer lookahead data. PUSH WORD  MACID      ;Module ID of MAC PUSH WORD  FrameSize  ;Total size of frame (zero if not known) PUSH WORD  BytesAvail ;Bytes of lookahead available in buffer PUSH LPBUF Buffer     ;Virtual address of lookahead data PUSH LPBYTE Indicate  ;Virtual address of indicate flag PUSH WORD  ProtDS     ;DS of called protocol module CALL ReceiveLookahead Returns:
 * 0x0000 SUCCESS
 * 0x0003 FRAME_NOT_RECOGNIZED
 * 0x0004 FRAME_REJECTED
 * 0x0005 FORWARD_FRAME
 * 0x0006 OUT_OF_RESOURCE
 * 0x0007 INVALID_PARAMETER
 * 0x00FF GENERAL_FAILURE

FrameSize Total size, in bytes, of the received frame. A value of zero indicates that the MAC does not know the total frame size at this time.

BytesAvail Number of bytes available in the lookahead buffer. This is guaranteed to be at least as large as the lookahead size established with the SetLookahead request. For frames that are smaller than the lookahead size, the lookahead buffer will contain the whole frame.

BufferVirtual address of contiguous lookahead buffer. The buffer contains the leading BytesAvail octets of the frame. This buffer is ephemeral; it is addressable to the protocol only during the scope of the receive call.

Indicate Virtual address of indication flag byte. This byte is set to 0xFF by the MAC prior to this call. If the protocol clears the byte to zero prior to resuming, then indications will be left disabled until IndicationOn is called from IndicationComplete.

Description:

This routine is called by a MAC to indicate reception of a frame and to offer frame lookahead data. The protocol is expected to inspect this information very rapidly to determine whether or not it wants to accept the frame. If it wants to accept the frame, it may call TransferData to ask the MAC to copy the frame data to a specified buffer described by a TDBufDescr. The protocol can indicate that it is rejecting or does not recognize the frame by returning an appropriate error code. Note that the FRAME_NOT_RECOGNIZED error has special significance to the VECTOR function. If the protocol is accepting the frame and if the lookahead buffer contains the whole frame, the protocol can simply copy the data itself before returning from receive. The protocol can determine that it has the whole frame if BytesAvail equals FrameSize, or if the lookahead information includes a protocol header with die frame length, and this matches BytesAvail.

It is strongly recommended that MACs provide a nonzero FrameSize whenever possible. Some protocols might not be able to process frames unless the frame size given by this parameter is known. A MAC can optionally indicate that it does not normally provide a nonzero frame size by setting bit 16 of the service flags in the MAC specific characteristics table.

The MAC implicitly disables indications (IndicationOff) before calling ReceiveLookahead. The indicate flag byte instructs the MAC on whether to reenable indications or leave Hem disabled on the return. If the protocol chooses to leave indications disabled, it can enable Them within IndicationComplete by calling IndicationOn.

The protocol must absolutely minimize its processing time within the ReceiveLookahead handler. This is necessary to let certain MACs reenable the hardware to avoid loss of incoming frames. Shortly after returning from ReceiveLookahead, the MAC will call die protocol back at its IndicationComplete entry point. The protocol can do any needed post-processing of the received frame at diet time. The MAC does not guarantee to provide one IndicationComplete call for each indication. It can choose to issue a single IndicationComplete for several indications that have occurred.

TransferData
Purpose: Transfer frame data from the MAC to a protocol. PUSH LPWORD  BytesCopied   ;Number of bytes copied PUSH WORD    FrameOffset   ;Starting offset in frame for transfer PUSH LPBUFTD BufDescr      ;Virtual address of transfer data description PUSH WORD    MACDS         ;DS of called MAC module CALL TransferData Returns:
 * 0x0000 SUCCESS
 * 0x0007 INVALID_PARAMETER
 * 0x0008 INVALID_FUNCTION
 * 0x00FF GENERAL_FAILURE


 * BytesCopied:Virtual address of buffer for returning the number of bytes copied during transfer data operation.
 * FrameOffset:Starting offset in received frame where data transfer must start. The value of FrameOffset must be less than or equal to the value of BytesAvail from the corresponding ReceiveLookahead.
 * TDBufDescr:Virtual address of transfer descriptor describing where to store the frame data.

Description:

A protocol calls this synchronous routine from within its ReceiveLookahead handler before return, to ask the MAC to transfer data for a received frame to protocol storage. The protocol can specify any starting frame offset and byte count for the transfer, so long as these don't exceed the frame's length. If bit 15 of the MAC service flags is set, multiple TransferDatas can be called during a single ReceiveLookahead indication. If this bit is reset, only one TransferData per ReceiveLookahead indication is permitted. In the latter case, subsequent calls within the same indication will return an error.

For MACs with bit 15 of the MAC service flags reset, a protocol intending to call TransferData must do so only if it has decided to accept the incoming packet. Since the MAC drive may be shared by multiple protocols, a protocol's failure to follow this restriction in this case jeopardizes other coexisting protocol drivers from receiving these packets. When a protocol is bound to a MAC with bit 15 set, this restriction does not apply as a mandatory requirement. However, it is still recommended in such cases for performance reasons that a protocol call TransferData only if it has decided to accept the incoming packet. A protocol module must set the lookahead size large enough to determine if the packet is intended for it by examining only the lookahead bytes presented by ReceiveLookahead.

It is recommended that the multiple TransferData feature with bit 15 set be implemented in MAC drivers whenever it is reasonable to do so with the adapter hardware.

IndicationComplete
Purpose: Allow the protocol to do post-processing on indications. PUSH WORD    MACID    ;Module ID of MAC PUSH WORD    ProtDS   ;DS of called protocol module CALL IndicationComplete Returns:
 * 0x0000 SUCCESS
 * 0x0007 INVALID_PARAMETER
 * 0x00FF GENERAL_FAILURE

Description:

A MAC calls this entry point to enable a protocol to do post-processing after an indication. The MAC will always generate an IndicationComplete subsequent to an indication regardless of the return code of the indication. Although still in interrupt context and

subject to the normal OS/2 guidelines for interrupt processing, the protocol is not under the severe time constraints of the indication. The MAC must minimize stack usage before calling this routine and, under DOS, must have swapped off of any special "interrupt" stack.

This routine is always entered with interrupts enabled and with the network adapter interrupt dismissed from the interrupt controller. Therefore, it may be reentered at the completion of another indication. Also no one-to-one correspondence is guaranteed between indications and IndicationComplete. A MAC may generate one IndicationComplete for several indications. A protocol may enforce a ones one correspondence by leaving indications disabled until the return from IndicationComplete.

If indications are explicitly disabled by a protocol on return from an indication, it is the protocol's responsibility to invoke IndicationOn as soon as possible during IndicationComplete

MAC developers must avoid simply serializing each indication with IndicationComplete, as this can negatively affect performance. The MAC must be designed to allow an indication to occur during IndicationComplete processing. Of course, if this occurs, another IndicationComplete call Will be necessary.

ReceiveChain
Purpose: Indicate reception of a frame in MAC-managed buffers. PUSH WORD  MACID      ;Module ID of MAC PUSH WORD  FrameSize  ;Total size of frame Bytes PUSH WORD  ReqHandle  ;Unique handle for this request PUSH LPBUF RxBufDescr ;Virtual address of receive descriptor PUSH LPBYTE Indicate  ;Virtual address of indicate flag PUSH WORD  ProtDS     ;DS of called protocol module CALL ReceiveChain Returns:
 * 0x0000 SUCCESS
 * 0x0001 WAIT_FOR_RELEASE
 * 0x0003 FRAME_NOT_RECOGNIZED
 * 0x0004 FRAME_REJECTED
 * 0x0005 FORWARD_FRAME
 * 0x0006 OUT_OF_RESOURCE
 * 0x0007 INVALID_PARAMETER
 * 0x00FF GENERAL_FAILURE


 * FrameSize:Total size of received frame, in bytes.
 * RxBufDescr:Virtual address of receive descriptor describing the received frame.
 * Indicate:Virtual address of indication flag byte. This byte is set to 0xFF by the MAC prior to this call. If the protocol clears the byte to zero prior to resuming, then indications will be left disabled until IndicationOn is called from IndicationComplete.

Description:

A MAC calls this routine to indicate the reception of a frame in MAC-managed storage. Ownership of this storage is implicitly passed to the protocol when this call is made. At its option, the protocol may copy the data right away and indicate this via the return code (in which case ownership reverts to the MAC); or the protocol may queue the request and copy the frame later (in which case it retains ownership of the frame's storage until it calls ReceiveRelease). Since the protocol may queue data received in this manner, it is possible that the MAC could run low on available frame buffers. The MAC may elect to call ReceiveLookahead instead of ReceiveChain while it is low on frame buffers. This allows the MAC to retain control of its remaining buffers until the protocol releases the buffers it is holding.

Note that for frames longer than 256 bytes, the MAC must guarantee that the first data block of the frame is at least 256 bytes long. Frames less than or equal to 256 bytes in length must be completely specified with a single data block. This allows the protocol to parse packet headers out of the first data block and greatly facilitates protocol processing efficiency.

Like ReceiveLookahead, a protocol's processing within ReceiveChain is time critical. At some point after return from ReceiveChain, the MAC will generate an IndicationComplete to allow post-processing of the indication.

The MAC implicitly disables indications (IndicationOff) before calling ReceiveChain. The indicate flag byte instructs the MAC on whether to reenable indications or leave them disabled on the return. If the protocol chooses to leave indications disabled, it can enable them within IndicationComplete by calling IndicationOn.

ReceiveRelease
Purpose: Return frame storage to the MAC that owns it. PUSH WORD  ReqHandle   ;Unique handle from ReceiveChain PUSH WORD  MACDS       ;DS of called MAC module CALL ReceiveRelease Returns:
 * 0x0000 SUCCESS
 * 0x0007 INVALID_PARAMETER
 * 0x0008 NOT_SUPPORTED
 * 0x00FF GENERAL_FAILURE

Description:

A protocol uses this call after it has copied frame data provided by a ReceiveChain call. ReceiveRelease returns ownership of the frame data blocks to the MAC.

IndicationOff
Purpose: Disable MAC indications. PUSH WORD  MACDS   ;DS of called MAC module CALL IndicationOff Returns:
 * 0x0000 SUCCESS
 * 0x0008 INVALID_FUNCTION
 * 0x00FF GENERAL_FAILURE

Description:

A protocol can use this call to prevent the generation of ReceiveLookahead, ReceiveChain, and Status indications from the MAC. This is similar in concept to disabling interrupts. When indications are off, a MAC must queue events that would cause it to generate indications to the protocol. A MAC implicitly disables indications just before calling the ReceiveLookahead, ReceiveChain, or Status indication entry point of a protocol.

The only legal use of IndicationOff is to bracket a call or calls to the MAC. For example, the following sequence is valid:
 * IndicationOff
 * TransmitChain
 * IndicationOn

In this situation the protocol must not block while indications are off and must call IndicationOn as soon as possible. The protocol must ensure that all calls to IndicationOff are paired with a corresponding call to IndicationOn. If the protocol issues an IndicationOff call from a timer tick handle, or from a ReceiveLookahead, ReceiveChain, or Status indication handler, it must issue the IndicationOn call before resuming.

Note that IndicationComplete may still occur even though indications are disabled. Disabling indications has no effect on a MAC's ability to call IndicationComplete.

This function always returns with interrupts disabled. It is the responsibility of the caller to reenable them.

IndicationOn
Purpose: Enable MAC indications.

Called from protocol to MAC: PUSH WORD  MACDS   ;DS of called MAC module CALL IndicationOn Returns:
 * 0x0000 SUCCESS
 * 0x0008 INVALID_FUNCTION
 * 0x00FF GENERAL_FAILURE

Description:

A protocol must use this call to reenable indications after having disabled them. Note that a MAC can optionally defer the actual reenabling of indications.

It is possible that IndicationOff and IndicationOn pairs will nest. Therefore, the MAC must maintain a reference count to enable it to determine when to actually reenable indications. The protocol must not assume that a call to IndicationOn will immediately enable indications.

IndicationOn may be called from an IndicationComplete handler after leaving indications disabled on return from an indication handler. IndicationOn may also be used, paired with IndicationOff, to bracket a call or calls to the MAC.

This function always returns with interrupts disabled. It is the responsibility of the caller to reenable them. No indications will be generated until after the call has returned.

General Requests
General requests are commands from a protocol to a MAC directing it to do adapter management operations like setting the station address, running diagnostics, and changing operating parameters or modes. A MAC may choose to implement any of the request functions synchronously or asynchronously. A MAC returns the REQUEST_QUEUED return code to inform the protocol that a given request will be processed asynchronously. When this is the case, the MAC will call back to the protocol's RequestConfirm entry point to indicate when processing of the request is complete. If a request handle of zero is used, then the RequestConfirm call is suppressed. It is the caller's responsibility to make certain that any data referenced by the request remains valid until the request is guaranteed to have completed. If a protocol makes a general MAC request when executing its InitiateBind startup function and the MAC returns REQUEST QUEUED, the protocol must wait for the corresponding RequestConfirm to be resumed before exiting from the InitiateBind function. Any other return code from a general request implies that no RequestConfirm will occur.

All general requests have the following common calling convention: PUSH WORD  ProtID    ; Module ID of protocol or zero PUSH WORD  ReqHandle ; Unique handle for this request or zero PUSH WORD  Param1    ; Request dependent word parameter or zero PUSH DWORD Param2    ; Request dependent dword parameter or zero PUSH WORD  Opcode    ; Opcode of request PUSH WORD  MACDS     ; DS of called MAC module CALL Request

InitiateDiagnostics
PUSH WORD  ProtID    ; Module ID of protocol PUSH WORD  ReqHandle ; Unique handle for this request or zero PUSH WORD  0         ; Pad parameter - must be zero PUSH DWORD 0         ; Pad parameter - must be zero PUSH WORD  1         ; Initiate diagnostics request PUSH WORD  MACDS     ; DS of called MAC module CALL Request
 * Purpose: Start run-time diagnostics.
 * Returns:
 * 0x0000 SUCCESS
 * 0x0002 REQUEST_QUEUED
 * 0x0006 OUT_OF_RESOURCE
 * 0x0007 INVALID_PARAMETER
 * 0x0008 INVALID_FUNCTION
 * 0x0009 NOT_SUPPORTED
 * 0x000A HARDWARE_ERROR
 * 0x00FF GENERAL_FAILURE

This function causes a MAC to run hardware diagnostics and update its status information in the MAC-specific status section of the characteristics table. A MAC must return an error if it does not support run-time diagnostics. While the diagnostics are in progress, the MAC must set the diagnostics in progress bit (bit 5) in the MAC status field in the MAC service-specific status table. If HARDWARE_ERROR is resumed, the protocol can examine the various fields in the service-specific status table for an indication as to the cause of the problem.
 * Description:

ReadErrorLog
PUSH WORD  ProtID    ; Module ID of protocol PUSH WORD  ReqHandle ; Unique handle for this request or zero PUSH WORD  LogLen    ; Length of log buffer PUSH LPBUF LogAddr   ; Buffer for returning log PUSH WORD  2         ; ReadErrorLog request PUSH WORD  MACDS     ; DS of called MAC module CALL Request
 * Purpose: Return the error log.
 * Returns:
 * 0x0000 SUCCESS
 * 0x0002 REQUEST_QUEUED
 * 0x0006 OUT_OF_RESOURCE
 * 0x0007 INVALID_PARAMETER
 * 0x0008 INVALID_FUNCTION
 * 0x0009 NOT_SUPPORTED
 * 0x00FF GENERAL_FAILURE

This command causes a read error log to be issued to the adapter. This command is implemented on the IBM Token-Ring adapter and possibly other adapters. The format of the information returned is adapter specific and not specified here.
 * Description:

SetStationAddress
Purpose: Set the network address of the station. PUSH WORD  ProtID     ; Module ID of protocol PUSH WORD  ReqHandle  ; Unique handle for this request or zero PUSH WORD  0          ; Pad parameter-must be zero PUSH LPBUF AdaptAddr  ; Buffer containing the adapter address PUSH WORD  3          ; SetStationAddress request PUSH WORD  MACDS      ; DS of called MAC module CALL Request


 * Returns:
 * 0x0000 SUCCESS
 * 0x0002 REQUEST_QUEUED
 * 0x0006 OUT_OF_RESOURCE
 * 0x0007 INVALID_PARAMETER
 * 0x0008 INVALID_FUNCTION
 * 0x0009 NOT_SUPPORTED
 * 0x00FF GENERAL_FAILURE

Description:

There is only a single station address. Each time it replaces the current station address in the MAC service- specific characteristics table and reconfigures the hardware to receive on that address if required. The station is initially configured with the address specified in the permanent station address field of the MAC service-specific characteristics table (which this call does not modify).

The adapter address buffer contains only the bytes of the address to be set. The length of the address must be equal to the length specified in the MAC service characteristics table.

If the hardware does not support a mechanism to modify its station address, the current station address buffer is not updated and this function returns INVALID_FUNCTION. In this case the MAC continues to use the permanent station address to recognize incoming directed packets.

If a MAC does not support the OpenAdapter and CloseAdapter commands (bit 11 of the MAC service flags is reset), then the SetStationAddress command can be issued by the protocol at any time. However, if the MAC supports the OpenAdapter and CloseAdapter commands (bit 11 of the MAC service flags is set), then this command is valid either during system initialization time or while the MAC is in a closed state. The protocol driver must issue an OpenAdapter call after issuing the SetStationAddress call for the SetStationAddress command to take effect.

OpenAdapter
PUSH WORD ProtID      ; Module ID of protocol PUSH WORD ReqHandle   ; Unique handle for this request or zero PUSH WORD OpenOptions ; Adapter-specific open options PUSH DWORD ExtendedRet ; Optional pointer to a DWORD extended return code ; (vendor specific or warning level) PUSH WORD 4           ; OpenAdapter request PUSH WORD MACDS       ; DS of called MAC module CALL Request
 * Purpose: Issue open request to the network adapter.
 * Returns:
 * 0x0000 SUCCESS
 * 0x0002 REQUEST_QUEUED
 * 0x0006 OUT_OF_RESOURCE
 * 0x0007 INVALID_PARAMETER
 * 0x0008 INVALID_FUNCTION
 * 0x0009 NOT_SUPPORTED
 * 0x0024 HARDWARE_FAILURE
 * 0x002A NETWORK_MAY_NOT_BE_CONNECTED
 * 0x00FF GENERAL_FAILURE

Optional vendor-specific information can be resumed through the ExtendedRet pointer. A caller supporting this would push a pointer to a DWORD. The DWORD would have been initialized to 0xFFFFFFFF (unsupported). If there is any extended return information, this value would be changed. A caller not supporting this would simply push a NULL (0) pointer. The OpenAdapter routine that supports this would verify that the ExtendedRet pointer is not NULL and then write the information. The OpenAdapter routine that does not support this would simply ignore the pointer.

The purpose of ExtendedRet is to provide warning messages on a SUCCESS return without requiring additional testing for those callers not supporting warnings, to provide additional information about GENERAL_FAILURE and HARDWARE_FAILURE, and to pass vendor specific codes on any return to provide for active functional experimentation and evolution without inconveniencing other vendors' components.

The purpose of the OpenAdapter function is to activate an adapter's network connection. This may involve making an electrical connection for some adapters, such as Token-Ring adapters. This also implies that a considerable delay may occur between submittal of this request and its confirmation. If the MAC indicates that OpenAdapter is supported (by setting bit 11 of the service flags in the MAC service-specific characteristics table), then the protocol driver must ensure that the adapter is open during bind-time processing. Since OpenAdapter can only be called when the adapter is closed, even in a VECTOR configuration, the protocol must first check if the adapter is already open by examining bit 4 of the MAC status in the MAC service specific status table.
 * Description:

While an adapter is closed, the following functions are guaranteed to operate: SetLookahead, SetPacketFilter, SetStationAddress, Interrupt, IndicationOff, IndicationOn.

Since this function is adapter specific, it is expected that any necessary parameters are either known a priori by the MAC or can be recovered from the PROTOCOL.INI file. The format of the information is highly adapter specific and left up to the implementor to define.

The OpenOptions parameter is adapter specific. For IBM Token-Ring and compatible adapters, these are defined in the IBM Token-Ring Technical Reference Manual.

CloseAdapter
PUSH WORD ProtID  Module ID of protocol PUSH WORD ReqHandle ; Unique handle for this request or zero PUSH WORD 0         ; Pad parameter- must be zero PUSH DWORD 0        ; Pad parameter- must be zero PUSH WORD 5         ; CloseAdapter request PUSH WORD MACDS     ; DS of called MAC module CALL Request
 * Purpose: Issue close request to the network adapter.


 * Returns:
 * 0x0000 SUCCESS
 * 0x0002 REQUEST_QUEUED
 * 0x0006 OUT_OF_RESOURCE
 * 0x0007 INVALID_PARAMETER
 * 0x0008 INVALID_FUNCTION
 * 0x0009 NOT_SUPPORTED
 * 0x00FF GENERAL_FAILURE

This function closes an adapter. This causes it to decouple itself from a network so that packets cannot be sent or received. CloseAdapter resets the functional or multicast addresses currently set.
 * Description:

Since this function is adapter specific, it is expected that any necessary parameters are either already known by the MAC or can be recovered from the PROTOCOL.INI file. The format of the information is highly adapter specific and left up to the implementor to define.

ResetMAC
Purpose: Reset the MAC software and adapter hardware. PUSH WORD ProtID    ; Module ID of protocol PUSH WORD ReqHandle ; Unique handle for this request or zero PUSH WORD 0         ; Pad parameter- must be zero PUSH DWORD 0        ; Pad parameter- must be zero PUSH WORD 6         ; ResetMAC request PUSH WORD MACDS     ; DS of called MAC module CALL Request


 * Returns:
 * 0x0000 SUCCESS
 * 0x0006 OUT_OF_RESOURCE
 * 0x0007 INVALID_PARAMETER
 * 0x0008 INVALID_FUNCTION
 * 0x0009 NOT_SUPPORTED
 * 0x0074 HARDWARE_FAILURE
 * 0x009A NETWORK_MAY_NOT_BE_CONNECTED
 * 0x00FF GENERAL_FAILURE

This function causes the MAC to issue a hardware reset to the network adapter. The MAC may discard without confirmation any pending requests and abort operations in progress. For compatibility with some current protocols that do not properly handle resets, it is suggested that the MAC complete pending requests, returning INVALID_FUNCTION on all confirmations that result. The MAC must preserve the current station address, lookahead length, packet filter, multicast address list, functional address, and indication on/off state.
 * Description:

For MACs that support the OpenAdapter function, the ResetMAC command leaves the adapter in the opened state if it was opened prior to the reset. The adapter open parameters that were in effect prior to the reset must be the same ones in effect after the reset.

When the reset is initiated, the MAC must generate a StartReset status indication back to the protocol. For some MACs a considerable delay can elapse between the start of the reset and its completion. All MACs must subsequently issue an EndReset indication when the reset is complete. During the time between the StartReset indication and the corresponding EndReset indication, the MAC must return INVALID_FUNCTION for any request it receives while a reset is in progress. The EndReset indication notifies the protocol that the MAC can handle new requests. As always, an IndicationComplete follows these indications. MACs written to version 1.0.1. of this spec will not issue the EndReset indication. They must issue an IndicationComplete to signal the end of the reset.

Note that the completion (the return from this command or the request confirm) of the ResetMAC request itself does not signal the start or end of the reset.

There can be no guarantee that this function will succeed, though the NDIS MAC developer must make every attempt. An error return from this call can be considered fatal. If the reset fails, the adapter may no longer be in the same state. For example, if the adapter was open before a failed ResetMAC, it may now be closed.

ResetMac must not be queued.

SetPacketFilter
Purpose: Select received packet general filtering parameters. PUSH WORD  ProtID     ; Module ID of protocol PUSH WORD  ReqHandle  ; Unique handle for this request or zero PUSH WORD  FilterMask ; Bitmask for packet filter PUSH DWORD 0          ; Pad parameter-must be zero PUSH WORD  7          ; SetPacketFilter request PUSH WORD  MACDS      ; DS of called MAC module CALL Request


 * Returns:
 * 0x0000 SUCCESS
 * 0x0002 REQUEST_QUEUED
 * 0x0006 OUT_OF_RESOURCE
 * 0x0007 INVALID_PARAMETER
 * 0x0008 INVALID_FUNCTION
 * 0x00FF GENERAL_FAILURE

FilterMask:Bit

This command tells the MAC which kinds of received packets must generate indications to the protocol invoking this command. A FilterMask of zero indicates that the MAC must not indicate received packets to that protocol. If a FilterMask bit is set, this indicates that the MAC must indicate that type of packet to the protocol. Except for a zero FilterMask a filter bit of zero does not require the MAC to suppress indications for that type of packet. For example, the FilterMask used by the MAC may or may not correspond to the capabilities of the hardware adapter. A MAC can be designed to receive multicast frames by promiscuously receiving all frames and discarding those that do not match the filter. It is optional for the MAC to support such software filtering. If the MAC can suppress such indications, it is strongly recommended that it do so. However, if the MAC does not suppress such indications, then the protocol must be prepared to receive these and discard the incoming packet if necessary.
 * Description:

If this request returns SUCCESS, then the hardware is enabled to receive the types of packets requested and will generate indications to the protocol for those types of packets.

If the MAC does not support the receiving of packets of the type specified, then it will return GENERAL_FAILURE. In this case the FilterMask is left in its previous state.

AddMulticastAddress
Purpose: Allow the adapter to respond to a multicast address. PUSH WORD  ProtID    ; Module ID of protocol PUSH WORD  ReqHandle ; Unique handle for this request or zero PUSH WORD  0         ; Pad parameter- must be zero PUSH LPBUF MultiAddr ; Buffer containing multicast address PUSH WORD  8         ; AddMulticastAddress request PUSH WORD  MACDS     ; DS of called MAC module CALL Request


 * Returns:
 * 0x0000 SUCCESS
 * 0x0002 REQUEST_QUEUED
 * 0x0006 OUT_OF_RESOURCE
 * 0x0007 INVALID_PARAMETER
 * 0x0008 INVALID_FUNCTION
 * 0x0009 NOT_SUPPORTED
 * 0x00FF GENERAL_FAILURE

This function allows the addition of multicast addresses. The term multicast address also implies 802.5 group addresses. This function allows the addition of only one address at a time but can be repeated to add more multicasts.
 * Description:

It is the MAC's responsibility to return an error if too many multicast addresses have been added (OUT_OF_RESOURCE or INVALID_FUNCTION) or if an address of the wrong type has been added (INVALID_PARAMETER).

Multicast addresses are never overwritten and return an error (INVALID_PARAMETER) if they already exist, no matter what Their type. They must be explicitly deleted.

The multicast address buffer contains only the bytes of the multicast address to be added. The length of the multicast address must be equal to the length specified in the MAC service characteristics table.

DeleteMulticastAddress
Purpose: Forbid the adapter to respond to a multicast address. PUSH WORD  ProtID    ; Module ID of protocol PUSH WORD  ReqHandle ; Unique handle for this request or zero PUSH WORD  0         ; Pad parameter- must be zero PUSH LPBUF MultiAddr ; Buffer containing multicast address PUSH WORD  9         ; DeleteMulticastAddress request PUSH WORD  MACDS     ; DS of called MAC module CALL Request


 * Returns:
 * 0x0000 SUCCESS
 * 0x0002 REQUEST_QUEUED
 * 0x0006 OUT_OF_RESOURCE
 * 0x0007 INVALID_PARAMETER
 * 0x0008 INVALID_FUNCTION
 * 0x0009 NOT_SUPPORTED
 * 0x00FF GENERAL_FAILURE

This function removes a previously added multicast address. The term multicast address also implies 802.5 group addresses. INVALID_PARAMETER is returned if the address is not in the table.
 * Description:

The multicast address buffer has the same format as in the AddMulticastAddress command.

UpdateStatistics
Purpose: Cause MAC statistics to be updated. PUSH WORD  ProtID    ; Module ID of protocol PUSH WORD  ReqHandle ; Unique handle for this request or zero PUSH WORD  0         ; Pad parameter - must be zero PUSH DWORD 0         ; Pad parameter - must be zero PUSH WORD  10        ; UpdateStatistics request PUSH WORD  MACDS     ; DS of called MAC module CALL Request


 * Returns:
 * 0x0000 SUCCESS
 * 0x0002 REQUEST_QUEUED
 * 0x0006 OUT_OF_RESOURCE
 * 0x0007 INVALID_PARAMETER
 * 0x0008 INVALID_FUNCTION
 * 0x00FF GENERAL_FAILURE

This function causes the MAC to atomically update the statistics in its characteristics table. The requester can then read the table when this operation is complete. Those statistics that are not always current will remain the same until the next UpdateStatistics call is performed. If all of the statistics in the table are always current, this function must return SUCCESS.
 * Description:

ClearStatistics
PUSH WORD  ProtID    ; Module ID of protocol PUSH WORD  ReqHandle ; Unique handle for this request or zero PUSH WORD  0         ; Pad parameter- must be zero PUSH DWORD 0         ; Pad parameter - must be zero PUSH WORD  11        ; ClearStatistics request PUSH WORD  MACDS     ; DS of called MAC module CALL Request
 * Purpose: Cause MAC statistics to be cleared.
 * Returns:
 * 0x0000 SUCCESS
 * 0x0002 REQUEST_QUEUED
 * 0x0006 OUT_OF_RESOURCE
 * 0x0007 INVALID_PARAMETER
 * 0x0008 INVALID_FUNCTION
 * 0x00FF GENERAL_FAILURE

This function causes the MAC to reset its statistics counters. This implies that all statistics must be reset to zero in an atomic operation.
 * Description:

InterruptRequest
Purpose: Request asynchronous indication. PUSH WORD  ProtID   ; Module ID of protocol PUSH WORD  0        ; Pad parameter - must be zero PUSH WORD  0        ; Pad parameter - must be zero PUSH DWORD 0        ; Pad parameter - must be zero PUSH WORD  12       ; InterruptRequest request PUSH WORD  MACDS    ; DS of called MAC module CALL Request
 * Returns:
 * 0x0000 SUCCESS
 * 0x0006 OUT_OF_RESOURCE
 * 0x0008 INVALID_FUNCTION
 * 0x0009 NOT_SUPPORTED
 * 0x00FF GENERAL_FAILURE

Description:

This function requests that the MAC generate an asynchronous interrupt status indication back to the protocol. The protocol may control the generation of this interrupt status indication by disabling and later enabling indications. The MAC may, at its discretion, suppress the generation of this indication if there is another indication pending that can be issued in place of the interrupt status indication. This request is intended to be used for MACs that can generate a hardware interrupt on demand. This function must be implemented if at all possible. InterruptRequest will substantially improve the performance of some protocols (particularly DLC).

SetFunctionalAddress
Purpose: Cause the adapter to change its functional address. PUSH WORD  ProtID    ; Module ID of protocol PUSH WORD  ReqHandle ; Unique handle for this request or zero PUSH WORD  0         ; Pad parameter- must be zero PUSH LPBUF FunctAddr ; Buffer containing functional address PUSH WORD  13        ; SetFunctionalAddress request PUSH WORD  MACDS     ; DS of called MAC module CALL Request
 * Returns:
 * 0x0000 SUCCESS
 * 0x0002 REQUEST_QUEUED
 * 0x0006 OUT_OF_RESOURCE
 * 0x0007 INVALID_PARAMETER
 * 0x0008 INVALID_FUNCTION
 * 0x0009 NOT_SUPPORTED
 * 0x00FF GENERAL_FAILURE

This function sets the IEEE 802.5 functional address to the passed functional address. The adapter will use the functional address to discern packets intended for it. For more information about functional addresses, see the IEEE 802.5 specification.
 * Description:

The functional address buffer contains only the bytes of the new functional address bit pattern. It represents the logical OR of all functional addresses to be registered with the adapter. The length of the functional address buffer is four bytes.

Multiple protocols can set or reset their functional address bit if required by each protocol by first reading the current functional address DWORD bit pattern from the MAC service characteristics table, then ORing in or ANDing out the required functional bit and passing the new functional address pattern in this command.

SetLookahead
Purpose: Set the length of lookahead information for ReceiveLookahead. PUSH WORD  ProtID    ; Module ID of protocol PUSH WORD  ReqHandle ; Unique handle for this request or zero PUSH WORD  Length    ; Minimum length of lookahead information PUSH DWORD 0         ; Pad parameter- must be zero PUSH WORD  14        ; SetLookahead request PUSH WORD  MACDS     ; DS of called MAC module CALL Request
 * Returns:
 * 0x0000 SUCCESS
 * 0x0002 REQUEST_QUEUED
 * 0x0007 INVALID_PARAMETER
 * 0x00FF GENERAL_FAILURE

This request sets the minimum length in bytes of lookahead information to be returned in a ReceiveLookahead indication. Until SetLookahead is initially called, a value of 64 bytes is assumed for the lookahead length. When first called, SetLookahead sets the lookahead length value equal to the length parameter of the request. After the first SetLookahead request, the lookahead length is changed only if the value of the length parameter is larger than the current lookahead length. If the length parameter value is smaller, the current lookahead length remains unchanged and SUCCESS is resumed. SetLookahead can be called at any time, and the lookahead length is preserved during a reset. The maximum value for the lookahead length is 256 bytes. MACs that never call ReceiveLookahead or always return lookahead information of length greater than or equal to 256 bytes can return SUCCESS without any internal action. MACs must support 256 bytes of lookahead data if requested.
 * Description:

General Request Confirmation
Purpose: Confirm the completion of a previous general request. PUSH WORD  ProtID    ; Module ID of protocol PUSH WORD  MACID     ; Module ID of MAC PUSH WORD  ReqHandle ; Unique handle for this request PUSH WORD  Status    ; Final status of original request PUSH WORD  Request   ; Original request opcode PUSH WORD  ProtDS    ; DS of called protocol module CALL RequestConfirm
 * Returns:
 * 0x0000 SUCCESS
 * 0x0006 OUT_OF_RESOURCE
 * 0x0007 INVALID_PARAMETER
 * 0x0024 HARDWARE_FAILURE
 * 0x00FF GENERAL_FAILURE

This function notifies a protocol that an asynchronous MAC control request has completed after the previous request had returned a REQUEST_QUEUED. It is possible that a RequestConfirm can be resumed to the protocol before the protocol's corresponding request function has completed.
 * Description:

The ProtID parameter must be the value passed by the protocol on the previous general request to identify the requester.

If a protocol had made a general MAC request when executing its InitiateBind startup function and the MAC resumed REQUEST_QUEUED, the protocol must wait for the corresponding RequestConfirm to be resumed before exiting from the InitiateBind function.

Status Indication
Status indications are spontaneous calls from a MAC to a protocol, typically at interrupt time. They inform the protocol of changes in MAC status.

All status indications have the following common calling convention:

Indicate is the virtue address of the indication flag byte. This byte is set to 0xFF by the MAC prior to this call. If the protocol clears the byte to zero prior to resuming, then indications will be left disabled until IndicationOn is called from IndicationComplete.

RingStatus
Purpose: Return a change in ring status.

Description:

This function is called by 802.5-style MAC drivers to indicate a change in ring status. The status codes for 802.5-style drivers are encoded as a 16-bit mask where the bits in the mask are defined as follows:

For certain ring status changes, the adapter may already have been removed from the ring. The protocol driver must check whether the adapter has been closed (by examining bit 4 of the MAC status field in the MAC service-specific status table). For additional information, see the IBM Token-Ring Technical Reference Manual. If the status condition caused the adapter to close, the MAC must return confirmations with non-SUCCESS status codes for all pending TransmitChain and general requests.

AdapterCheck
Purpose: Return hardware status.

Description:

This function is called to indicate a fatal adapter error. If this function is called, the protocol must issue a ResetMAC call (if supported) before communications can resume. Note that a MAC may choose to tolerate some number of errors before issuing an AdapterCheck indication. For example, a MAC may want to accept the occasional receive DMA overrun, and only issue the AdapterCheck for this condition if it occurs excessively.

For 802.5 MACs the Reason code is defined as follows (NOT a bitmask):

All 802.5 values not defined in the preceding list are reserved.

The MAC must always return confirmations with non-SUCCESS status codes for all pending TransmitChain and general requests.

For 802.3 MACs the reason code is defined as follows (NOT a bitmask):

All 802.3 values not defined in the preceding list are reserved.

StartReset
Purpose: Imply that the adapter has started a reset.

Description:

This function is called to indicate that the adapter has started a reset. This will generally be due to a call to ResetMAC (perhaps by another protocol driver in a VECTOR configuration) but can be unsolicited. The protocol must assume when it gets this indication that all requests outstanding to the MAC have been discarded without notification. The end of the reset will be signaled by an EndReset indication. The reset process may take a significant amount of time. While it is in progress, the MAC might reject any requests it cannot handle with INVALID_FUNCTION (0x0008 ). As with any other indication, StartReset is entered with indications implicitly disabled. To protect itself from other indications, the protocol may choose to modify the indicate flag to keep indications disabled on return. This will not prevent the EndReset indication from being generated, however StartReset is affected by IndicationOn and IndicationOff.

EndReset
Purpose: Imply that the adapter has finished a reset. PUSH WORD  MACID    ;Module ID of MAC PUSH WORD  Status   ;MAC error information PUSH LPBYTE Indicate ;Virtual address of indicate flag PUSH WORD  5        ;EndReset indication PUSH WORD  ProtDS   ;DS of called protocol module CALL Status Returns:
 * 0x0000 SUCCESS
 * 0x0008 INVALID_FUNCTION

Description:

This function is called to indicate that the adapter has finished a reset and follows the StartReset indication. The protocol may return INVALID_FUNCTION if it was written to version 1.0.1 of this specification, where it assumes end of reset on IndicationComplete. To ensure compatibility with version 1.0.1 protocol drivers, the MAC must ensure the IndicationComplete is called after EndReset and before any other indications.

EndReset will pass up a success/fail code for ResetMAC in the status parameter:
 * 0x0000 SUCCESS
 * 0x0024 HARDWARE_FAILURE
 * 0x002A NETWORK_MAY_NOT_BE_CONNECTED
 * 0x00FF GENERAL_FAILURE

As with any other indication, EndReset is entered with indications implicitly disabled. To protect itself from other indications, the protocol may choose to modify the indicate flag to keep indications disabled on return. MAC drivers must be prepared for the possibility that both StartReset and EndReset allow the protocol to modify this flag.

EndReset is NOT affected by IndicationOn/IndicationOff. In other words, if the protocol modifies the indicate flag during StartReset to disable indications, this will not prevent the EndReset indication from being generated.

If both StartReset and EndReset disable indications, the IndicationOff depth is two, requiring two calls to IndicationOn in order to enable indications. For example, if protocol A disables indications during StartReset and protocol B disables indications during EndReset, both protocols must issue IndicationOn before indications are reenabled. The same is true if the same protocol issues IndicationOff twice.

Interrupt
Purpose: Imply that an interrupt has occurred as the result of an interrupt request. PUSH WORD  MACID    ;Module ID of MAC PUSH WORD  0        ;Pad parameter - must be zero PUSH LPBYTE Indicate ;Virtual address of indicate flag PUSH WORD  4        ;Interrupt indication PUSH WORD  ProtDS   ;DS of called protocol module CALL Indication Returns:
 * 0x0000 SUCCESS

Description:

The MAC calls this function to indicate to a protocol that an interrupt requested by an interrupt request has occurred. Since this indication can be deferred by disabling indications, a protocol might use this mechanism to implement a simple scheduling schema to allow it to regain control once outside of a critical code region. The MAC may, at its discretion, suppress the generation of this indication if there is another indication pending that can be issued in place of the interrupt status indication.

System Requests
All MAC and protocol modules implement a set of system request functions that support module-independent functions such as binding. The caller of these functions is usually the Protocol Manager. The entry point for system requests is defined in the common characteristics table for the module. All system requests are implemented synchronously. Note that all pointers in system requests are Ring 0 GDT virtual addresses.

All system requests have the following common calling convention: PUSH DWORD  Param1   ;Request-dependent dword parameter or zero PUSH DWORD  Param2   ;Request-dependent dword parameter or zero PUSH WORD   Param3   ;Request-dependent word parameter or zero PUSH WORD   Opcode   ;Opcode of request PUSH WORD   TargetDS ;DS of called module CALL System

InitiateBind

Purpose: Instruct a module to bind to another module. PUSH DWORD   0        ;Pad parameter - must be zero PUSH LPBUF   CharTab  ;Characteristics of module to bind PUSH WORD    LastBind ;Nonzero if last InitiateBind PUSH WORD    1        ;InitiateBind request PUSH WORD    ProtDS   ;DS of called protocol module CALL System Returns:
 * 0x0000 SUCCESS
 * 0x0008 INVALID_FUNCTION
 * 0x0021 INCOMPLETE_BINDING
 * 0x0022 DRIVER_NOT_INITIALIZED
 * 0x0023 HARDWARE_NOT_FOUND
 * 0x0024 HARDWARE_FAILURE
 * 0x0025 CONFIGURATION_FAILURE
 * 0x0026 INTERRUPT_CONFLICT
 * 0x0027 INCOMPATIBLE_MAC
 * 0x0028 INITIALIZATION_FAILED
 * 0x002A NETWORK_MAY NOT_BE CONNECTED
 * 0x002B INCOMPATIBLE_OS_VERSION
 * 0x00FF GENERAL_FAILURE

Description:

This call is issued by the Protocol Manager to an upper protocol module. It passes the address of the characteristics table of the lower module that the upper module must issue a bind call to. If the upper module specified a BindingsList including more than one lower module, then InitiateBinds will be issued for those modules in the order the lower modules are listed in the BindingsList structure. LastBind is used to indicate the last InitiateBind request so that the module can perform any final initialization prior to returning. In the static default binding case of one static protocol and one MAC, the Protocol Manager will issue an InitiateBind, passing the characteristics table of the MAC even if no bindings list was specified. In this case LastBind will be nonzero. In the nondefault case, if a module other than a MAC does not have lower bindings (having a BindingsList with a NumBindings count = 0), the Protocol Manager will still issue an InitiateBind to the module to allow final initialization. In this case CharTab will be NULL and LastBind will be nonzero.

If the bind operation fails, then the InitiateBind operation must also fail, returning the same return code as the failing bind call.

If a module returns a non-SUCCESS code on InitiateBind, in the dynamic mode the Protocol Manager will automatically deregister that module and remove all reference to it in its bind tables. In particular, any other module that had registered (via RegisterModule) its intention to bind with the failed module will get an InitiateBind call with the CharTab pointer FAR NULL and LastBind nonzero. A module that has lower bindings and receives an InitiateBind with a NULL bind CharTab must generate a non-SUCCESS return code in order to force the Protocol Manager to deregister it. In DOS it is recommended that a dynamic module that failed its bind uninstall itself. In OS/2 it is recommended that the dynamic driver that failed its bind leave its dynamic segments unlocked.

Bind
Purpose: Exchange module characteristics table information. PUSH LPBUF  CharTab  ;Pointer to caller's table PUSH LPBUF  TabAddr  ;Address where to return a pointer characteristics PUSH WORD   0        ;Pad parameter- must be zero PUSH WORD   2        ;Bind request PUSH WORD   TargetDS ;DS of called module CALL System Returns:
 * 0x0000 SUCCESS
 * 0x0008 INVALID_FUNCTION
 * 0x0022 DRIVER_NOT_INITIALIZED
 * 0x0023 HARDWARE_NOT_FOUND
 * 0x0024 HARDWARE_FAILURE
 * 0x0025 CONFIGURATION_FAILURE
 * 0x0026 INTERRUPT_CONFLICT
 * 0x0027 INCOMPATIBLE_MAC
 * 0x0028 INITIALIZATION_FAILED
 * 0x002A NETWORK_MAY NOT BE_CONNECTED
 * 0x002B INCOMPATIBLE_OS_VERSION
 * 0x00FF GENERAL_FAILURE

Description:

This function is used by one module to bind to another. It exchanges pointers to characteristics tables between the two modules. A MAC will accept only one bind and will not accept additional bind attempts.

For compatibility with remote initial program load, MAC drivers must not manipulate the network adapter at INIT time. The MAC driver is free to determine if the network adapter is present, but must leave any hardware manipulation to bind time processing.

InitiatePrebind (OS/2 only)
Purpose: In OS/2 dynamic bind mode, instruct a module to restart its prebind initialization. PUSH DWORD  0      ;Pad parameter - must be zero PUSH LPBUF  0      ;Pad parameter - must be zero PUSH WORD   0      ;Pad parameter - must be zero PUSH WORD   3      ;Bind request PUSH WORD   ProtDS ;DS of called protocol module CALL System Returns:
 * 0x0000 SUCCESS
 * 0x00FF GENERAL_FAILURE

Description:

In the OS/2 dynamic mode, this call is issued by the Protocol Manager to a dynamically loadable protocol driver when the Protocol Manager InitAndRegister is called. This function is available for the protocol driver to restart its prebind initialization when it is dynamically reloaded.

An OS/2 dynamic protocol driver is assumed to be made up of static and transient segments. When the protocol is not needed, the transient segments are unlocked (using the DevHlp Unlock command) to allow them to be swapped out. When the protocol is needed again, InitiatePrebind is issued. During InitiatePrebind, the driver needs to lock down its dynamic segments (using the DevHlp Lock command, type 1) to force them back into memory and make them addressable again. The protocol must save the lock handle resumed by this call to use Unlock later. Also, the prebind initialization sequence is initiated in this call and consists of rereading the PROTOCOL.INI memory image, configuration initialization, prebind memory allocations, and registration with the Protocol Manager. The protocol module typically carries out here the same functions that are performed by a static protocol module when a strategy routine INIT command is given.

InitiateUnbind
Purpose: Instruct a module to unbind from another module. PUSH DWORD  0          ;Pad parameter - must be zero PUSH LPBUF  CharTab    ;Characteristics of module to unbind PUSH WORD   LastUnbind ;Nonzero if last InitiateUnbind PUSH WORD   4          ;InitiateUnbind request PUSH WORD   ProtDS     ;DS of called protocol module CALL System Returns:
 * 0x0000 SUCCESS
 * 0x00FF GENERAL_FAILURE

Description:

This call is issued by the Protocol Manager in dynamic mode to an upper protocol module. It passes the address of the characteristics table of the lower module to which the upper module must issue an Unbind command (this would be an entry into the VECTOR if the lower module is a MAC). LastUnbind is used to indicate the last InitiateUnbind request, so the module can perform any final cleanup before resuming.

If a protocol module does not have lower bindings (having a BindingsList with a NumBindings count = 0), InitiateUnbind will still be issued with CharTab set to NULL and LastUnbind set to nonzero in order to allow the module to terminate.

Unbind
Purpose: An unbind request from an upper protocol module to a lower module. PUSH LPBUF  CharTab  ;Callers characteristics table PUSH DWORD  0        ;Pad parameter- must be zero PUSH WORD   0        ;Pad parameter - must be zero PUSH WORD   5        ;Unbind request PUSH WORD   TargetDS ;DS of called module CALL System Returns:
 * 0x0000 SUCCESS
 * 0x0008 INVALID_FUNCTION
 * 0x00FF GENERAL_FAILURE

Description:

This function is used by one protocol module to unbind from another. The caller's characteristics table is passed to permit the called module to identify the upper module. If the Unbind is to a MAC, the VECTOR does the Unbind cleanup on behalf of the MAC. Thus MAC drivers themselves do not need to support this call.

Protocol Manager Primitives
Since the Protocol Manager primitives can be accessed via an IOCTL in OS/2, a request block is defined as follows: struct ReqBlock {    unsigned Opcode             /*Opcode for Protocol Manager request */ unsigned Status            /*Status at completion of request*/ char far *Pointer1             /*First parameter Ring 0 GDT pointer */ char far *Pointer2             /*Second parameter Ring 0 GDT pointer */ unsigned Word1             /*Parameter word */ }; Direct calls are made to the Protocol Manager with a pointer to the ReqBlock on the stack. For IOCTL requests, the parameter buffer contains a pointer to the ReqBlock. The direct calling sequence is as follows: PUSH LPBUF ReqBlock  ; Ring 0 GDT address of ReqBlock PUSH WORD  TargetDS  ; DS of Protocol Manager CALL ProtManEntry Note that under OS/2 the direct entry cannot be used at CONFIG.SYS initialization time since the driver is still in Ring 3 context.

Note also that if the Protocol Manager is in dynamic mode, these primitives can be invoked by other modules after system initialization. Dynamic OS/2 Ring 0 device drivers issuing these primitives post-INIT time must use the direct entry interface since the IOCTL interface is illegal at this time.

GetProtocolManagerlnfo
Purpose: Retrieve the pointer to configuration image.
 * Returns:
 * 0x0000 SUCCESS
 * 0x0008 INVALID_FUNCTION
 * 0x0002 F INFO_NOT_FOUND
 * 0x00FF GENERAL_FAILURE

This request is used by a module to the configuration information parsed from the user defined protocol configuration file PROTOCOL.INI. Modules invoke this function during device driver initialization to obtain this information for initializing configuration variables and making dynamic memory allocations and to determine their inter-module bindings.
 * Description:

In DOS dynamic mode, INFO_NOT_FOUND is returned if the Protocol Manager detects that the structured memory image is not valid. This can occur if, prior to loading a dynamic module, the structured configuration memory image was not registered with the Protocol Manager via a RegisterProtocolManagerInfo command or if the memory image got corrupted between registering it and getting it via the current primitive. The corruption might occur if another DOS program is loaded between the memory image registrations and the memory image read operation by a dynamic protocol invoking the GetProtocolManagerInfo primitive.

This request is valid in both the static and dynamic modes of Protocol Manager operation. In the static mode, this request is only valid prior to binding and starting. Invoking this primitive in static mode after all modules are bound and started will cause INVALID_FUNCTION to be resumed by the Protocol Manager.

RegisterModule
Purpose: Register a module and its bindings.
 * Returns:
 * 0x0000 SUCCESS
 * 0x0008 INVALID_FUNCTION
 * 0x002C ALREADY_REGISTERED
 * 0x00FF GENERAL_FAILURE

This request is used by a driver or dynamically loadable executable to identify one of its contained modules to the Protocol Manager. After calling RegisterModule, a static driver must remain installed and respond to system requests. A dynamic OS/2 driver must leave its system entry function code permanently locked in memory. A dynamic DOS module must remain installed and respond to system requests until it is unbound and unloaded. This registration is accomplished by passing a pointer to the module's characteristics table to the Protocol Manager. The driver also passes a bindings list requested by the module. The bindings list contains the one or more module names that the module wants to bind to as a client. This bindings information is later used by the Protocol Manager to determine the necessary sequence of InitiateBind commands to issue. This bindings list must persist while the protocol is operational. In the static default bindings case of one static protocol and one MAC, the bindings list pointer provided in this request can be NULL, indicating that a protocol module by default will bind to the single underlying MAC. Otherwise, in the nondefault bindings case, a NULL bindings list pointer provided in this request will indicate that this module will not bind to any other module at the current time and is not ready to initialize. In this latter case the Protocol Manager will not call the module's InitiateBind system function. A NULL bindings list pointer is particularly useful for dynamic OS/2 drivers that register their module name at INIT time, but are not to remain fully resident at startup time. This is called a nonbindable registration. A protocol module can also pass a non-NULL bindings list with a zero number of bindings count. In the default bindings case, this is interpreted by the Protocol Manager to bind the protocol to the single underlying MAC. In the nondefault bindings configuration this means that a protocol is registering without any lower bindings, but is required to be initialized by an InitiateBind call.
 * Description:

A driver that contains multiple modules can call RegisterModule multiple times, once for each module. The Protocol Manager responds to each request by assigning each module a module ID. The module ID is resumed in the module's characteristics table on completion of the RegisterModule request.

If a module name is currently registered with the Protocol Manager, an attempt to register the same module name will fail and a status code of ALREADY REGISTERED will be resumed. A dynamic OS/2 driver is considered currently registered if it had previously registered with a non-NULL bindings list indicating a requirement to bind and/or start and it had not yet unbound. Thus, a dynamic OS/2 driver can reregister with the Protocol Manager under the same module names if it either had unbound or had not previously made a bindable registration.

This request is valid in both the static and dynamic modes of Protocol Manager operation. In the static mode, this request is only valid prior to binding and starting. Invoking this primitive in static mode after all modules are bound and started will cause INVALID_FUNCTION to be returned by the Protocol Manager. A registration of a dynamic module (bit 2 set of the module function flags in the common characteristics table) in static Protocol Manager mode is invalid and will generate INVALID_FUNCTION. It is mandatory that all static DOS and static and dynamic OS/2 device drivers invoke this function at least once at INIT time.

BindAndStart
Purpose: Initiate the binding process.
 * Returns:
 * 0x0000 SUCCESS
 * 0x0007 INVALID_PARAMETER
 * 0x0008 INVALID_FUNCTION
 * 0x0020 ALREADY_STARTED
 * 0x0021 INCOMPLETE_BINDING
 * 0x0022 DRIVER_NOT_INITIALIZED
 * 0x0023 HARDWARE_NOT_FOUND
 * 0x0024 HARDWARE_FAILURE
 * 0x0025 CONFIGURATION_FAILURE
 * 0x0026 INTERRUPT_CONFLICT
 * 0x0027 INCOMPATIBLE_MAC
 * 0x0028 INITIALIZATION_FAILED
 * 0x0029 NO_BINDING
 * 0x0002 D PATH_NOT_FOUND
 * 0x0002 E INSUFFICIENT_MEMORY
 * 0x00FF GENERAL_FAILURE

This request is used to trigger the Protocol Manager bind and start sequence. This permits an application program (for example, executing from a DOS batch or OS/2 command file) to trigger the bind sequence. The bind sequence is invoked by the Protocol Managers calling each module's inter-module InitiateBind function. If an InitiateBind fails, then BindAndStart will fail with the same return code as the failing InitiateBind.
 * Description:

In the static mode of Protocol Manager operation, this request can be invoked only once to bind and start all static drivers. Successive invocations return INVALID_FUNCTION.

In the dynamic mode, this command tells the Protocol Manager to issue the InitiateBind primitive to all dynamically loaded protocol drivers that have registered since the last InitiateBind (or since the beginning of time for the first call)

In DOS, the caller is required to invoke this primitive via the direct entry point rather than the DOS IOCTL method. The Protocol Manager will generate an INVALID_FUNCTION error if this function is invoked by an IOCTL. This will permit the protocol modules to make DOS function calls during their bind and start sequence initiated by this primitive (when the Protocol Manager calls the InitiateBind system entry point of the protocol). If the IOCTL were used, the bind/start sequence would be carried out inside a DOS call, and protocols would not be able to make further DOS calls within their initialization sequence in order to prevent DOS reentry.

In DOS, the Protocol Manager loads PROTMAN.EXE to execute this command. The caller must have previously guaranteed that at least 20K of memory is available to load PROTMAN.EXE prior to invoking the BindAndStart primitive. In static VECTOR configurations (Chapter 7), PROTMAN.EXE will remain resident after BindAndStart completes. In such cases it is strongly recommended that the caller free as much memory as possible prior to calling BindAndStart so the PROTMAN.EXE will reside in the lowest memory possible. This will prevent large unusable gaps in DOS memory when the calling function terminates.

A utility, NETBIND.EXE, that invokes the BindAndStart primitive is provided with the Protocol Manager and is described in Appendix E.

GetProtocolManagerLinkage
Purpose: Retrieve Protocol Manager dispatch and DS value.
 * Returns:
 * 0x0000 SUCCESS
 * 0x0008 INVALID_FUNCTION
 * 0x00FF GENERAL_FAILURE

This request is used by a module to obtain the dispatch entry point and DS of the Protocol Manager. Direct calls can then be made by DOS and OS/2 Ring 0 drivers and DOS utilities to the dispatch entry point.
 * Description:

All dynamically reloaded OS/2 protocol drivers must issue this command to the Protocol Manager at CONFIG.SYS INIT time using the IOCTL mechanism and must save the Ring 0 Protocol Manager dispatch entry point and DS. When the driver subsequently reregisters with the Protocol Manager on reload at post-INIT time, it must do so via the direct entry interface using the saved entry point and DS (since an IOCTL would be illegal at that time).

Any DOS utility that intends to invoke the BindAndStart or UnbindAndStop Protocol Manager primitives must first invoke this primitive to get the Protocol Managers direct entry point.

This request is valid in both the static and dynamic modes of Protocol Manager operation. In the static mode, this request is only valid prior to binding and starting. Invoking this primitive in static mode after all modules are bound and started will cause INVALID_FUNCTION to be resumed by the Protocol Manager.

GetProtocollniPath
Purpose: A command to obtain the path to the PROTOCOL.INI file read by the Protocol Manager what it initialized.
 * Returns:
 * 0x0000 SUCCESS
 * 0x0007 INVALID_PARAMETER
 * 0x0008 INVALID_FUNCTION

This primitive can be called by an application program or dynamically loadable protocol that will read and parse the PROTOCOL.INI file to obtain the original location of the PROTOCOL.INI file used by the Protocol Manager when it initialized. This permits such a program to use the same file read by the Protocol Manager. The Protocol Manager returns only the pathname to the subdirectory containing the PROTOCOL.INI file, excluding the string \PROTOCOL.INI, which may be up to 60 characters in length. This string will include the drive identifier and be fully qualified relative to the root. The buffer must be large enough to hold the resumed string. If not, the contents of the buffer are undefined and the INVALID_PARAMETER error is returned.
 * Description:

This request is valid in both the static and dynamic modes of Protocol Manager operation. In the static mode, this request is only valid prior to binding and starting. Invoking this primitive in static mode after all modules are bound and started will cause INVALID_FUNCTION to be returned by the Protocol Manager.

RegisterProtocolManagerlnfo
Purpose: A command valid only in the dynamic mode to register the current starting address of the PROTOCOL.INI memory image with the Protocol Manager.
 * Returns:
 * 0x0000 SUCCESS
 * 0x0008 INVALID_FUNCTION

In dynamic mode, this command registers with the Protocol Manager the address of the PROTOCOL.INI memory image. It is assumed that prior to dynamically loading a protocol module, the PROTOCOL.INI file is reread and reparsed in some memory image. The pointer to the memory image is given to the Protocol Manager, so that it is available for the GetProtocolManagerInfo primitive of the dynamic initializing module that reads its configuration parameters.
 * Description:

In static mode, this command is illegal and the INVALID_FUNCTION error code is resumed.

A utility, READPRO.EXE, that reads and parses the PROTOCOL.INI file into a memory image and registers this with the Protocol Manager is provided with the Protocol Manager and is described in Appendix E.

InitAndRegister
Purpose: An optional dynamic OS/2 command to dynamically restart the prebind initialization of a dynamically reloadable protocol driver.
 * Returns:
 * 0x0000 SUCCESS
 * 0x0007 INVALID_PARAMETER
 * 0x0008 INVALID_FUNCTION
 * 0x00FF GENERAL_FAILURE

In OS/2 dynamic mode, this command reactivates the transient portions of a protocol driver previously statically loaded at system startup, but for which the transient portions of the driver were not locked down. The command causes the Protocol Manager to invoke the system entry point of the specified module with the InitiatePrebind function in order for the driver to restart its prebind initialization. The prebind initialization functions are driver specific. However, it is expected that such functions might include In static mode, this command is illegal and the INVALID_FUNCTION error code is resumed.
 * Description:
 * Locking down its dynamic segments using the DevHlp Lock command (lock type 1) and saving the resumed lock handle
 * Getting its PROTOCOL.INI configuration information
 * Doing its prebind initialization
 * Registering with the Protocol Manager

UnbindAndStop
Purpose: A dynamic binding command to terminate a transient, previously dynamically bound protocol module and to terminate its bindings.
 * Returns:
 * 0x0000 SUCCESS
 * 0x0007 INVALID_PARAMETER
 * 0x0008 INVALID_FUNCTION
 * 0x0002 D PATH_NOT_FOUND
 * 0x0002 E INSUFFICIENT_MEMORY

This command is used in the dynamic mode to terminate either a specific protocol module or a set of previously dynamically bound protocol modules and to terminate their binds. A "set" is the collection of protocol modules previously loaded or reloaded between two successive BindAndStart calls or between the last BindAndStart and this call. Successive UnbindAndStop commands with NULL Pointer2 arguments terminate protocol sets in the reverse order in which they were bound. The Protocol Manager removes references to the protocols from its VECTOR (for MAC unbindings) table and general bindings tables. The Protocol Manager issues an InitiateUnbind command to each protocol to be unbound so that the protocol can issue an Unbind command to the modules that it is bound to. For MAC unbindings, the Unbind is issued back to the Protocol Manager VECTOR. The NULL Pointer2 option is used in DOS environments for TSR protocol modules in which the unbind sequence usually proceeds in reverse order of the bind sequence. The non- NULL Pointer2 option must be used in OS/2 environments. The NULL Pointer2 option is invalid for OS/2.
 * Description:

In DOS, the caller is required to invoke this primitive via the direct entry point method rather than the DOS IOCTL method. The Protocol Manager will generate an INVALID_FUNCTION error if this function is invoked by an IOCTL. This will permit the protocol modules to be terminated to make DOS function calls during their unbind/stop sequence initiated by this primitive (when the Protocol Manager calls the InitiateUnbind system entry point of the protocol). If the IOCTL were used, the unbind/stop sequence would be carried out inside of a DOS call, and protocols would not be able to make further DOS calls within their termination sequence in order to prevent DOS reentry.

In DOS the Protocol Manager loads PROTMAN.EXE to execute this command. The caller must have previously guaranteed that at least 20K of memory is available to load PROTMAN.EXE prior to invoking the UnbindAndStop primitive.

A utility, UNBIND.EXE, that invokes the UnbindAndStop primitive is provided with the Protocol Manager and is described in Appendix E.

In static mode, this command is illegal and the INVALID_FUNCTION error code is resumed.

BindStatus
Purpose: A command to obtain information from the Protocol Manager about the current set of bound modules.
 * Returns:
 * 0x0000 SUCCESS
 * 0x0008 INVALID_FUNCTION
 * 0x000D BUFFER_TOO_SMALL

If enabled by the Protocol Managers BINDSTATUS=YES parameter in PROTOCOL.INI, this command can be called at any time to obtain information from the Protocol Manager about the current set of bound modules. If this command is disabled, an attempt to invoke this command will return INVALID_FUNCTION.
 * Description:

The following characteristics tables are returned for the modules that qualify: The tables are linked together into a bind tree using a new structure: struct BindNode {       struct cctable far *commonptr, struct BindNode far *down; struct BindNode far *right; }; NOTE: There may be additional fields added to BindNode in the future, so do not rely on its exact size.
 * Common characteristics
 * Service-specific characteristics (including the multicast address list for MAC modules)
 * Service-specific status
 * Media-specific statistics (for MAC modules only)

A BindNode is linked to its common characteristics table (CCT) by the CommonPtr field. The CCTs are then linked into a bind tree using the right and down pointers. Down points to the first BindNode bound below this one, and right points to the next. At the top of the tree (the uppermost level), the right pointers also link together the BindNodes as if they are bound to a virtual root BindNode.

A simple example might help illustrate this better: protocol /     \      MAC1    MAC2 This would be represented by the following bind tree: Protocol |           V           MAC1 --> MAC2 In the example, the BindNodes have been hidden to keep the diagram simple-only their down and right pointers are shown. The remaining down and right pointers would be NULL.

One option when making this call is to pass a NULL buffer pointer (in Pointer1), in which case the root BindNode pointer will be returned in Pointer1. The Protocol Manager uses BindNodes internally to build the bind tree. The caller can then run the current bind tree to obtain information. This is the only method supported under DOS. Under OS/2, this method will only work for Ring 0 drivers.

Under OS/2, Ring 3 programs must use a second method by providing a pointer to a buffer (in Pointer1) of a specified size (in Word1) to copy the characteristics tables into. In this case, the Protocol Manager will copy the qualifying tables into the buffer provided. The first entry in the buffer will be the root BindNode. The order of the remaining BindNodes and tables within the buffer is undefined. The BindNodes and their various tables are linked together by pointers that will be fixed by the Protocol Manager to use the same selector as the buffer itself (that is, Ring 3 if the buffer is Ring 3). Specifically, the Protocol Manager will fix the following entries:
 * BindNode:
 * CommonPtr
 * Down
 * Right
 * Common characteristics:
 * Pointer to service-specific characteristics
 * Pointer to service-specific status
 * Service-specific characteristics
 * Pointer to multicast address list (MACs only)
 * Service-specific status
 * Pointer to media-specific statistics (MACs only)

The remaining pointers (for example, dispatch tables and entry points) will be in an undefined state and must not be relied upon.

If the buffer is too small, BUFFER_TOO_SMALL will be resumed, the pointers to tables that were not copied will be NULL, and the bytes copied return parameter (Word1) will indicate where the information was truncated.

The information resumed is merely a snapshot at a particular point of time. The Protocol Manager will disable interrupts while copying individual status and media- specific statistics tables to guarantee their internal integrity. The caller cannot assume that all tables were copied in the same atomic operation, however.

In the case of OS/2, if two or more modules are bound to the same lower module, the lower module's table is duplicated in the tree. Therefore, the Ring 3 caller will have to provide a larger amount of buffer space for the returned information.

The number of nodes in the bind tree does not necessarily reflect the number of modules bound.

RegisterStatus
Purpose: A command to query whether a specific logical module is currently registered with the Protocol Manager.
 * Returns:
 * 0x0000 SUCCESS
 * 0x0008 INVALID_FUNCTION
 * 0x002C ALREADY_REGISTERED

This command can be called in either the static or dynamic mode to determine whether a specific logical module is currently registered with the Protocol Manager. This can be used by the caller to determine whether a specified module has already registered with the Protocol Manager to prevent duplicate registration. A SUCCESS status resumed means that the specified module is not currently registered with the Protocol Manager. An ALREADY_REGISTERED status means that the module is currently registered.
 * Description:

In the static mode, this request is only valid prior to binding and starting. Invoking this primitive in static mode after all modules are bound and started will cause INVALID_FUNCTION to be resumed by the Protocol Manager.

Protocol Manager Initialization
The Protocol Manager is loaded and initialized in both the OS/2 and DOS environments via the operating system CONFIG.SYS INIT sequence. It must be loaded before any protocol or MAC driver is loaded. In DOS, the Protocol Manager is provided in a file called PROTMAN.DOS. For OS/2, the file is PROTMAN.OS2. The device name for the Protocol Manager is PROTMAN$ under DOS and \DEV\PROTMAN$ under OS/2 (the \DEV format is required by versions 1.2 or later of OS/2).

In DOS, to save memory an additional dynamically readable component of the Protocol Manager called PROTMAN.EXE is provided. This file must reside in the same directory as the static device driver component, PROTMAN.DOS, itself. This file is called for execution by the Protocol Manager device driver component whenever the Protocol Manager primitives BindAndStart and UnbindAndStop are to be executed. In the static VECTOR mode (Chapter 7), PROTMAN.EXE will remain resident after BindAndStart executes.

The Protocol Manager reads the PROTOCOL.INI file at INIT time and parses it to create the configuration memory image passed to the protocol modules. The file is located in the \LANMAN directory of the boot drive or the directory given by the /I: parameter on the DEVICE=PROTMAN.xxx line in CONFIG.SYS. Under DOS, this image is relocated to just below the memory ceiling, where it must remain untouched until all binding has completed. The Protocol Manager computes a checksum of this image and checks it at bind time to guarantee that the image has not been modified in the interim. Note that this memory is not reserved by the Protocol Manager.

If the Protocol Manager CONFIG.SYS initialization is successful, it is ready to support the initialization of the other drivers. However, the initialization can be aborted for either of the following reasons:
 * The Protocol Manager did not have enough memory to hold the PROTOCOL.INI configuration memory image.
 * The Protocol Manager encountered a syntax error while parsing the PROTOCOL.INI file. This could have been an illegal hexadecimal or decimal parameter value, an overflow condition (numeric value could not fit into 32 bits) was encountered, or a string was encountered with missing end quotes.

These conditions are flagged as fatal errors to prevent erroneous configuration parameters from propagating to the drivers for their operation.

Static Binding Sequence
The Protocol Manager can be configured to operate either in the static binding mode or in the dynamic binding mode. In the static binding mode, only statically loadable device drivers can be loaded and bound once at system initialization time. In the dynamic binding mode, dynamically loadable protocol drivers can be loaded and dynamically bound and unbound during system operation on a demand basis. Static drivers can also be loaded at INIT time in dynamic mode. The static binding sequence is described in this section. The dynamic binding sequence is described in Chapter 7, "VECTOR and Dynamic Binding."

To determine the binding sequence, the Protocol Manager builds a tree representing the bindings for all the modules in the system. MAC drivers are at the bottom, and the highest level (for example, NetBIOS) protocol layers are at the top. It then binds pairs together from the bottom up. To do this, it issues an InitiateBind to the upper module in the pair, passing it the characteristics table of the lower module. The upper module is expected to issue a bind to the lower module (if it is acceptable) and return. This continues with the next higher-up module. If there is a module that is not bound to anything else, it receives an InitiateBind with a NULL characteristics table pointer.

To be more formal, the following definitions are required: The Protocol Manager builds a tree with multiple branches. Each MAC driver is at the base of a branch, with the protocol layers bound to it above it. Standalone modules are also considered branches by themselves. The left-to- right order is defined by the order in which the modules register with the Protocol Manager. The Protocol Manager does a preorder transversal of the tree, issuing InitiateBinds to all of the nodes except the MAC drivers.
 * A MAC driver is a protocol module with an upper-layer interface level of one (MAC layer) and a lower-layer interface level of zero (physical). It must support binding at its upper boundary.
 * A MAC-layer entity is a protocol module with both upper- and lower-layer interface levels of one. It must support binding at its lower boundary.
 * A standalone protocol module is one that has a lower-layer interface levy of zero and that does not support binding at its upper boundary.

An important aspect of the binding scheme is that it allows for modules to specify that they only do binding from above or below. This is a requirement in cases where a monolithic module exposes several interfaces, such as a NetBIOS, TLI, and DLC. The TLI could be presented as a logical module that had an upper interface (the TLI) but no lower interface (since it uses a private internal interface to its DLC). Such a module would have a characteristics table with the following settings: Sequence for non-VECTOR configurations:
 * 1) Protocol Manager driver (PROTMAN.OS2 for OS/2 or PROTMAN.DOS for DOS) is loaded during CONFIG.SYS initialization. The Protocol Manager must be configured ahead of any MAC or protocol drivers in CONFIG.SYS.
 * 2) Protocol Manager initializes and reads PROTOCOL.INI to build the configuration memory image.
 * 3) MAC and protocol drivers are loaded by the operating system. During its initialization processing, each driver optionally does the following:
 * 4) * Open the PROTMAN$ device.
 * 5) * Invoke the GetProtocolManagerInfo primitive to PROTMAN$ to get a pointer to the configuration memory image.
 * 6) * Read configuration parameters from the image and use these to finish initialization and build characteristics tables.
 * 7) * Use the RegisterModule function once for each module to be defined to the Protocol Manager.
 * 8) CONFIG.SYS processing ends and applications are started.
 * 9) An application opens the PROTMAN$ device and issues the BindAndStart IOCTL. Such an application utility, called NETBIND.EXE, is provided with the Protocol Manager driver and is defined in Appendix E.
 * 10) The Protocol Manager uses information passed on previous RegisterModule calls to determine the module binding hierarchy.
 * 11) Proceeding from bottom to top of the binding hierarchy, the Protocol Manager uses InitiateBind to cause each module to bind to the module below it in the hierarchy. Each module getting this call responds by issuing a bind call to the module specified by the Protocol Manager on InitiateBind.
 * 12) When all modules have been bound, the Protocol Manager returns from BindAndStart.

The system is now fully operational. VECTOR configurations are similar, with the VECTOR being automatically inserted between layers one and two, if necessary (on top of the MAC driver as well as any MAC-layer entities that are present).

OS/2 Calling Convention
All of the Protocol Manager requests are supported by a single OS/2 IOCTL function. The services are demultiplexed via a function code specified in the ReqBlock structure.

This IOCTL has the following IOCTL request packet parameters:
 * Block device unit code: Undefined since the Protocol Manager is a character device.
 * Command code: 16 for generic IOCTL.
 * Status: If the IOCTL corresponds to one of the Protocol Manager commands, then the status field is returned with the ERR bit cleared, signifying IOCTL successful completion. However, the final status of the command is returned in the status field of the ReqBlock buffer as defined below. Note that if the command is recognized the ERR bit is always cleared regardless of the status returned in the status field. However, if the command is not recognized, an IOCTL status UNKNOWN_COMMAND (3) is returned with the ERR bit set. Finally, all of the commands return with the status DON bit set.
 * Category code: 0x81, which is the LAN Manager category code.
 * Function code: 0x58 for Protocol Manager command type.
 * Parameter buffer: Pointer to ReqBlock structure.
 * Data buffer: Unused, therefore the pointer is NULL.

By using the GetProtocolManagerLinkage request, a module can obtain the Protocol Manager dispatch point and DS. Once a module obtains the Protocol Manager's entry point and data segment, it passes a request to the Protocol Manager via the following function call: int (far Pascal *ProtManEntry)(ReqBlockPtr, DataSeg); struct ReqBlock far *ReqBlockPtr; unsigned DataSeg; where:
 * ReqBlockPtr = a FAR pointer to the request block.
 * DataSeg = the Protocol Manager's data segment base.

The Protocol Manager returns in AX the same return code that is returned in the ReqBlock status.

DOS Calling Convention
All of the Protocol Manager requests are supported by a single DOS IOCTL function. The services are demultiplexed via a function code specified in the ReqBlock. This IOCTL should be requested via interrupt 21 with general registers loaded with the following contents:
 * AH = 44H for IOCTL request
 * AL = 02H for device input
 * DS:DX = Pointer to ReqBlock structure
 * CX = 14 for the size of the ReqBlock structure
 * BX = Handle from DOS open of PROTMAN$

This IOCTL generates the following IOCTL request packet parameters:
 * Block device unit code: Undefined since the Protocol Manager is a character device.
 * Command code: 3 for IOCTL input.
 * Status: If the IOCTL corresponds to one of the Protocol Manager commands, then the status field is returned with the ERR bit cleared, signifying IOCTL successful completion. However, the final status of the command is resumed in the status field of the ReqBlock buffer as defined below. Note that if the command is recognized the ERR bit is always cleared regardless of the status resumed in the status field. However, if the command is not recognized an IOCTL status UNKNOWN COMMAND (3) is returned with the ERR bit set. Finally, all of the commands return with the status DON bit set.
 * Media descriptor byte: Unused.
 * Transfer address: Pointer to ReqBlock structure.
 * Byte/sector count: 14.
 * Starting sector number: unused.

By using the GetProtocolManagerLinkage request, a module or application can obtain the Protocol Manager dispatch point and DS. It then makes a request to the Protocol Manager via the same direct calling mechanism as OS/2.

Chapter 7 - VECTOR and Dynamic Binding
In static mode, the VECTOR is a function that is implemented within the Protocol Manager that allows more than one protocol stack to drive a single MAC. In this mode, the Protocol Manager uses the VECTOR function only if it detects that more than one protocol is using the same MAC. If more than one MAC is attached to multiple protocol stacks, then an instantiation of the VECTOR is created for each MAC so attached.

In dynamic mode, the VECTOR function is always present unconditionally for protocol/MAC intermodule communications. There can be zero, one, or more protocol stacks that bind to a MAC, but the VECTOR function is still present. There can be zero protocols if there is only one dynamic protocol stack being used in the system and that stack is not currently loaded. In the dynamic mode, the VECTOR shields all static binding MACs from the interactions of dynamic binding and unbinding protocol modules.

Static VECTOR Binding
The Protocol Manager will modify the normal binding process if it detects that multiple protocols have requested the use of the same MAC in the PROTOCOL.INI file.


 * 1) At INIT time from RegisterModule the Protocol Manager has determined the bind hierarchy and has found some MACs that bind to two or more protocols, signaling the insertion of VECTOR
 * 2) To a MAC that will support multiple protocol stacks, the Protocol Manager issues a bind, passing the Protocol Manager characteristics table with entry points into the VECTOR module. The MAC starts itself and returns, passing back to the Protocol Manager a pointer to the MAC's characteristics table.
 * 3) For a protocol that is part of a multiple protocol stack binding to the single MAC that was issued the previous bind command, the Protocol Manager issues InitiateBind, passing as the bind intermodule entry point, an entry point within the VECTOR module inside of the Protocol Manager.
 * 4) The protocol module responds by issuing a bind request back to the Protocol Manager through its VECTOR entry point. The protocol module passes its characteristics table to the Protocol Manager VECTOR. The Protocol Manager returns a characteristics table within the VECTOR that is copied from the associated MACs characteristics tables, substituting the VECTOR entry points for the real MACs entry points.
 * 5) The protocol starts itself ant returns from InitiateBind.
 * 6) The Protocol Manager then issues subsequent InitiateBinds to other protocol modules as described above. If these other protocols are bound to a MAC through the VECTOR, the VECTOR procedure is repeated. Otherwise the non- VECTOR procedure is used.

At the conclusion of the binding process the VECTOR is in a position to filter calls as appropriate, going in either direction across the MAC/protocol interface.

Dynamic VECTOR Binding
A dynamic module can be loaded and bound after system initialization time on a demand basis. This dynamic loading and binding takes place in three phases:


 * 1) The PROTOCOL.INI file is reread.
 * 2) The dynamic protocol module does some prebind initialization, including getting its PROTOCOL.INI configuration parameters ant registering with the Protocol Manager.
 * 3) The dynamically loaded protocol module dynamically binds to other modules given in its bind specification. If these other modules are MACs, the bind takes place through the Protocol Manager VECTOR facility.

At some point the dynamic protocol module is no longer required. The protocol module unbinds itself, terminates, ant unloads itself from memory.

The mechanisms for dynamically binding and unbinding are carried out somewhat differently between DOS and OS/2. The procedures are briefly described in the following section.

Dynamic Binding/Unbinding in the DOS Environment

 * 1) In dynamic mode, both static and dynamic protocol modules can be supported. At startup time, the Protocol Manager performs initialization and binding of static modules as described in the "Static Binding Sequence" section in Chapter 6. However, in the dynamic mode, the VECTOR function is always inserted.
 * 2) At some point after system startup, a dynamic loadable protocol module (that can be a transient application program or a TSR) is demand loaded. For the dynamic protocol module to have its configuration parameters at initialization, the PROTOCOL.INI file must be reread. Either an application program or the protocol module itself reads ant parses the PROTOCOL.INI file into the configuration memory image. It is suggested that the application or protocol module obtain the location of the PROTOCOL.INI file using the GetProtocolIni primitive. A pointer to this memory image is passed to the Protocol Manager via the RegisterProtocolManagerInfo primitive. This is required since the configuration memory image created by the Protocol Manager at MT time is not valid at post-INIT time. An application utility, READPRO.EXE, that reads and parses PROTOCOL.INI is provided with the Protocol Manager ant is described in Appendix E.
 * 3) After loading, the protocol module initializes. Minimally, the protocol gets its PROTOCOL.INI configuration information from the Protocol Manager via GetProtocolManager Info, does its prebind initialization, and registers with the Protocol Manager via RegisterModule.
 * 4) Either an application or the dynamic protocol module itself requests that the Protocol Manager initiate the binding sequence via the BindAndStart primitive. This causes the bind sequence described in steps 3 through 5 of the "Static VECTOR Binding" section, earlier in this chapter, to be executed. After the bind, the dynamic protocol is ready for use. An application utility, NETBIND.EXE, to initiate the binding sequence is provided with the Protocol Manager ant is described in Appendix E.
 * 5) During operation, all protocol commands to the MAC go through the VECTOR.
 * 6) When the dynamic protocol module is ready terminate, either it or an application program issues the UnbindAndStop command to the Protocol Manager. This causes the Protocol Manager to call the protocol's InitiateUnbind system entry point. In turn, this allows the protocol to issue Unbinds to other modules it was bound to and to do final cleanup before terminating. On return from the UnbindAndStop command, the protocol can be removed from memory. An application utility, UNBIND.EXE, to initiate the unbinding sequence is provided with the Protocol Manager and is described in Appendix E.

Dynamic Binding/Unbinding in the OS/2 Environment

 * 1) In OS/2, all dynamic protocol modules are multisegment OS/2 device drivers. A dynamic OS/2 protocol differs from a static one in that the dynamic module has code and/or data segments that can be swapped out of virtual memory when not needed. These extra code and data segments must be specified with IOPL in the module's .DEF file so that they me marked as movable/swappable and not discardable by OS/2. In a static protocol module all segments are permanently locked in memory. A dynamic protocol module uses the OS/2 DevHlp Lock and Unlock calls (using a lock type of 1) to lock and free its code and/or data segments as needed. A dynamic protocol module is able to reregister multiple times with the Protocol Manager ant to dynamically bind with other configured modules. When no longer required, the dynamic module can unbind ant the dynamic memory segments can be unlocked to free up the memory. Static OS/2 protocol modules register and bind only at system initialization time. They do not unbind.
 * 2) Since all OS/2 dynamic protocol modules are OS/2 device drivers, they may perform some INIT time initialization. The protocol must always register at INIT time with the Protocol Manager via RegisterModule. A protocol that is not required at system startup must still register with the Protocol Manager at INIT time, passing a NULL BindingsList pointer in the RegisterModule primitive. This is called a nonbindable registration. In this case the protocol need not lock down its extra code and data segments. It does, however, need to save the selector values for its dynamic code and data segments. The device drives device header, strategy routine, and the NDIS system entry routine must reside in the driver's main code and data segments (the first ones in the driver), which are permanently locked down. A driver required at system startup must pass a non-NULL BindingsList pointer if it has modules it is required to bind to (a bindable registration). A driver required at system startup must go ahead and DevHlp Lock its other segments at INIT time, making sure to save the lock handle returned by the call. Also at INIT time, the protocol module must invoke the GetProtocolManagerLinkage primitive to get and save the Protocol Managers Ring 0 direct entry point and DS.
 * 3) Assuming that the protocol was not required at system startup time, at some point in time later it needs to be dynamically bound. At this point the module needs to get its PROTOCOL.INI configuration parameters, lock down its code and data segments, and perform its bindings. lathe configuration parameters are not repined in the base data segment, the protocol must raced the PROTOCOL.INI file. This is tone in a similar fashion to that described for DOS. The InitAndRegister primitive is the standard facility that lets the Protocol Manager request the protocol to reload its dynamic segments and perform its prebind initialization. Upon receiving the InitAndRegister primitive, the Protocol Manager calls the protocol driver's system entry point with InitiatePrebind, allowing the protocol to perform its prebind initialization. The protocol module uses this opportunity to issue DevHlp Lock calls (lock type 1) on its dynamic segments to bring them back into memory. The handle returned from the Lock call must be saved for later unlocking. Also at this juncture, the protocol can get its PROTOCOL.INI memory image from the Protocol Manager via the direct entry point GetProtocolManagerInfo function. It may also do other prebind initialization and finally register with the Protocol Manager via the direct entry point RegisterModule function. If the protocol module had previously made a nonbindable registration at system startup, then the current registration affords it the opportunity to specify its bindings to the Protocol Manager.
 * 4) The bind and postbind initialization step is similar to that described for DOS. Again, any protocol binds to MACs are performed through the VECTOR.
 * 5) During protocol operation, any protocol commands to a MAC go through the VECTOR.
 * 6) When the protocol is no longer required, an application or the protocol itself can issue the UnbindAndStop command to the Protocol Manager. The sequence is similar to that described for DOS. The OS/2 driver, however, issues DevHlp Unlock commands against all of its dynamic segments so that these can be swapped out from memory. The previously saved lock handle is required on this call.

VECTOR Demultiplexing
The VECTOR dispatches incoming frames to protocol stacks using either a preprogrammed default or user statically defined priority polling mechanism. The default mechanism is based on the InterfaceFlags variable in the protocol's lower dispatch table. These flags describe the protocol according to the kinds of frames it handles:
 * Non-LLC frames
 * LLC frames with specific LSAPs
 * LLC frames with nonspecific LSAPs

According to default dispatch priority, VECTOR polls protocols in that order (and within that order, in the order they registered) until it finds one that does not return FRAME_NOT_RECOGNIZED or FORWARD_FRAME in the indication. For specific protocols, this default can be overridden by specifying the bracketed name of the protocol with the Protocol Manager PROTOCOL.INI keyword PRIORITY. Protocols with static priorities specified in this manner are polled by the VECTOR before any protocol not so specified. Protocols with static priorities are themselves polled in the order in which their bracketed names appear in the PRIORITY keyword parameter list. Of course, a protocol appearing in the static list is only polled if it is registered with the Protocol Manager and has bound to the MAC offering up the frame.

Appendix A - System Return Codes
This appendix lists return codes used in this version of the NDIS specification. Note that new error codes may be added in the future. Both protocol and MAC driver developers must design their code to allow for this.

0x0000 SUCCESS: The function completed successfully.

0x0001 WAIT_FOR_RELEASE: The ReceiveChain completed successfully but the protocol has retained control of the data buffer. ReceiveRelease will be called to release the data buffers.

0x0002 REQUEST_QUEUED: The current request has been queued. If the request handle is nonzero, the module will call TransmitConfirm or RequestConfirm when the request completes.

0x0003 FRAME_NOT_RECOGNIZED: This error is returned from the protocol when a MAC does an Indication and the frame does not make sense to the protocol. This will be interpreted by the VECTOR to mean that the next protocol in line ought to be called with the Indication.

0x0004 FRAME_REJECTED: A received frame was recognized but it was discarded. The buffer may be immediately reused.

0x0005 FORWARD_FRAME: A protocol wants the received frame to be offered to other protocols but wants to receive an IndicationComplete. This will be interpreted by the VECTOR to mean that the next protocol in line ought to be called with the Indication.

0x0006 OUT_OF_RESOURCE: The module is in a transient out-of-resource condition. The current request was not completed.

0x0007 INVALID_PARAMETER: One or more parameters were invalid.

0x0008 INVALID FUNCTION: A command function was requested when it was not legal to do so or an invalid request was made.

0x0009 NOT_SUPPORTED: A valid request that is not supported by the module was issued.

0x000A HARDWARE_ERROR: A hardware error occurred during the execution of this request. The request was not completed successfully; this can be considered nonfatal.

0x000B TRANSMIT_ERROR: The packet was not transmitted. This error code may indicate a local resource problem, excessive collisions, or a remote resource problem. On Token-Ring networks, this would be returned if the destination address was recognized but the receiver was out of buffers. This is a nonfatal error and can be taken as a hint that the packet should be retransmitted.

0x000C NO_SUCH_DESTINATION: The destination address was not recognized by any adapter on the local ring. This error is Token-Ring specific and can be interpreted to mean that source routing must be invoked to reach the destination.

0x000D BUFFER_TOO_SMALL: The buffer provided was too small for the information being returned. Some commands may still return partial information.

0x0020 ALREADY_STARTED: The Protocol Manager has already started the network drivers. This error occurs when BindAndStart is called more than once.

0x0021 INCOMPLETE_BINDING: This bind-time error occurs when the Protocol Manager cannot complete all of the bindings described in the bindings list, most probably due to missing modules.

0x0022 DRIVER_NOT_INITIALIZED: This bind-time error occurs when the MAC does not initialize properly during system boot, and a subsequent request is made to the MAC.

0x0023 HARDWARE_NOT_FOUND: This bind-time error occurs when the network adapter is not found by the MAC.

0x0024 HARDWARE_FAILURE: This error occurs in the following cases: network adapter reset failed, network adapter diagnostics failed, network adapter is not responding, network adapter is not found by the MAC. This error can be considered fatal.

0x0025 CONFIGURATION_FAILURE: This bind-time error occurs when the configuration is unacceptable to the network adapter.

0x0026 INTERRUPT_CONFLICT: This bind-time error occurs in OS/2 only, when an interrupt from some other device in the computer conflicts with the network adapter's interrupt.

0x0027 INCOMPATIBLE_MAC: This bind-time error occurs when a protocol determines a MAC is not compatible for the binding operation. Thus, binding cannot proceed.

0x0028 INITIALIZATION_FAILED: This bind-time error occurs when a protocol fails its initialization.

0x0029 NO_BINDING: This bind-time error occurs to indicate that the binding was not performed. This error can occur if a protocol driver took an error exit during its initialization or if a protocol driver has its upper level incorrectly specified as a MAC.

0x002A NETWORK_MAY_NOT_BE_CONNECTED: This bind-time error indicates that the adapter may not be connected to a network. It is intended to be suggestive of corrective action by the user.

0x002B INCOMPATIBLE_OS_VERSION: This bind-time error indicates that a protocol or MAC driver does not support the version of DOS or OS/2 being used.

0x002C ALREADY_REGISTERED: This error is returned by the Protocol Manager if an attempt is made to register a module with a module name already registered with the Protocol Manager. It is also resumed from a RegisterStatus primitive to indicate that the name is already registered.

0x002D PATH_NOT_FOUND: This error is resumed by the DOS Protocol Manager if PROTMAN.EXE could not be found when attempting to execute a BindAndStart or UnbindAndStop command.

0x002E INSUFFICIENT_MEMORY: This error is resumed by the DOS Protocol Manager if PROTMAN.EXE could not be loaded due to insufficient DOS memory when attempting to execute a BindAndStart or UnbindAndStop command.

0x002F INFO_NOT_FOUND: This error is resumed by the DOS Protocol Manager in a GetProtocolManagerInfo command if the PROTOCOL.INI structured configuration memory image is not present or was previously invalidated due to being overwritten or corrupted.

0x00FF GENERAL_FAILURE: Unspecified failure during execution of the function. 0xF000-0xFFFF: Reserved for vendor-defined error returns. These errors are treated as GENERAL_FAILURE.

Appendix B - Reference Material

 * OS/2 Device Drivers Guide
 * DOS Technical Reference
 * ANSI/IEEE standard 802.2 - 1985 (ISO/DIS 8802/2) Logical link control standard.
 * ANSI/IEEE standard 802.3 - 1985 (ISO/DIS 8802/3) Carrier Sense Multiple Access with Collision Dection local area network standard.
 * ANSI/IEEE standard 802.5 - 1985 (ISO/DIS 8802/5) Token- Ring local area network standard.
 * The EtherNet. A Local Area Network. Data Link Layer and Physical Layer Specifications, version 2.0, November 1982. Also known as the "Ethernet Blue Book."
 * IBM Token-Ring Network PC Adapter Technical Reference (69X7830).
 * IBM Token-Ring Network Architecture Reference - November 1985 (6165877).
 * Information processing systems - Open Systems Interconnection - Basic Reference Model, (ISO 7498). The OSI reference model.

Appendix C - NDIS 2.0.1 802.3
The 802.3 media-specific statistics structure is defined as follows:

Statistics in bold are mandatory, all others are strongly recommended. Reserved slots should return as 0xFFFFFFFF (unsupported). WORD       Length of 802.3 statistics structure, including this field WORD       802.3 statistics structure version level (1) DWORD      Total frames with alignment error DWORD      Reserved (obsolete statistic) DWORD      Total frames with overrun error DWORD      Reserved (obsolete statistic) DWORD      Total frames transmitted after deferring DWORD      Total frames not transmitted - max (16) collisions DWORD      Reserved (obsolete statistic) DWORD      Total late (out of window) collisions DWORD      Total frames transmitted after exactly one (1) collision DWORD      Total frames transmitted after multiple collisions DWORD      Total frames transmitted, CD heartbeat DWORD      Reserved (obsolete statistic) DWORD      Total carrier sense lost during transmission DWORD      Reserved (obsolete statistic) DWORD      Total number of underruns (version 2.0.1 or later) When updating the statistics counters, a frame is counted in all the supported counters that apply.

Examples


 * 1) A "Multicast flame received ok" is counted in the following statistics counters:
 * 2) * Total multicast frames received ok
 * 3) * Total frames received ok
 * 4) A "Transmit broadcast frame with one collision" is counted in all the following statistics counters:
 * 5) * Frames transmitted with only one collision
 * 6) * Total broadcast frames transmitted
 * 7) * Total frames transmitted ok

Definitions
Total frames with alignment error

(NumberOfFramesReceivedWithAlignmentErrors)

This contains a count of frames that are not an integral number of bytes in length and do not pass FCS check. It reports on alignment errors "as the station sees it."

Total frames with overrun error

This contains a count of frames that could not be accepted due to a DMA overrun error.

Total frames transmitted after deferring

(NumberOfFramesWithDeferredTransmission)

This counter does not include frames involved in collisions.

Total frames not transmitted - max (16) collisions

(NumberOfFramesAbortedDueToExcessiveCollision)

This contains a count of the frames that are not transmitted successfully due to excessive collisions.

Total late (out of window) collisions

(NumberOfLateCollisions)

This contains a count of frames that are involved in an out-of-window collision.

Total frames transmitted after exactly one (1) collision

(NumberOfSingleCollisionFrames)

This contains a count of frames that are transmitted after exactly one collision.

Total frames transmitted after multiple collisions

(NumberOfMultipleCollisionFrames)

This contains a count of frames that are transmitted after a multiple number of collisions.

Total frames transmitted, CD heartbeat

(NumberOfSQETestErrors)

This contains a count of frames transmitted with the CD (collision detection) signal missing.

Total carrier sense lost during transmission

(NumberOfCarrierSenseErrors)

This contains a count of frames that experienced carrier sense lost (carrier sense signal not present at the receive pair of the controller) during transmission.

Total number of underruns (version 2.0.1 or later)

This contains a count of frames that could not be transmitted due to a DMA underrun error.

Appendix D - 802.5 Media-Specific Statistics
The 802.5 media-specific statistics structure is defined as follows:

Statistics in bold are mandatory, all others are strongly recommended. Reserved slots should return as 0xFFFFFFFF (unsupported). WORD        Length of 802.5 statistics structure, including this field WORD        802.5 statistics structure version level (1) DWORD       FCS or code violations detected in repeated frame DWORD       Reserved (obsolete statistic) DWORD       Number of 5 half-bit time transition absences detected DWORD       A/C errors DWORD       Frames transmitted with abort delimiter DWORD       Frames transmitted that failed to return DWORD       Frames recognized, no buffer available DWORD       Frame copied errors DWORD       Number of frequency errors detected DWORD       Number of times active monitor regenerated DWORD       Reserved DWORD       Reserved DWORD       Reserved DWORD       Reserved (obsolete statistic) DWORD       Number of underruns When updating the statistics counters, a frame is counted in all the supported counters that apply.

Definitions

 * FCS or code violations detected in repeated frame : This counter is incremented for every repeated frame that has a code violation or fails the frame check sequence (FCS) cyclic redundancy check.


 * Number of 5 half-bit time transition absences detected : Also known as burst error, this counter is incremented every time 5 half-bit time transitions are not detected between SDEL and EDEL in a repeated flame.


 * A/C errors : Also known as ARI/FCI set error, this counter is incremented when a station receives more than one AMP or SMP MAC frame with AC (ARI/FCI) equal to zero without first receiving an intervening AMP MAC frame. This counter indicates that the upstream adapter is unable to set its AC (ARI/FCI) bits in a frame that it has copied.


 * Frames transmitted with abort delimiter : This counter is incremented each time the adapter transmits an abort delimiter. This indicates that the frame was aborted in mid-transmission.


 * Frames transmitted that failed to return : This counter is incremented when a transmitted frame fails to return from around the ring due to time-out or the reception of another frame.


 * Frames recognized, no buffer available : Also known as receiver congestion, this counter is incremented when a ring station is receiving/repeating a frame and recognizes a frame addressed to it, but has no buffer space available for the frame.


 * Frame copied errors : This counter is incremented when a ring station receives or repeats a frame from the ring with the ring station's individual address, but with A = C = 1, indicating a possible duplicate address.


 * Number of frequency errors detected : This counter is incremented when a ring station detects a signal frequency problem.


 * Number of times active monitor regenerated : This counter is incremented each time the active monitor is lost and regenerated.


 * Number of underruns : This counter is incremented each time a DMA underrun is detected.

Appendix E - Utilities Provided with the Protocol Manager
To save system integrators the effort to read and parse the PROTOCOL.INI file, to register it with the Protocol Manager, to invoke the binding and unbinding of Protocol Manager primitives, and to report various Protocol Manager error conditions, three utilities are provided with the Protocol Manager in both the DOS and OS/2 environments and one utility is provided exclusively for the OS/2 environment:

If the system integrator requires more functionality than that provided by these utilities, the integrator can write an application utility that performs the desired functionality and invokes the required Protocol Manager primitives described in Chapter 5. For example, if in DOS a more flexible unbind facility to unbind in a user-specified order is required, UNBIND.EXE can be replaced by a user-written utility that invokes the UnbindAndStop primitive, in which Pointer2 points to the name of the module to be unbound.

Notices
October 8, 1990

This specification is intended for use by those developing or using networking products. This specification may be copied freely for that purpose as long as copyright notice is preserved on all copies of the specification. No fee or royalty is required by either 3Com Corporation or Microsoft Corporation to develop products that use the information contained within this specification. Information contained in this specification can be included in documents, presentations, or products of third parties; however, authorship must be attributed jointly to 3Com Corporation and Microsoft Corporation, and appropriate copyright notices must be placed in any such documents or presentations. Additional copies of this specification can be obtained from 3Com Corporation or Microsoft Corporation.

Copyright Notices
Copyright 1988, 1989, 1990 3Com Corporation/Microsoft Corporation

Microsoft, the Microsoft logo, and MS are registered trademarks of Microsoft Corporation.


 * 3Com is a registered trademark and EtherLink II is a trademark of 3Com Corporation.
 * AppleTalk is a registered trademark of Apple Computer, Inc.
 * ArcNet is a registered trademark of Datapoint Corporation.
 * IBM is a registered trademark of International Business Machines Corporation.
 * EtherNet is a registered trademark of Xerox Corporation.