INFO: Differences Between Data Link Control APIs on WinNT & DOS

ID: Q156081

The information in this article applies to:

SUMMARY

This article describes the major differences between the Win32 Data Link Control (DLC) API and the DOS DLC interface. It assumes familiarity with the DLC protocol and the relevant specification documents. Where appropriate, differences from the IBM OS/2 DLC interface are also described.

MORE INFORMATION

The Win32 DLC API has been designed to be as compatible with the IBM OS/2 DLC API for OS/2 1.xx as possible. The limits to compatibility are those imposed by the operating system functions (such as Event vs. Semaphores), and the differing memory models (flat vs. segmented).

The API is described herein as differences from the Command Control Block (CCB) interface in the IBM LAN Technical Reference, Fourth Edition (Dec, 1990). Areas addressed in the IBM documentation are generally not repeated here.

Differences between the Win32 and OS/2 DLC API

The following is a list of the differences between IBM OS/2 DLC and the Win32 DLC API.

Differences between the Win32 and DOS/2 DLC API

Win32 DLC API

In general, most of the functions and their parameter blocks are identical to those of the IBM DLC API for OS/2 1.xx, with the pointers being changed from 16-bit offsets to 32-bit flat addresses.

Because of the compatibility with the IBM DLC specification, all Ethernet network and broadcast addresses in the functions and data structures that are common to Ethernet and token-ring networks, use the token-ring Net headers and have swapped bit order in the addresses. The functions and data structures that are only possible on the Ethernet use the normal Ethernet Net headers and bit order. For example, DIX Ethernet frames use the Ethernet order in the receive and transmit buffer Net headers. DIR.SET.MULTICAST.ADDRESS also uses the Ethernet order.

The data types, constants and error codes mentioned in the following sections are documented in the DLCAPI.H file, which ships with Microsoft Visual C++ version 4.0, or the Win32 SDK.

API Call

The Win32 DLC services are provided by a single entry point of

ASCLAN_STATUS Acslan(PLLC_CCB pCCB, PLLC_CCB * ppBadCCB);

where:

    pCCB    - Command Control Block, defines the function type and its
              input parameters.
    pBadCCB - Returns the address of the invalid CCB, if server CCBs were
              queued together and one of them failed. The parameter may be
              NULL if the application only specifies one command.

    Return code: ASCLAN status code. The DLC error or success status is
                 always returned in the CCB status field.

The Command Control Block (CCB) defines parameters common for all DLC requests. The request-specific parameters are either in an external parameter table or in four bytes reserved for them in the Win32 CCB. For example:

// 
// LLC_CCB - the Command Control Block structure from DLCAPI.H
// 

typedef struct _LLC_CCB {
    UCHAR uchAdapterNumber;         // Adapter
    UCHAR uchDlcCommand;            // DLC command
    UCHAR uchDlcStatus;             // DLC command completion code
    UCHAR uchReserved1;             // reserved for DLC DLL
    struct _LLC_CCB* pNext;         // CCB chain
    ULONG ulCompletionFlag;         // used in command completion
    CCB_PARMS u;                    // parameters
    HANDLE hCompletionEvent;        // event for command completion
    UCHAR uchReserved2;             // reserved for DLC DLL
    UCHAR uchReadFlag;              // set when special READ CCB chained
    USHORT usReserved3;             // reserved for DLC DLL
} LLC_CCB, *PLLC_CCB;

where:

    uchAdapterNumber - Network adapter number, 0, 1, 2.. 255
    uchCommand       - Function code, mostly compatible with IBM spec.
    uchDlcStatus     - DLC return status
    pNext            - Used to chain CCBs. Several Canceled commands or
                       completed TRANSMIT CCBs may be chained with this
                       field. It can also provide a READ command to
                       complete the current command.
    ulCompletionFlag - Optional flag set by READ when the command is
                       completed. The DLC API driver does not use the
                       parameter if it was set to 0 before the call.
    u                - Function-dependent parameter table.
    hCompletionEvent - Event handle which can be used to wait for command
                       completion. This must be created with the Win32 API
                       CreateEvent.
    uchReadFlag      - This should be set if a READ CCB is chained in this
                       command.

