Important: |
This is retired content. This content is outdated and is no
longer being maintained. It is provided as a courtesy for
individuals who are still using these technologies. This content
may contain URLs that were valid when originally published, but now
link to sites or pages that no longer exist. |
Microsoft Corporation
July 2000
Summary:This white paper describes the
implementation of the Network Driver Interface Specification (NDIS)
in Microsoft Windows CE Platform Builder 3.0. (36 pages)
Contents
Introduction
Windows CE Implementation of NDIS
Differences Between Windows CE and Windows
NT Implementations
What Is NDIS?
Windows CE Communications
Architecture
Windows CE Miniport-Driver
Architecture
Protocol Drivers
Installing Network Adapter Drivers
IrDA Support
NDIS Token Ring Support
NDISWAN Support
DMA
Introduction
This white paper describes the implementation of the Network
Driver Interface Specification (NDIS) in Microsoft Windows CE
Platform Builder 3.0. NDIS refers to the interface by which one or
more local area network (LAN) and wide area network (WAN) adapter
drivers communicate with one or more underlying network adapters,
one or more overlying protocol drivers, one or more miniport
drivers, and the operating system (OS). The Windows CE 3.0
communications architecture provides support for NDIS version 4.0.
Windows CE 3.0 offers an array of new and improved NDIS
features.
Windows CE 3.0 supports new features that include intermediate
drivers that expose an NDIS protocol-driver interface, NDISWAN,
Token Ring, a layered miniport-driver structure, and an improved
structure for the binding of adapters. This white paper provides a
brief outline of each one of these features. It also describes how
the NDIS implementation in Microsoft Windows NT version 4.0 differs
from the NDIS implementation in Windows CE 3.0, and it provides
guidelines for programmers on how to handle these differences when
they are writing NDIS drivers for Windows CE.
Windows CE Implementation of NDIS
Windows CE 3.0 supports NDIS 4.0, which also is implemented in
Windows NT 4.0. The NDIS implementation in both Windows CE and
Windows NT 4.0, with some minor exceptions, is source-code
compatible. NDIS miniport drivers are fully portable, and you
should be able to port an existing miniport driver from Windows NT
to a Windows CE-based device. You also can create a customized
miniport driver for a Windows CE-based device by following the
steps that are provided in the Windows CE driver development kit
(DDK) on how to write a miniport driver. Because Windows CE does
not require backward compatibility with legacy drivers, it does not
support full NIC (network interface card) drivers or monolithic
network drivers.
Windows CE 3.0 features a built-in tool for testing NDIS
miniport drivers. This testing tool, which is called NDISTest,
allows you to perform functionality, stress, and performance tests
on NDIS miniport drivers. NDISTest is implemented as a protocol
driver and ships with a set of LAN test scripts. For more detailed
information on NDISTest and how to use it, consult the Windows CE
Device Driver Test Kit (DDTK).
The NDIS implementation in Windows CE 3.0 includes some new and
improved features, such as support of Token Ring and NDISWAN, and
full support of intermediate drivers. The new dynamic
adapter-binding feature that is implemented in Windows CE 3.0
provides a more flexible system of managing the binding and
unbinding of network adapters.
The following list shows the key features of NDIS support in
Windows CE 3.0:
- Portability of drivers between platforms that support NDIS.
- Support for network adapter miniport drivers.
- Support for intermediate (including layered) and upper-level
drivers.
- Support for Ethernet (802.3), Token Ring (802.5), and Infrared
Data Association (IrDA) medium types.
- Support for the WAN medium type.
- Support for ISA, PCI, and PC Card devices.
- Dynamic binding of adapters, and support for Plug and Play.
- Support for multiple network adapters that are bound to the
same protocol.
Differences Between Windows CE and
Windows NT Implementations
Although the NDIS implementation in Windows CE and Windows NT is
source-code compatible, and although each OS, with a few
exceptions, supports identical APIs, there are some differences in
the implementations of NDIS between Windows CE and Windows NT:
- Windows NT and Windows CE share the same source code for
miniport drivers, but each OS uses a different compilation method.
In Windows NT, miniport drivers are compiled as system (.sys)
files. Because Windows CE does not support system files, you must
compile a miniport driver as a dynamic link library (DLL). To
compile a miniport driver as a DLL, the driver must export the
DriverEntryfunction in its module definition (.def) file.
DriverEntryinitializes the driver and calls other functions
in the DLL to perform platform-specific initializations.
- Windows CE does not support input (.inf) files for dynamic
installation and configuration of NDIS miniport drivers.
- Windows CE does not provide built-in support for Direct Memory
Access (DMA) functionality. However, developers can implement DMA
code in a miniport driver for a specific combination of a Windows
CE-based platform and a network adapter. This white paper provides
a
code sampleon how to implement DMA
operations in a miniport driver for Windows CE.
- Windows CE does not support contiguous physical memory
allocations. This memory must be allocated in a platform-specific
way.
- The NDIS wrapper interface (Ndis.dll) that is supported in
Windows CE does not make any calls to the multipacket
sendhandler in the miniport driver.
- The I/O port address that is returned from the
NdisMRegisterIoPortRangefunction represents a 32-bit virtual
address in Windows CE and should be treated as a 32-bit value.
Because Windows CE does not use the lower 64 KB region of the I/O
address space, you should not use 16-bit values for I/O port
addresses. Many Windows CE devices emulate I/O ports on top of
mapped memory.
- The Windows CE implementation of NDIS does not provide access
to the PCMCIA attribute memory. A driver instead must use the PC
Card Services functions to read the card information.
- In Windows CE, the IrDA protocol driver supports only a single
statically bound adapter.
- The
NdisSendPacketsfunction is not supported in Windows CE.
What Is NDIS?
NDIS describes the interface by which one or more network
adapter drivers communicate with one or more underlying network
adapters, with one or more overlying protocol drivers, with one or
more miniport drivers, and with the OS. NDIS provides a fully
abstracted interface for network adapter driver development.
NDIS provides a pair of abstraction layers that are used to
connect network drivers to an overlying protocol stack, such as
Transmission Control Protocol/Internet Protocol (TCP/IP) or IrDA,
and an underlying network adapter. NDIS performs a set of external
functions for network adapter drivers, such as registering and
intercepting hardware interrupts and communicating with underlying
network adapters.
The Windows library (Ndis.dll) provides a fully abstracted
interface to which you can write a customized network adapter
driver for Windows CE. This library exports all of the Windows CE
kernel-mode functions that are required for driver development. The
Ndis.dll file also maintains binding and state information about
all of the underlying network adapter drivers. NDIS supports the
following network components:
- A network adapter driver that receives a network packet from an
upper-layer driver for transmission on the network through an
underlying network adapter.
- A network adapter driver that accepts a network packet from an
underlying network adapter and passes the packet up to an
upper-layer driver.
- An upper-layer driver that sets specific configuration
parameters for a network adapter or a network adapter driver.
- An upper-layer driver that queries a network adapter driver for
specific configuration data from an underlying network adapter or
from the network adapter driver.
- A network adapter driver that informs an overlying driver
asynchronously of changes in the status of the network or of the
network adapter.
Figure 1 shows the general NDIS architecture that is implemented
in Windows CE-based platforms.
Figure 1. General NDIS architecture in Windows CE-based
platforms
The NDIS interface is located between an upper-level protocol
driver (such as the TCP/IP protocol driver on the top of the
communications architecture), the intermediate and miniport drivers
in the middle of the communications architecture, and a network
adapter at the bottom of the communications architecture. Because
NDIS provides an interface to the upper and lower edges of a
miniport driver, the NDIS interface often is referred to as the
NDIS Wrapper. The NDIS Wrapper provides the operating environment
for drivers that use NDIS; its components are located in the
Ndis.dll file.
Windows CE Communications
Architecture
One of the key features of Windows CE-based devices is their
ability to communicate with other devices. Windows CE supports two
basic types of communication: serial communication and
communication over a network. Most devices feature built-in
communications hardware, such as a serial port or an IR
transceiver. The NDIS implementation in Windows CE supports the
following communications media: Ethernet (802.3), Token Ring
(802.5), IrDA, and WAN.
Figure 2 outlines the communications architecture of the Windows
CE OS.
Figure 2. Communications architecture of the Windows CE
operating system
In the Windows CE communications architecture, the NDIS
interface is located below the IrDA, TCP/IP, and Point-to-Point
Protocol (PPP) protocol drivers. The NDIS Wrapper presents an
interface to the upper and lower edges of a miniport driver. To an
upper-level driver, such as the TCP/IP protocol driver, the NDIS
interface looks like a miniport driver. To the miniport, the NDIS
interface looks like an upper-level protocol driver. At the bottom
of the communications architecture, the NDIS interface functions as
a network adapter driver that interfaces directly with the network
adapter at the lower edge. At the upper edge, the network adapter
driver presents an interface to allow upper layers to send packets
on the network, handle interrupts, reset or halt the network
adapter, and query or set the operational characteristics of the
driver.
Windows CE Miniport-Driver
Architecture
Miniport drivers directly manage network adapters that are
installed on a device. At the lower edge, miniport drivers use NDIS
to "talk" to the adapter hardware. At the upper edge, miniport
drivers present an interface to allow protocol drivers to configure
the adapter, as well as to send and receive packets over the
network.
Windows CE 3.0 supports WAN miniport drivers. A WAN miniport
provides protocol drivers (for example, PPP) access to a WAN
interface.
Windows CE currently supports miniport drivers for the following
medium types:
- Ethernet (802.3)
- Token Ring (802.5)
- IrDA
- WAN
Writing a Miniport Driver
When you write an NDIS miniport driver, you should ensure that
the driver is easily portable across all of the other platforms
that support the NDIS 4.0 interface. Ideally, porting from one
hardware platform to another will require only recompilation with a
system-compatible compiler.
To guarantee cross-platform portability, you should avoid
calling OS-specific functions and, instead, use the NDIS
equivalents of such calls. NDIS exports a wide array of functions
for writing drivers, so that it is not necessary to make calls to
the OS directly.
You should write your miniport driver in the C language by using
the ANSI C standard. Make sure not to include any calls to C
run-time library functions in your driver code, instead of
NDIS-provided functions. Kernel mode on Windows NT does not allow
the use of floating-point operations; so, if you use floating-point
calls in your driver, the driver might work only on Windows CE. If
you must include platform-specific features in your driver, make
sure to encapsulate the code between the
#ifdefand
#endifstatements.
Windows CE 3.0 ships with several samples of driver code. Driver
developers should consult this sample code to gain a better
understanding of the concept of writing an NDIS miniport driver for
Windows CE. The driver sample code that is shipped with Windows CE
3.0 includes the following:
- NE2000 ISA, PCI, and PC Card drivers
- Proxim Wireless Ethernet PC Card driver
- FAST IR driver that uses the National Semiconductor chip set
For a set of detailed instructions on how to write a customized
miniport driver for Windows CE, see the Windows CE DDK.
Driver Registration and NDIS Library
Initialization
All NDIS miniport and intermediate drivers must provide a
DriverEntryfunction. When a miniport driver is loaded, NDIS
calls
DriverEntry, which creates an association between the
miniport driver and the NDIS library, and registers the miniport
driver with NDIS.
The
DriverEntryfunction requires the following syntax:
NTSTATUS DriverEntry( IN PDRIVER_OBJECT
pDriverObject_, IN PUNICODE_STRING pRegistryPath_);
The following parameters are passed into the
DriverEntryfunction:
- A pointer to the driver object, which was created by the I/O
system.
- A pointer to the registry path, which specifies where
driver-specific parameters are stored.
The
DriverEntryfunction must call the
NdisMInitializeWrapperfunction, and then the
NdisMRegisterMiniportfunction.
DriverEntryfirst calls
NdisMRegisterMiniportwith the parameters that are passed to
DriverEntry, which returns a wrapper handle.
DriverEntrythen passes the handle to
NdisMRegisterMiniport.
Windows CE does not support the common network .inf file format
for dynamic installation and registry configuration of miniport
drivers that are used in Windows NT. Instead, Windows CE uses the
registry for dynamic installation and binding of device drivers.
Therefore, your driver installation program must make sure to
create the appropriate registry settings for your miniport driver
in the Windows CE registry.
Figure 3 shows the process for registering a miniport driver and
initializing the NDIS library.
Figure 3. Registering a miniport driver and initializing the
NDIS library
Layered Miniport Drivers
The NDIS architecture that is implemented in Windows CE also
features intermediate drivers. An NDIS intermediate driver does not
use NDIS functions to control adapter hardware. Instead, it sits on
top of another driver, such as the serial driver. The "layered"
driver model represents a special kind of intermediate driver that
sits on top of an NDIS miniport driver. Windows CE 3.0 now also
supports a layered driver architecture. A layered miniport driver
exposes a miniport-driver interface to the overlying protocol
driver and a protocol-driver interface to the underlying miniport.
In a layered miniport-driver structure, the protocol driver "talks"
to a miniport driver that is at the bottom of the layered miniport
driver. A layered miniport driver exports
MiniportXxxfunctions at its upper edge and
ProtocolXxxfunctions at its lower edge.
Layered miniport drivers are used to filter out certain packets
or to perform other special functions, such as decryption and
encryption of data. To prevent packets from looping back between
the layered driver and the miniport driver, the layered driver
should set the
NDIS_FLAGS_DONT_LOOPBACKpacket flag by calling the
NdisSetPacketFlagsfunction.
A layered miniport driver calls the
NdisOpenAdapterfunction to open and establish a binding to
an underlying adapter driver or intermediate NDIS driver that
exports a set of
MiniportXxxfunctions at its upper edge. A layered miniport
driver exports the
MiniportSetInformationand
MiniportQueryInformationfunctions to process
Setand
Queryrequests from a higher-level driver, and to pass them
on to a lower-level driver.
NdisMXxxfunctions may be called only when the driver is
running in a miniport-driver context. If the function of a layered
miniport driver is not in a miniport-driver context, make sure to
use the
NdisIMSwitchToMiniportfunction before you call any
MiniportXxxfunctions. Use the
NdisIMRevertBackfunction to leave the miniport-driver
context. All of the miniport-driver handler functions that are
registered with NDIS will be called by NDIS within a
miniport-driver context.
Figure 4 shows the layered NDIS miniport-driver architecture
that is supported in Windows CE 3.0.
Figure 4. Layered NDIS miniport-driver architecture supported in
Windows CE 3.0
Table 1 lists a set of new NDIS library functions that are
supported in Windows CE. These functions apply to intermediate
drivers.
Table 1. New NDIS library functions that are supported in
Windows CE
Function
|
Description
|
NdisIMDeInitializeDeviceInstance
|
Calls the
MiniportHaltfunction of an NDIS intermediate driver to tear
down the virtual network adapter of the driver. |
NdisIMGetDeviceContext
|
Allows the
MiniportInitializefunction of an NDIS intermediate driver to
access the device context area that is allocated by its
ProtocolBindAdapterfunction. |
NdisIMInitializeDeviceInstance
|
Calls the
MiniportInitializefunction of an NDIS intermediate driver to
set up the virtual network adapter of the driver for I/O operations
on an underlying network adapter driver to which the intermediate
driver is bound. |
NdisIMInitializeDeviceInstanceEx
|
Calls the
MiniportInitializefunction of an NDIS intermediate driver to
initialize the virtual network adapter of the driver and,
optionally, to set up state information about the virtual network
adapter of the driver for subsequently bound protocols. |
NdisIMRegisterLayeredMiniport
|
Registers an intermediate driver's
MiniportXxxentry points and name with the NDIS library when
the driver initializes. |
Any NDIS intermediate or layered miniport driver that exports
both
MiniportXxxand
ProtocolXxxfunctions usually sets up a characteristics
structure and calls the
NdisIMRegisterLayeredMiniportfunction from its
DriverEntryfunction after
DriverEntrycalls the
NdisMInitializeWrapperfunction. This structure is copied in
the
NdisIMRegisterLayeredMiniportrequest to the internal storage
of the NDIS library. Thus, once it has registered, such a driver
cannot change its handler functions. An intermediate driver can
call the
NdisMRegisterMiniportfunction, instead of the
NdisIMRegisterLayeredMiniportfunction, if it is prepared for
an immediate call to the
MiniportInitializefunction.
NDIS Driver Upper-Edge Functions
NDIS intermediate drivers and layered miniport drivers export a
subset of
MiniportXxxfunctions and a
DriverEntryfunction that fulfills the initialization-time
requirements of the NDIS library. NDIS miniport drivers, as well as
NDIS intermediate drivers, export NDIS upper-edge functions.
The following table lists the NDIS driver upper-edge functions
that are supported in Windows CE.
Table 2. NDIS driver upper-edge functions supported in Windows
CE 3.0
Function
|
Description
|
DriverEntry
|
Is called by the OS to activate and initialize the
network adapter driver. |
MiniportCheckForHang
|
Checks the internal state of the network
adapter. |
MiniportDisableInterrupt
|
Disables the network adapter from generating
interrupts. |
MiniportEnableInterrupt
|
Enables the network adapter to generate
interrupts. |
MiniportHalt
|
De-allocates and de-registers resources that are
used for the network adapter, and halts the network adapter. |
MiniportHandleInterrupt
|
Is called to complete interrupt-driven I/O
processing; this is a deferred processing function. |
MiniportInitialize
|
Initializes the network adapter. |
MiniportISR
|
Runs at a high priority as the interrupt service
function for the network adapter. |
MiniportQueryInformation
|
Queries the capabilities and current status of the
miniport driver. |
MiniportReconfigure
|
Currently, the NDIS library never calls this
function; but a
MiniportInitializefunction can call a
MiniportReconfigurefunction as an internal driver
function. |
MiniportReset
|
Issues a hardware reset to the network
adapter. |
MiniportReturnPacket
|
Receives a packet from an upper layer that
previously was passed up by a call to the
NdisMIndicateReceivePacketfunction. |
MiniportSend
|
Transmits a packet though the network adapter onto
the network. |
MiniportSetInformation
|
Changes (sets) information about the miniport
driver or its network adapter. |
MiniportTransferData
|
Copies the contents of a packet that is received by
the network adapter into a given packet buffer. |
MiniportWanSend
|
Transmits a packet though the network adapter onto
the network. WAN miniport drivers use this function instead of the
MiniportSendfunction. |
Windows CE does not support Windows NT NDIS IRQ lines.
NDIS Protocol Driver Lower-Edge Functions
NDIS protocol drivers and layered miniport drivers also export a
set of lower-edge functions that share "Protocol" as a common
prefix. All of the NDIS driver functions that have this prefix have
been given metanames that describe their respective basic
functionalities in the references that follow.
NDIS-defined driver functions can have any name that the driver
writer chooses. For easy debugging, most system-supplied protocols
substitute a driver-specific prefix for the "Protocol" prefix that
is used in this documentation.
The following table lists the NDIS driver lower-edge functions
that are supported in Windows CE.
Table 3. NDIS driver lower-edge functions supported in Windows
CE 3.0
Function
|
Description
|
ProtocolBindAdapter
|
Is a required driver function to support Plug and
Play. |
ProtocolCloseAdapterComplete
|
Completes the processing for an unbinding operation
for which the
NdisCloseAdapterfunction returned
NDIS_STATUS_PENDING. |
ProtocolOpenAdapterComplete
|
Completes the processing of a binding operation for
which the
NdisOpenAdapterfunction returned
NDIS_STATUS_PENDING. |
ProtocolReceive
|
Is a required driver function in NDIS protocols
that bind themselves to connectionless network adapter drivers;
this function determines whether a received network packet is of
interest to the protocol's client(s) and, if so, copies the
indicated data and, possibly, calls the
NdisTransferDatafunction to retrieve the rest of the
indicated network packet. |
ProtocolReceiveComplete
|
Completes post-processing of one or more of the
preceding receive indications from a network adapter driver. |
ProtocolReceivePacket
|
Processes receive indications that are made by
underlying connectionless network adapter driver(s) that call the
NdisMIndicateReceivePacketfunction either with packet
arrays, because the underlying driver supports multipacket receive
indications, or with individual packets that have out-of-band
information associated with them. A call to the
ProtocolReceivePacketfunction also can occur as a result of
loop back. |
ProtocolRequestComplete
|
Completes the processing of a protocol-initiated
query or set for which the
NdisRequestfunction returned
NDIS_STATUS_PENDING. |
ProtocolResetComplete
|
Completes the processing of a protocol-initiated
reset operation for which the
NdisResetfunction returned
NDIS_STATUS_PENDING. |
ProtocolSendComplete
|
Completes the processing of a protocol-initiated
sendoperation that previously was passed to the
NdisSendfunction, which returned
NDIS_STATUS_PENDING. |
ProtocolStatus
|
Handles status-change notifications that are raised
by an underlying connectionless network adapter driver or by
NDIS. |
ProtocolStatusComplete
|
Completes a status-change operation that was
initiated when the underlying driver called the
NdisMIndicateStatusor the
NdisMCoIndicateStatusfunction. |
ProtocolTransferDataComplete
|
Is a required driver function if the protocol might
bind itself to an underlying connectionless network adapter driver
that does not indicate full-packet receives by using the
NdisMIndicateReceivePacketfunction. The
ProtocolTransferDataCompletefunction completes the
processing of a protocol-initiated transfer-data request for which
the
NdisTransferDatafunction returned
NDIS_STATUS_PENDING. |
ProtocolUnbindAdapter
|
Is a required driver function to support Plug and
Play. |
Miniport-Driver Registration
An NDIS miniport driver must register its
MiniportXxxinterface functions within its
DriverEntryfunction. A layered miniport driver must register
its
ProtocolXxxfunctions also. To register its
MiniportXxxfunctions, the driver must make one of two
possible NDIS registration calls: either
NdisMRegisterMiniport(for non-layered miniport drivers) or
NdisIMRegisterLayeredMiniport(for layered miniport drivers).
Both of these calls export the MiniportXxx functions of the driver.
The function that is called determines whether the intermediate
driver or the NDIS controls when the intermediate driver
initializes as a miniport driver and, as a result, when the
intermediate driver's virtual network adapter(s) is (are) made
available for requests from higher-level drivers.
After the driver calls the
NdisMRegisterMiniportfunction, NDIS calls the
MiniportInitializefunction of the driver to request
initialization of its virtual network adapter(s).
Protocol Drivers
Windows CE 3.0 provides protocol drivers for TCP/IP, PPP, and
IrDA. A protocol driver exports a set of
ProtocolXxxfunctions at its lower edge, then communicates
with NDIS to send and receive network packets, and to bind to an
underlying miniport network-adapter driver or intermediate NDIS
driver that exports a
MiniportXxxinterface at its upper edge.
Protocol drivers that communicate with underlying NDIS drivers
call NDIS library functions to send and receive packets. To send a
packet to an underlying NDIS driver, a protocol driver must call
the
NdisSendfunction. Unlike Windows NT 4.0, Windows CE 3.0 does
not support the
NdisSendPacketsfunction, which allows for multiple packets
to be sent to underlying drivers. To forward a request to the
underlying driver that it query the capabilities or status of its
network adapter, or that it set the state of its network adapter, a
protocol driver must call the
NdisRequestfunction.
Windows CE NDIS protocol drivers are exposed to applications
through the Windows Sockets (Winsock) API. The interface between a
protocol driver and Winsock is private. Figure 5 shows the NDIS
protocol-driver architecture that is supported in Windows CE.
Figure 5. NDIS protocol-driver architecture supported in Windows
CE
In the Windows CE protocol-driver architecture, a protocol
driver communicates with the overlying Winsock APIs through a
private interface. The NDIS protocol driver uses the NDIS interface
to communicate with the underlying miniport driver and bind to the
network adapter.
Protocol-Driver Initialization
NDIS protocol drivers are loaded through the registry. You must
set the registry values for the following registry key:
HKEY_LOCAL_MACHINE\Drivers\BuiltIn\MyDriver. This key
commonly is named after the customized driver, and contains the
subkeys that appear in Table 4.
Table 4. Registry subkeys for NDIS protocol-driver
initialization
Subkey
|
Contents
|
DLL
|
"Mydriver.dll" |
Order
|
dword:3 |
Keep
|
dword:1 |
Entry
|
MyDriverInitialize |
Note
Make sure to set the
Ordersubkey to a value that causes the protocol driver to
load after NDIS. That is, the
Ordervalue should be greater than that of the
Ordervalue for NDIS.
To register a protocol driver with NDIS, the driver should call
the
NdisRegisterProtocolfunction from within the
MyDriverInitializefunction.
To register a protocol driver as a stream interface driver, you
must call the
RegisterDevicefunction. For a list of the required entry
points for stream interface driver DLLs, see the Windows CE
DDK.
Dynamic Adapter Binding
Windows CE 3.0 features an inherent dynamic-adapter-handling
system that provides Plug and Play compatibility for built-in—and
removable—network adapters. Windows CE 3.0 supports a set of new
functions that allow protocol drivers greater control over the
creation of adapter instances and over adapter binding and
unbinding.
When a protocol driver registers with NDIS, the currently
registered adapters are offered to the protocol via the
BindAdapterHandlerfunction, just as if the adapters were
newly inserted PC Cards. Protocol drivers no longer require
registry keys that specify the built-in adapter instances to which
they must bind. A Plug and Play-ready protocol driver can support
dynamic binding to underlying network adapters by providing the
ProtocolBindAdapterand
ProtocolUnbindAdapterfunctions. NDIS calls the
ProtocolBindAdapterfunction of a protocol driver to notify
it that an adapter is available. The protocol can choose to ignore
this notification, or it can try to bind to the adapter by calling
the
NdisOpenAdapterfunction.
Previously, the built-in and removable network adapters featured
different binding mechanisms. For built-in adapters, the protocol
was responsible for binding to a network adapter by calling the
NdisOpenAdapterfunction according to registry settings.
TCP/IP and IrDA each had its own set of registry settings that
defined the names of the adapters to which it was to bind during
initialization. Driver developers could modify the binding process
by manipulating the registry settings for protocol drivers.
In Windows CE version 2.10 or earlier, NDIS informed the
protocol driver of the presence of a new network adapter by calling
the
BindAdapterHandlerfunction only if the network adapter was a
removable PC Card. With Windows CE 3.0, this binding mechanism
applies to built-in, as well as removable, adapters. That is, when
a protocol driver registers with NDIS, it is informed about all
current adapters via its
BindAdapterHandlerfunction.
Although driver developers no longer can control the binding
mechanism by manipulating the protocol registry settings (except
for IrDA, which statically binds to a single adapter and, thus,
does not use the
BindAdapterHandlerfunction), Windows CE 3.0 features an
alternate mechanism that enables driver developers to specify which
adapters get bound to which protocols. You can define the protocols
that an adapter is to bind to by specifying the required protocol
in the
HKLM\Comm\<adapter
Name>\Parms\ProtocolsToBindToregistry entry of the adapter.
This entry corresponds to a
MULTI_SZvalue that lists the names of all of the protocols
that should be informed about the presence of the adapter. If the
first entry is "NOT," the remaining entries will list the protocols
that should not be informed about the adapter. If this registry
entry is not set for an adapter, all of the protocol drivers will
be informed about the adapter instance, and might attempt to bind
to it.
If a Windows CE-based device has a PC Card inserted into its
PCMCIA slot, the system will not suspend automatically on idle
activity. To allow a Windows CE-based device to suspend on no user
activity, you must make the following registry entry under
HKEY_LOCAL_MACHINE:
HKEY_LOCAL_MACHINE\Comm\Cxport\NoIdleTimerReset
The TCP/IP protocol stack checks for this registry setting
during initialization. If the
NoIdleTimerResetsubkey has been entered in the registry and
set to nonzero, the system will not call the
SystemIdleTimerResetfunction. Note that when the system goes
into suspend, you will have to reinitialize all of your networking
activity; for example, you will have to obtain a new IP address.
Also, because TCP/IP checks for the registry setting during
initialization time, you must restart the device if you want to
change from one registry setting to another. Failure to set the
above registry key will result in the system not suspending.
NDIS Adapter-Binding Management
Windows CE 3.0 supports the
NdisMRebindProtocolsToAdapterfunction, which allows a
network adapter to request that it be unbound from all of the
protocol drivers to which it currently is bound, and then re-bound
to protocols, as if it were newly registered with NDIS. For
example, a wireless adapter that switches to a base station on a
subnet that is different from its current IP address can invoke
this function to cause the TCP/IP protocol stack to rerun DHCP to
obtain a new IP address for the device. This functionality
eliminates the need for the user to "pop out" a network adapter and
reinsert it in order to obtain a new address.
Plug and Play
The dynamic adapter-binding feature that is supported in Windows
CE 3.0 complies with the requirements for Plug and Play
compatibility. Plug and Play enables a computer system to recognize
hardware configuration changes automatically, and configure
attached devices with little or no user intervention. Plug and Play
allows the user to attach a new network adapter and start working
without having to configure the device manually. With Windows CE
3.0, you can unbind an adapter from a protocol driver and
subsequently rebind it without having to remove the adapter.
Windows CE support for Plug and Play differs from the Windows
2000 support for Plug and Play.
Windows CE support for Plug and Play has the following
capabilities and features:
- Automatic and dynamic recognition of installed hardware, which
includes initial system installation, in addition to response to
run-time hardware events, such as insertion or removal of cards.
- Streamlined hardware configuration in response to automatic and
dynamic recognition of hardware, which includes dynamic hardware
activation, resource arbitration, device-driver loading, drive
mounting, and so forth.
- Support for particular buses and other hardware standards that
facilitate automatic and dynamic recognition of hardware and
streamlined hardware configuration, which includes Plug and Play
PCMCIA, PC Card/CardBus, USB, and 1394. Support also includes
promulgation of standards, and advice on how hardware should
behave.
- An orderly Plug and Play framework in which driver writers can
operate, which includes infrastructure such as APIs, kernel-mode
notifications, executive interfaces, and so forth.
Note that Plug and Play operation does not require Plug and Play
hardware. To the degree that it is possible, the first two items
that are listed above apply to legacy hardware, as well as to Plug
and Play hardware. In some cases, orderly enumeration of legacy
devices is not possible, because the detection methods are
destructive or inordinately time-consuming.
The primary impact that Plug and Play support has on protocol
stacks is that network interfaces can connect and disconnect at any
time. The Windows CE TCP/IP stack and related components have been
adapted to support Plug and Play.
Windows CE Plug and Play is transparent to the miniport drivers.
When the user attaches a network adapter, a miniport driver is
automatically installed, loaded, and bound. When the network
adapter is removed, the miniport driver is unbound, shut down, and
unloaded. To implement Plug and Play on a Windows CE-based system,
you must set the
DriverEntryfunction to "init." All of the other
miniport-driver initialization code should be set to "page," as it
might be used after system initialization. The Windows NT DDK
provides the standard registry keywords that can be used for Plug
and Play.
Miniport drivers for network adapters require a
HKEY_LOCAL_MACHINE\Drivers\PCMCIA\Plug and Play ID\registry
key. This key typically is named after the Plug and Play ID of the
network adapter, but setting this key is not a requirement. Table 5
shows the subkeys that are contained in the key:
Table 5. Subkeys contained in network adapter registry key
Subkey
|
Contents
|
DLL
|
The literal value Ndis.dll. |
Prefix
|
The literal value NDS. |
Miniport
|
The name of the miniport driver for the network
adapter, which corresponds with the name of the registry key that
is within
HKEY_LOCAL_MACHINE\Comm\for the miniport driver. |
For example, a network adapter can have the following additional
keys:
[HKEY_LOCAL_MACHINE\Drivers\PCMCIA\Plug and Play ID]
DLL="NDIS.dll"
Prefix= "NDS"
Miniport="NE2000"
The NDIS interface sets the values for the
BusNumberand
BusTypekeys for network adapters. The
BusNumberkey contains the socket and function pair for the
adapter. The
BusTypekey contains the value for the network adapter bus.
If the information structure of the network adapter contains a
network address value, Ndis.dll will create a
\
HKEY_LOCAL_MACHINE\Comm\<miniport
Name>\<miniport Instance>\Network Addressregistry key
to store the network address.
Miniport drivers for a network adapter typically implement an
Install_Driverfunction for installing the appropriate
registry settings that will allow dynamic recognition of the
network adapter. For example, when a network adapter is inserted
into a Windows CE system, it tries to recognize the appropriate
driver for the adapter by matching its Plug and Play ID with an
appropriate key in the registry. If the system fails to find a Plug
and Play match, it will prompt the user to enter a driver name. If
this user-supplied driver DLL exports
Install_Driver, the system calls this function. The primary
purpose of this function is to populate the Windows CE registry
with appropriate entries for this miniport driver, as described
above, so that future insertions of the network adapter will lead
to dynamic loading of the correct NDIS miniport driver.
Installing Network Adapter
Drivers
The installation procedures for network adapter drivers depend
on whether you want to install an adapter driver for a removable
network adapter, such as a PC Card, or for a built-in network
adapter.
To install a removable network adapter driver, you must complete
the following steps:
- Connect to a Windows CE platform, or detect that a connection
already exists.
- Copy the installable device driver DLL to the Windows
directory.
- PC Card Services will call the
Install_Driverentry point in the miniport driver. The
Install_Driverfunction will create the appropriate registry
keys and values for each driver.
To install a built-in network adapter driver, Setup must
complete the following steps:
- Connect to a Windows CE platform, or detect that a connection
already exists.
- Copy the installable device driver DLL to the Windows
directory.
- Wait for the Setup program to create the required registry keys
and values for the driver.
- Restart the device.
IrDA Support
The NDIS implementation in Windows CE 3.0 features IrDA support.
Unlike in Windows NT, which supports binding to multiple adapter
instances, the Windows CE IrDA protocol driver can bind only to a
single miniport driver at a time. In the Windows communications
architecture, infrared sockets are exposed through extensions to
the Winsock interface.
Windows CE features the following two Windows CE-specific object
identifiers that provide for the sharing of hardware resources:
-
OID_IRDA_REACQUIRE_HW_RESOURCES
-
OID_IRDA_RELEASE_HW_RESOURCES
When an infrared socket has been opened and no others are
currently open, the set information handler of the miniport driver
is passed a request with the
OID_IRDA_REACQUIRE_HW_RESOURCESmessage to the miniport
driver. This message tells the miniport driver to take ownership of
any resources that are needed for IR communication (for example,
IrSIR opens a COM port). After all of the open infrared sockets
have been closed, the miniport driver receives the
OID_IRDA_RELEASE_HW_RESOURCESmessage through its query
information handler. After it receives this message, the miniport
driver releases all of the previously acquired hardware
resources.
NDIS Token Ring Support
The Windows CE implementation of NDIS now supports network
adapters that are of a Token Ring medium type (802.5). The Token
Ring support in Windows CE is a subset of the NDIS Token Ring
implementation in Windows NT.
When a network adapter of Token Ring medium type receives a data
packet over the network, its miniport driver indicates the packet
by calling the
NdisMTrIndicateReceivefunction. This function notifies NDIS
that a particular link has received a packet, and that the packet
is ready to be forwarded to the appropriate bound protocol
driver.
After the complete packet has been transferred, the miniport
driver must call the
NdisMTrIndicateReceiveCompletefunction to notify NDIS that
the transfer operation has been completed, even if a particular
packet is not accepted by any bound protocol.
NdisMTrIndicateReceiveCompletenotifies any bound protocol
that already has consumed the initial indication that it can begin
post-processing the received data.
Table 6 shows a list of supported APIs that apply directly to
the Token Ring medium type.
Table 6. Supported APIs that apply directly to the Token Ring
medium type
Function
|
Description
|
NdisMTrIndicateReceive
|
Notifies NDIS that a Token Ring packet (or some
initial look-ahead portion of the packet) has arrived, so that NDIS
can forward the packet to bound protocols. |
NdisMTrIndicateReceiveComplete
|
Notifies NDIS that a Token Ring receive packet,
which was identified in a preceding call to the
NdisMTrIndicateReceivefunction, has been transferred fully
by the NIC, so that NDIS can notify the appropriate bound protocol
drivers. |
Token Ring Object Identifiers
Table 7 summarizes the object identifiers that are used to get
or set Token Ring operational characteristics for NDIS drivers and
network adapters. All Token Ring object identifiers start with
OID_802_5Xxx, which is the universal identifier for Token Ring
networks.
Table 7. Object identifiers
Length
|
Q
|
S
|
Name
|
6 |
M |
|
OID_802_5_PERMANENT_ADDRESS
Permanent station address
|
6 |
M |
|
OID_802_5_CURRENT_ADDRESS
Current station address
|
4 |
M |
M |
OID_802_5_CURRENT_FUNCTIONAL
Current functional address
|
4 |
M |
M |
OID_802_5_CURRENT_GROUP
Current group address
|
4 |
M |
|
OID_802_5_LAST_OPEN_STATUS
Last open status
|
4 |
M |
|
OID_802_5_CURRENT_RING_STATUS
Current ring status
|
4 |
M |
|
OID_802_5_CURRENT_RING_STATE
Current ring state
NDISWAN Support
Windows CE 3.0 now also supports NDISWAN. The NDISWAN
implementation in Windows CE 3.0 features the AsyncMAC miniport
driver. The AsyncMAC miniport driver is responsible for sending and
receiving packets, performing asynchronous framing, and managing
Telephony API (TAPI) devices. NDISWAN for Windows CE 3.0 also
features a PPP layer, which is implemented as an NDIS protocol
driver. Driver writers also can develop their own customized
NDISWAN miniport driver.
The NDISWAN architecture that is implemented in Windows CE
differs from the NDISWAN architecture that is implemented in
Windows NT. Windows NT uses an intermediate NDIS driver, NDISWAN,
which manages WAN miniport drivers and maps WAN packets into
Ethernet packets, as it binds to the TCP/IP protocol stack as an
802.3 adapter. In Windows CE, the PPP protocol driver does not bind
to TCP/IP as an 802.3 miniport driver. Instead, it interfaces
directly to IP. While asynchronous framing occurs in the AsyncMAC
miniport driver in Windows CE, Windows NT uses the NDISWAN
intermediate driver to perform asynchronous framing. Unlike Windows
NT, Windows CE 3.0 does not support multi-link PPP.
Figure 6, below, shows the NDISWAN architecture that is
implemented in Windows CE.
Figure 6: NDISWAN architecture in Windows CE.
In the NDISWAN architecture in Windows CE, PPP is implemented as
an NDIS protocol driver. PPP communicates with the underlying
AsyncMAC miniport driver through the NDIS layer, which exposes an
NDIS protocol interface on the upper edge and an NDIS
miniport-driver interface on the lower edge. When PPP receives a
packet from TCP/IP, it does PPP framing, compression, and
encryption, and then passes the packet on to the AsyncMAC miniport
driver. After having received a packet from PPP, the AsyncMAC
miniport driver performs the asynchronous framing, and then
forwards the packet to the TAPI device by calling Win32 serial
APIs. When receiving a packet through the network, the AsyncMAC
miniport driver strips the flags off the packet, performs the
Cyclic Redundancy Check (CRC), and passes the packet up to PPP
through the NDIS layer. Before the WAN miniport driver can send or
receive packets on the network, an application must set up a
connection that originates on the sending node, or accept a
connection that originates on a remote node, by making or accepting
a call. Requests from TAPI and status indications to TAPI all go
through the WAN miniport driver.
After a connection with a remote node has been established,
packets can be exchanged over the network. The WAN miniport driver
specifies the default number of outstanding packets that it can
have for every data channel in the
MaxTransmitvalue, and submits the
MaxTransmitvalue to PPP as a response to an
OID_WAN_GET_INFOrequest. The
OID_WAN_GET_INFOstructure contains the following
information:
- The type of framing that is required for a packet.
- The amount of padding that must be placed at the head and tail
of a frame.
- The maximum size frame that the network adapter driver can send
and receive.
- The maximum number of frames that can be queued for
transmission.
- The number of links that are supported by the network adapter.
The WAN miniport driver might have to modify or add to the
header, as well as to the end of a packet. The NDISWAN
implementation in Windows CE 3.0 provides appropriate padding at
the beginning and end of each packet. The WAN miniport driver can
alter the data in the packet in any way that is appropriate, in
order to send it on the WAN medium.
AsyncMAC Registry Settings
The NDISWAN implementation in Windows CE 3.0 includes a
HKEY_LOCAL_MACHINE\Comm\AsyncMac1\Parmsregistry key. This
key contains a set of subkeys that allow you to configure values
that are specific to the WAN miniport driver, such as the maximum
packet size that a miniport driver will receive from a link.
The following table describes the registry settings for the
HKEY_LOCAL_MACHINE\Comm\AsyncMac1\Parmskey.
Table 8. Registry settings
Registry key
|
Type
|
Default
|
Description
|
MaxFrameSize
|
DWORD
|
1500 |
Specifies the maximum frame size (in bytes) that
the driver can send and receive, not including MAC layer
framing. |
MaxRecvFrameSize
|
DWORD
|
1500 |
Specifies the largest packet that the driver will
accept from the network, not including MAC layer framing. |
MaxSendFrameSize
|
DWORD
|
1500 |
Specifies the largest packet size that the driver
will send, not including MAC layer framing. |
ReceiveBufferSize
|
DWORD
|
2000 |
Specifies the total size, in bytes, of the receive
buffer for a driver that supports internal buffering. |
Note Setting
MaxRecvFrameSizeor
MaxSendFrameSizewill override the value of
MaxFrameSizefor that direction.
NDIS Library Functions Used by WAN Miniport
Drivers
NDIS miniport drivers for WAN adapters call most of the
functions that are called by other miniport drivers. However, WAN
miniport drivers cannot call the following functions:
-
NDISMIndicateReceive
-
NDISMIndicateReceiveComplete
-
NDISMSendComplete
NDIS miniport drivers for WAN adapters must instead call the
functions shown in Table 9.
Table 9. Functions called for NDIS miniport drivers for WAN
adapters
Function
|
Description
|
NdisMWanIndicateReceive
|
Notifies NDIS that a particular link has received a
packet, and that the packet has been identified by the given
link-context handle, and on a particular network adapter, by the
adapter handle. Also, notifies NDIS that the full packet is
available to be forwarded to the appropriate bound protocol
driver(s). |
NdisMWanIndicateReceiveComplete
|
Notifies NDIS that one or more receives on a
particular link, identified by the given link-context handle, and
on a particular network adapter, identified by the adapter handle,
are complete (that is, the preceding call to the
NdisMWanIndicateReceivefunction has returned), so that NDIS
can notify the appropriate bound protocol driver(s). |
NdisMWanSendComplete
|
Returns the packet and final status of a completed
sendrequest for which the driver previously returned
NDIS_STATUS_PENDING, so that NDIS can return the completed
packet to the appropriate bound protocol driver. |
NDISWAN Object Identifiers
Table 10 summarizes the object identifiers that are used to get
or set operational characteristics for NDIS drivers and WAN
adapters.
Table 10. Object identifiers
Length
|
Q
|
S
|
Name
|
6 |
M |
|
OID_WAN_PERMANENT_ADDRESS
Permanent station address
|
6 |
M |
|
OID_WAN_CURRENT_ADDRESS
Current station
|
1 or 6 |
|
M |
OID_WAN_PROTOCOL_TYPE
Protocol type
|
4 |
M |
|
OID_WAN_MEDIUM_SUBTYPE
Medium subtype
|
4 |
|
M |
OID_WAN_HEADER_FORMAT
Format the packet header
|
4 |
M |
|
OID_WAN_GET_INFO
Get information
|
4 |
M |
|
OID_WAN_GET_LINK_INFO
Get link information
|
4 |
|
M |
OID_WAN_SET_LINK_INFO
Set link information
|
4 |
M |
|
OID_WAN_LINE_COUNT
Line count
|
50 |
0 |
|
OID_WAN_GET_COMP_INFO
Get compression information
|
50 |
|
O |
OID_WAN_SET_COMP_INFO
Set compression information
|
60 |
O |
|
OID_WAN_GET_STATS_INFO
Get statistics information
|
|
|
|
OID_TAPI_TRANSLATE_ADDRESS
Translate the name or number entered by the user into the final
format required by the miniport driver to make the connection
DMA
Unlike the Windows NT implementation, the Windows CE
implementation of NDIS does not support Direct Memory Access (DMA)
operations inherently. Some platforms might provide DMA libraries
for use by driver developers, or the miniport driver might need to
implement DMA entirely on its own. In Windows NT, there are two
methods to implement DMA, depending on whether the LAN is a
subordinate DMA network adapter or a busmaster DMA network
adapter.
Non-Busmaster DMA Network
Adapters
For subordinate DMA transfers, a Windows NT miniport driver
calls a set of functions that consist of
NdisMRegisterDmaChannel,
NdisMDeregisterDmaChannel,
NdisMSetupDmaTransfer,
NdisMCompleteDmaTransfer, and
NdisMReadDmaCounter. The Windows CE implementation of NDIS
does not support these functions. Instead, the required
functionality can be implemented directly in the miniport-driver
code.
To implement DMA transfers in a miniport driver, you must
reserve a physical memory block from the memory map of a Windows
CE-based device. Then, you must map the memory block of the device
to virtual address pointers by using the
VirtualAllocand
VirtualCopyfunctions. Mapping the memory block of the device
to virtual address pointers provides the miniport driver with a
shared memory block to send and receive packet buffers.
To see an example of how to implement DMA operations in a
miniport driver for Windows CE, consult the sample code for the
National Semiconductor Fast IR Miniport Driver that is shipped with
Windows CE 3.0.
The following code samples show how to
implement DMA functionality in a miniport driver in Windows CE:
/********************************/ Copyright (c)
2000 Microsoft Corporation Module Name: Ndisdma.h Abstract: This
will implement the NDIS-required DMA functions that differ from the
Windows CE and Windows NT implementations.
**********************************/ #ifndef _NDISDMA_H_ #define
_NDISDMA_H_ #ifdef UNDER_CE typedef struct _NDIS_DMA_DESCRIPTION {
BOOLEAN DemandMode; BOOLEAN AutoInitialize; BOOLEAN
DmaChannelSpecified; DMA_WIDTH DmaWidth; DMA_SPEED DmaSpeed; ULONG
DmaPort; ULONG DmaChannel; } NDIS_DMA_DESCRIPTION,
*PNDIS_DMA_DESCRIPTION; // DMA Operations. NDIS_STATUS
NdisMRegisterDmaChannel ( OUT PNDIS_HANDLE MiniportDmaHandle, IN
NDIS_HANDLE MiniportAdapterHandle, IN UINT DmaChannel, IN BOOLEAN
Dma32BitAddresses, IN PNDIS_DMA_DESCRIPTION DmaDescription, IN
ULONG MaximumLength); VOID NdisMDeregisterDmaChannel (IN
NDIS_HANDLE MiniportDmaHandle); VOID NdisMSetupDmaTransfer ( OUT
PNDIS_STATUS Status, IN PNDIS_HANDLE MiniportDmaHandle, IN
PNDIS_BUFFER Buffer, IN ULONG Offset, IN ULONG Length, IN BOOLEAN
WriteToDevice); VOID NdisMCompleteDmaTransfer ( OUT PNDIS_STATUS
Status, IN PNDIS_HANDLE MiniportDmaHandle, IN PNDIS_BUFFER Buffer,
IN ULONG Offset, IN ULONG Length, IN BOOLEAN WriteToDevice); ULONG
NdisMReadDmaCounter (IN NDIS_HANDLE MiniportDmaHandle); #endif //
UNDER_CE #endif // _NDISDMA_H_ /**********************************/
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE. Copyright (c) 2000 Microsoft Corporation
**********************************/ #include <windows.h>
#include <ndis.h> #include "Nsc.h" #include "Ndisdma.h"
#define FIR_BUFFER_BASE_PA 0x00001000 #define MINIPORT_DMA_HANDLE
(NDIS_HANDLE) 0x45454545 // We will map our virtual address to //
our DMA physical buffer. // This is used with any buffer that //
was mapped into our physical // buffer. PVOID VirtualToPhysAddress
(PVOID pvVirtual) { // Make sure that the given virtual address is
// within the range of our buffer. ASSERT (((PUCHAR)pvVirtual >=
(PUCHAR)g_pvDmaVirtualBase) && ((PUCHAR)pvVirtual
<((puchar)g_pvdmavirtualbase + NSCIRDA_DMA_BUFFER_LEN))); //
Physical address is the base physical address // plus the offset in
the virtual address space. return (PVOID)
((DWORD)NSCIRDA_DMA_BUFFER_BASE_PA + (DWORD)pvVirtual
(DWORD)g_pvDmaVirtualBase); } const int DmaAddrReg[4]="{" 0x00,
0x02, 0x04, 0x06}; const int DmaCountReg[4]="{" 0x01, 0x03, 0x05,
0x07}; const int DmaPageReg[4]="{" 0x87, 0x83, 0x81, 0x82}; //
Define the DMA-mode register structure. typedef struct _DMA_MODE {
UCHAR Channel : 2; UCHAR TransferType : 2; UCHAR AutoInitialize :
1; UCHAR AddressDecrement : 1; UCHAR RequestMode : 2; }DMA_MODE,
*PDMA_MODE; // Define TransferType values. #define VERIFY_TRANSFER
0x00 #define READ_TRANSFER 0x01 // Read from the device. #define
WRITE_TRANSFER 0x02 // Write to the device. // Define RequestMode
values. #define DEMAND_REQUEST_MODE 0x00 #define
SINGLE_REQUEST_MODE 0x01 #define BLOCK_REQUEST_MODE 0x02 #define
CASCADE_REQUEST_MODE 0x03 #define DMA_SETMASK 4 #define
DMA_CLEARMASK 0 #define DMA_READ 4 #define DMA_WRITE 8 #define
DMA_SINGLE_TRANSFER 0x40 #define DMA_AUTO_INIT 0x10 // Auto
initialization mode // Define DMA 1 address and // count structure
// (for 8237 compatibility) typedef struct _DMA1_ADDRESS_COUNT {
UCHAR DmaBaseAddress; UCHAR DmaBaseCount; } DMA1_ADDRESS_COUNT,
*PDMA1_ADDRESS_COUNT; // Define DMA 1 control register structure //
(for 8237 compatibility) typedef struct _DMA1_CONTROL {
DMA1_ADDRESS_COUNT DmaAddressCount[4]; UCHAR DmaStatus; UCHAR
DmaRequest; UCHAR SingleMask; UCHAR Mode; UCHAR ClearBytePointer;
UCHAR MasterClear; UCHAR ClearMask; UCHAR AllMask; } DMA1_CONTROL,
*PDMA1_CONTROL; NDIS_DMA_DESCRIPTION g_DMA_Description; BOOL
g_fRegistered; UINT g_nDmaChannel;
/**********************************/ NDIS_STATUS
NdisMRegisterDmaChannel ( PNDIS_HANDLE phMiniportDmaHandle,
NDIS_HANDLE hMiniportAdapterHandle, UINT nDmaChannel, BOOLEAN
fDma32BitAddresses, PNDIS_DMA_DESCRIPTION pDmaDescription, ULONG
ulMaximumLength) { NDIS_STATUS Status="NDIS_STATUS_SUCCESS;"
DEBUGMSG (ZONE_INIT | ZONE_DMA, (TEXT("+NdisMRegisterDmaChannel
(%#x, %#x, %d, %d, %#x, %d\r\n"), phMiniportDmaHandle,
hMiniportAdapterHandle, nDmaChannel, fDma32BitAddresses,
pDmaDescription, ulMaximumLength)); // Check to ensure that we are
not registered already. Allow only // one at a time. if
(g_fRegistered) { Status="NDIS_STATUS_RESOURCE_CONFLICT;" goto
done; } // One DMA Channel per driver. Return Constant.
*phMiniportDmaHandle="MINIPORT_DMA_HANDLE;" // Store the
description for later use. memcpy (&g_DMA_Description,
pDmaDescription, sizeof (NDIS_DMA_DESCRIPTION));
g_nDmaChannel="nDmaChannel;" if (g_nDmaChannel> 3) { DBGERR
((TEXT("The channel is > 3. Not available in this sample
driver!"))); Status = NDIS_STATUS_RESOURCES; goto done; } //
Indicate that we are registered. g_fRegistered = TRUE; done:
DEBUGMSG (ZONE_INIT | ZONE_DMA, (TEXT("-NdisMRegisterDmaChannel
[%s, hDma = %#x]\r\n"), DBG_NDIS_RESULT_STR (Status),
*phMiniportDmaHandle)); return (Status); }
/**********************************/ VOID NdisMDeregisterDmaChannel
(PNDIS_HANDLE phMiniportDmaHandle) { DEBUGMSG (ZONE_INIT |
ZONE_DMA, (TEXT("+NdisMDeregisterDmaChannel (%#x)\r\n"),
phMiniportDmaHandle)); if (*phMiniportDmaHandle ==
MINIPORT_DMA_HANDLE) g_fRegistered = FALSE; DEBUGMSG (ZONE_INIT |
ZONE_DMA, (TEXT("-NdisMDeregisterDmaChannel\r\n"))); }
/**********************************/ VOID NdisMSetupDmaTransfer (
PNDIS_STATUS pStatus, PNDIS_HANDLE phMiniportDmaHandle,
PNDIS_BUFFER pBuffer, ULONG Offset, ULONG Length, BOOLEAN
WriteToDevice) { int DMAAddr, DMACount, DMAPage, Offset2, Page; int
DMAChanOffset; UCHAR bReadWrite; UCHAR bMode; PDMA1_CONTROL
dmaControl = 0; DMA_MODE dmaMode; DWORD dwPhysAddress;
DBGDMA((TEXT("+NdisMSetupDmaTransfer %s: buf = 0x%x, offset = %d,
len = %d"), (WriteToDevice == TRUE) ? TEXT("TX") : TEXT("RX"),
pBuffer, Offset, Length)); *pStatus = NDIS_STATUS_SUCCESS; if
(phMiniportDmaHandle != MINIPORT_DMA_HANDLE) { *pStatus =
NDIS_STATUS_RESOURCES; goto done; } DMAAddr =
DmaAddrReg[g_nDmaChannel]; DMACount = DmaCountReg[g_nDmaChannel];
DMAPage = DmaPageReg[g_nDmaChannel]; // We";re making the
assumption of 8-bit. DMAChanOffset = g_nDmaChannel; if (Offset +
Length > pBuffer->BufferLength) { DBGERR ((TEXT(";The offset
+ length is greater than the buffer length!"))); *pStatus =
NDIS_STATUS_RESOURCES; goto done; } // Get the physical address
from the virtual address. dwPhysAddress =
(DWORD)VirtualToPhysAddress (pBuffer->VirtualAddress) + Offset;
DBGDMA((TEXT("Address = 0x%X";), (PBYTE)pBuffer->VirtualAddress
+ Offset)); DBGDMA((TEXT("Length = 0x%X"),
pBuffer->BufferLength)); DBGDMA((TEXT("Channel = 0x%X"),
g_nDmaChannel)); DBGDMA((TEXT("DMA Buffer 0x%x, len %d"),
dwPhysAddress + Offset, Length)); // PROGRAM THE DMA chip Page =
(int) ((dwPhysAddress >> 16) & 0xFF); Offset2 = (int)
(dwPhysAddress & 0xFFFF); // Disable DMA while programming.
WRITE_PORT_UCHAR ((PUCHAR) 0x0A, (UCHAR) (DMAChanOffset | 4)); //
Clear byte pointer. WRITE_PORT_UCHAR ((PUCHAR) 0x0C, (UCHAR) 0);
dmaMode.Channel = g_nDmaChannel; dmaMode.TransferType =
(WriteToDevice ? WRITE_TRANSFER : READ_TRANSFER);
dmaMode.RequestMode = DEMAND_REQUEST_MODE; dmaMode.AutoInitialize =
FALSE; dmaMode.AddressDecrement = FALSE; // 8-bit demand mode
non-autoinit bReadWrite = (WriteToDevice ? 0x8 : 0x4); bMode =
bReadWrite | g_nDmaChannel; WRITE_PORT_UCHAR ((PUCHAR) 0x0B,
bMode); // LO byte address of buffer. WRITE_PORT_UCHAR
((PUCHAR)DMAAddr, (UCHAR) (Offset2 & 0xFF)); // HI byte address
of buffer. WRITE_PORT_UCHAR ((PUCHAR)DMAAddr, (UCHAR) (Offset2
>> 8)); // Physical page number. WRITE_PORT_UCHAR
((PUCHAR)DMAPage, (UCHAR) Page); // LO byte of count.
WRITE_PORT_UCHAR ((PUCHAR)DMACount, (UCHAR) ((Length - 1) &
0xFF)); // HI byte of count. WRITE_PORT_UCHAR ((PUCHAR)DMACount,
(UCHAR) ((Length - 1) >> 8)); DBGDMA((TEXT("ReadCount
(before) = %d"), NdisMReadDmaCounter (phMiniportDmaHandle))); //
Done programming the DMA, enable it. WRITE_PORT_UCHAR ((PUCHAR)
0x0A, (UCHAR) DMAChanOffset); done:
DBGDMA((TEXT("-NdisMSetupDmaTransfer [%s]"), DBG_NDIS_RESULT_STR
(*pStatus))); return; } /**********************************/ VOID
NdisMCompleteDmaTransfer ( PNDIS_STATUS Status, PNDIS_HANDLE
MiniportDmaHandle, PNDIS_BUFFER Buffer, ULONG Offset, ULONG Length,
BOOLEAN WriteToDevice) { DBGDMA((TEXT("+NdisMCompleteDmaTransfer
%s: buf = 0x%x, offset = %d, len = %d"), (WriteToDevice == TRUE) ?
TEXT("TX") : TEXT("RX"), Buffer, Offset, Length)); // Disable the
DMA. WRITE_PORT_UCHAR ((PUCHAR) 0x0A, (UCHAR) (g_nDmaChannel | 4));
DBGDMA((TEXT("-NdisMCompleteDmaTransfer [NDIS_STATUS_SUCCESS]")));
*Status = NDIS_STATUS_SUCCESS; } /********************************/
ULONG NdisMReadDmaCounter (NDIS_HANDLE MiniportDmaHandle) { UCHAR
bLo, bHi; bLo = READ_PORT_UCHAR ((PUCHAR)
DmaCountReg[g_nDmaChannel]); bHi = READ_PORT_UCHAR ((PUCHAR)
DmaCountReg[g_nDmaChannel]); DBGDMA((TEXT("NdisMReadDmaCounter
[StatusReg = 0x%x, Count = %d]"), READ_PORT_UCHAR ((PUCHAR) 0x08),
bHi << 8 | bLo)); return (bHi << 8 | bLo); }
Busmaster-DMA Network Adapter
For busmaster-DMA network adapters, a Windows NT miniport driver
calls a set of functions that consist of
NdisQueryMapRegisters,
NdisMAllocateMapRegisters,
NdisMAllocateSharedMemory,
NdisMFreeSharedMemory,
NdisMStartBufferPhysicalMapping, and
NdisMCompleteBufferPhysicalMappingto facilitate the DMA
transfer. The Windows CE implementation of NDIS does not support
these functions. However, driver developers can implement a
functionality that supports DMA transfers directly in the miniport
driver.
In Windows NT, a miniport driver generally transfers data that
is received by a busmaster-DMA network adapter into
device-accessible buffers that are within a shared memory block
allocated by the miniport driver. The miniport driver calls the
NdisMInidcateReceivePacketfunction to indicate the packet to
the protocol. The miniport driver can reserve a shared memory
block, too, as described in the preceding section,
Non-Busmaster DMA Network
Adapters.
To transfer packet data for a send request, a Windows NT
miniport driver first maps the virtual range that contains the data
to the
NdisMStartBufferPhysicalMappingfunction, in order to obtain
the mapped range of device-accessible addresses for use by its
network adapter. Then, the miniport driver downloads the returned
physical addresses to the network adapter. If the driver allocated
cached memory, the miniport driver calls the
NdisFlushBufferand
NdisMUpdateSharedMemoryfunctions. After it has downloaded
the physical addresses to the network adapter, the miniport driver
programs the network adapter for the transfer operation.
The network adapter indicates that the transfer operation is
complete, either by transmitting an interrupt, or by a change of
state that is discovered when the network adapter driver polls the
MiniportTimerfunction. After the network adapter has
completed the transfer operation, the miniport driver calls the
NdisMCompleteBufferPhysicalMappingfunction, usually from the
MiniportHandleInterruptfunction.
On Windows CE, a miniport driver can use the
LockPagesor
UnlockPagesfunction, in place of the
NdisMStartBufferPhysicalMappingand
NdisMCompleteBufferPhysicalMappingNDIS functions, for
mapping virtual addresses to physical address ranges.
|
|