Most DLC commands may only be executed synchronously, with the status and the optional output parameters being returned immediately. The network I/O commands may be executed sychronously or asynchronously.

Command Completion

The NT DLC command can be completed in two ways:

Waiting on the event handle defined in the CCB.

-or-

Setting a completion flag in the CCB and reading the command completion with the READ command.

The method of polling on the status code in the CCB is unreliable in Windows NT and should not be used. The status field may be updated before the other returned parameters have been set, and should not be polled for completion.

Ethernet Type Support

The DLC API specification for the direct interface only allows data encapsulated in 802.5 or 802.3 frames. This makes it impossible to receive other Ethernet types. The new direct station ids 0004H and 0005H can receive all Ethernet types.

Users may also specify a specific Ethernet frame type in the new parameter field of the DIR.OPEN.STATION command. The direct station then only receives frames which have that specific Ethernet frame type. The received frame type is returned in the DLC header field of the non-contiguous frame header.

Received DIX Ethernet frames always include the frame padding, if the frame length is less than 64 bytes.

The Ethernet NET header is used whenever an application is sending or receiving Ethernet type frames.

Buffer Management

The buffer allocation and management methods in the Win32 DLC API are quite different from the DOS or OS/2 1.xx methods. The buffer headers, however, are as defined in the specifications.

The DLC buffers of Win32 are allocated from a single virtual memory block and the DLC driver defines the buffer segment sizes. For each received frame it allocates a minimal combination of 256, 512, 1024, 2048 and 4096 buffer segments (at most one of each size). The algorithm minimizes the non-paged memory needed for different buffer segment headers (DLC headers, internal segment header and MDL). It also allocates the minimal number of buffers for the received frames. Applications may request the fixed size buffers or an optimal number of buffers for a frame size.

The DLC buffers pools are dynamically expanded from the application-specified minimum size threshold if the size of free buffers is less than this value during a READ, DLC.FLOW.CONTROL or BUFFER.GET command. The buffer pool cannot, however, be increased beyond its maximum size.

An application may use its own transmit buffers or send data directly from the buffer pool. Because the DLC driver locks all the transmit buffers that are not in the buffer pool, applications should avoid using too many small transmit buffers.

Use the following methods to obtain better performance:

DLC API Functions

The following section itemizes the functions in the Win32 DLC set that are different from the CCB2 interface of the IBM LAN Technical Reference. Other functions are identical to the specification, except that pointers are 32-bit flat pointers.

1. BUFFER.CREATE

This function creates a new DLC buffer pool and returns its handle. All SAP stations and the direct station on the same adapter number use the same buffer pool. The same buffer pool may also be shared by different adapters owned by the same application. For example:

   typedef struct _LLC_BUFFER_CREATE_PARMS {
       OUT HANDLE  hBufferPoolHandle;
       IN PVOID        pBuffer;
       IN ULONG        cbBufferSize;
       IN ULONG        cbMinimumSizeThreshold;
   } LLC_BUFFER_CREATE_PARMS, *PLLC_UFFER_CREATE_PARMS;

LLC_BUFFER_CREATE_PARMS Structure

    hBufferPoolHandle ? Handle of the created buffer pool. This handle can
                        be used by the same process to share a single
                        buffer pool by several adapter contexts. This
                        handle may be given in the extended parameter
                        table of another DIR.OPEN.ADAPTER command.

    pBuffer           ? The application must provide this buffer to
                        the DLC buffer manager. The buffer may be static
                        or allocated from the heap. The buffer manager
                        allocates all DLC buffers from this virtual
                        buffer. This buffer area must not be used for
                        anything else.

    cbBufferSize      ? The total size of the buffer. This must be the
                        maximum size of the buffer pool. 0x2000 (hex) is
                        the minimum buffer size, because the buffer manager
                        only uses the full 4K pages.

    cbMinimumSizeThreshold ? The buffer manager tries to keep at least this
                             much free space in the buffer pool. The
                             buffer pool is extended by READ, BUFFER.GET
                             and DLC.FLOW.CONTROL commands. This
                             parameter should be big enough to hold all
                             data received between two sequential READ
                             commands. The buffer manager also releases
                             (unlocks) the extra buffer space after a
                             constant time.

All buffer segments in a DLC buffer pool are allocated from a single virtual memory block. Its size is also the maximum size of the buffer pool. This command returns an error if it cannot lock the given minimum buffer size. At least one adapter must be open before buffer pool can be created. The RECEIVE command fails if a buffer pool has not been defined for the adapter.

Windows/Windows NT DLC applications should very carefully select the total and minimum buffer pool sizes, because the memory manager of Windows/Windows NT has a dynamic quota available pages for each process. A DLC application may not work at all if it tries to allocate too large a buffer pool in low memory conditions. The transmit commands using buffers outside of the buffer pool may fail for the same reason.

DLC applications should minimize the time that the buffers returned by the data receive or by the BUFFER.GET request are held, because those buffers are still locked in the memory. DLC applications should also be able to recover if the DLC device driver runs out of the buffers, because it may not be able to add new memory to the buffer pool (if the entire system is running out of memory).

In any case, there always is at least the minimal free buffer space if the BUFFER.CREATE request has been completed successfully.

2. BUFFER.FREE

This request returns one or more buffers to the adapter's pool. It cannot be used to add new virtual memory blocks to the existing pool. The buffers must have been obtained with BUFFER.GET

3. BUFFER.GET

This command returns the requested buffers. The command can be used both to get several buffers of the same size or to get an optimal set of buffers for the given frame size.

In the first case below, cBufferToGet includes the number the returned buffers and cbBufferSize is the size of the returned buffer segment. The size is rounded up to next available buffer size (256, 512, 1024, 2048 or 4096).

In the second case the number of returned buffers must be 0 and cbBufferSize includes the size of the actual frame that is copied to buffers. The buffer manager returns enough buffers to contain the whole frame including its buffer headers. cbBuffersLeft returns the size of free locked memory in 256 bytes blocks or 65536 if the actual size is above 1MB. For example:

   typedef struct _LLC_BUFFER_GET_PARMS {
       IN  USHORT          usReserved;
       IN  USHORT          cBuffersLeft;
       IN  USHORT          cBufferToGet;
       IN  USHORT          cbBufferSize;
       OUT PLLC_BUFFER     pFirstBuffer;
   } LLC_BUFFER_GET_PARMS, *PLLC_BUFFER_GET_PARMS;

4. DLC.FLOW.CONTROL

A Windows NT application should issue this command immediately when a link station enters a local busy state. The driver clears the busy state when there are enough free buffers to receive more frames in the buffer pool.

5. DIR.CLOSE.ADAPTER

This command closes the adapter logically, release all its resource and cancels any outstanding commands. Open SAP or link stations are reset prior to completion of this command. The canceled commands return error code 0x62. If the application has previously set bits of the functional address, the adapter support software resets the bits.

6. DIR.INITIALIZE

This command resets the network adapter. Only the BRING_UPS field in the parameter block is returned. All other fields are reserved. For security reasons, the command resets the adapter physically only if the adapter was not functioning normally when the command was issued.

See the ?IBM LAN Technical Reference? for further information.

7. DIR.INTERRUPT

This command does not do anything in Windows NT.

8. DIR.OPEN.ADAPTER

This command must be completed successfully before any network communication can start. It does not usually open the physical adapter, but results in a logical open. This is because multiple applications and drivers may be accessing the same DLC driver.

Applications may have to provide the security descriptor parameter in the parameter table.

All fields specific to the IBM Token Ring hardware or the DOS NETBIOS interface have been removed from the parameter tables. The DOS security and direct interface buffer pool parameters are also obsolete.

The bring-up diagnostic result is returned (it is not defined in CCB1). Otherwise, the CCB1 parameter tables and parameters are used.

DIR_OPEN_ADAPTER_PARMS Structure

   typedef struct _LLC_DIR_OPEN_ADAPTER_PARMS {
       PDIR_ADAPTER_PARMS  pAdapterParms;
       PLLC_EXTENDED_ADAPTER_PARMS pExtendedParms;
       PLLC_PARMS          pDlcParms;
       PVOID               Reserved1;
   } LLC_DIR_OPEN_ADAPTER_PARMS, *PLLC_DIR_OPEN_ADAPTER_PARMS;

       pExtendedParms  ?    Pointer to new open parameters.
       pAdapterParameters ? Pointer to adapter parameter table.
       pDlcParameters     ? Pointer to DLC parameter table, see IBM
                            documentation for further information.

EXTENDED_ADAPTER_PARMS Structure

   typedef struct _LLC_EXTENDED_ADAPTER_PARMS {
       HANDLE              hBufferPoolHandle;
       PVOID               pSecurityDescriptor;

   } LLC_EXTENDED_ADAPTER_PARMS, *PLLC_EXTENDED_ADAPTER_PARMS;

       hBufferPoolHandle   ? Buffer pool handle returned by a
                             BUFFER.CREATE command.
       pSecurityDescriptor ? Windows/Windows NT security descriptor used by
                             all open commands on the adapter.

See ?IBM Local Area Network Technical Reference? for further information.

9. DIR.OPEN.DIRECT

The fields that define the buffer pool in the IBM specification are not used. Windows NT provides an extension to receive frames of specific Ethernet types using the direct station when the usEthernetType field has a valid Ethernet type (>1500).

The protocol type mask, match and offset can be used to receive frames for a particular subprotocol type or socket. The optional parameters are ignored if the ulProtocolTypeMask is zero. The offset defines the distance of the protocol type from the beginning of the protocol header (offset 14 in the frame header). The mask is used to bitwise AND the data and the result must be equal to the match.

That is, the packet is received whenever:

    (*(PULONG)((PUCHAR)pFrame + 14 + offset) & mask) == match)

   typedef struct _LLC_DIR_OPEN_DIRECT_PARMS {
       IN  USHORT          usReserved[4];
       IN  USHORT          usOpenOptions;
       IN  USHORT          usEthernetType;
       IN  ULONG           ulProtocolTypeMask OPTIONAL;
       IN  ULONG           ulProtocolTypeMatch OPTIONAL;
       IN  USHORT          usProtocolTypeOffset OPTIONAL;
   } LLC_DIR_OPEN_DIRECT_PARMS, *PLLC_DIR_OPEN_DIRECT_PARMS;

10. DIR.READ.LOG

All parameter fields of this function may not be supported by some network adapters because the implementation of error counters is optional in NDIS 3.0. These fields are supported by Microsoft-provided NDIS 3.0 drivers, including IBM Token Ring.

11. DIR.SET.FUNCTIONAL.ADDRESS

On Ethernet, each bit set in the token-ring functional addresses causes a mapping to an Ethernet-multicast address. Please see the ?IBM LAN Technical Reference? for more information.

12. DIR.SET.MULTICAST.ADDRESS

This command sets a 48-bit multicast address for the currently open DLC adapter context. A zero value removes the previous multicast address. This command is only supported on Ethernet networks and is an alternative to the DIR.SET.GROUP.ADDRESS function that can only set the lowest 32 bits of a multicast address. This operation may fail if the Ethernet adapter does not have a multicast address available.

The bit order of the multicast address is the normal Ethernet bit order.

13. DIR.SET.GROUP.ADDRESS

Only one application may set a group address for a token ring adapter. This operation may also fail if the Ethernet adapter does not have available multicast addresses.

14. READ

As in the IBM specification, except that all the fields in the parameter table are naturally aligned. The not contiguous buffer is also aligned. The data and the optional header begin at offset 64.

15.READ.CANCEL

As in the CCB2 specification, except that the pParameter field in the CCB of the command is used to specify the CCB pointer of the canceled command.

16. RECEIVE

The receive option 5 (BREAK) is not supported.

17. RECEIVE.CANCEL

Uses the pParameter field of the CCB to point to the CCB pointer of the canceled command.

Unsupported DOS Commands

The following DOS DLC commands are not supported by Windows NT:

WOW/DOS DLC

DLC services are made available to DOS applications running in the DOS/WOW environment on Windows NT. The API is directly compatible with existing IBM emulators using the DOS DLC API in DOS.

Windows applications that communicate with DOS terminate-and-stay-resident (TSR) applications to access DLC services should also work unmodified on WOW.

REFERENCES

Additional query words:
Keywords          : kbnetwork kbAPI kbDLC kbNTOS350 kbSDKPlatform kbWinOS95 kbGrpNet 
Issue type        : kbinfo

Last Reviewed: January 1, 1999