Click here to learn
about this Sponsor:
Home  |  News  |  Articles  |  Polls  |  Forum  |  Directory

Keywords: Match:
How Windows CE bus drivers work
by David Liao (Apr. 30, 2007)

Foreword: Windows CE bus drivers play an important role in virtualizing bus architectures to make higher-level client drivers "bus agnostic." This extensive technical article by David Liao, a developer on Microsoft's Windows CE team, explains what Windows CE bus drivers do, and explores some of their key functions.



How Windows CE Bus Drivers Work

by David Liao


Abstract

A bus driver is designed for controlling and configuring a specific Bus. It also configures and controls hardware on the bus and loads and unloads hardware drivers called client drivers. It also carries out bus request from its client drivers. A bus driver has two basic functions from software perspective. One is serving its client driver. Another is configuring, loading, and controlling its client drivers. Microsoft provides a bus driver for most common buses, such as PCI, PCCARD, and the "Root" Bus.

What a Bus Driver does

A Bus Driver is responsible for Hardware Configuration, Hardware Power Control, Bus address translation, and loading and unloading upper-level client drivers.

Loading and Unloading upper-level client drivers

Most upper-level client drivers are loaded by a bus driver calling ActivateDevice(Ex). ActivateDevice(Ex) loads a client driver according to the contents of a registry entry that is passed in by the caller.

This means you need the registry in order to load the driver. A Bus driver has to either use an existing registry entry or create an instance registry entry according to a template.

For PNP drivers, the bus driver configures the hardware and sets up instance registry entries according to PNP information. Then, it loads a client driver by calling ActivateDevice(Ex) and specifying the new instance registry entries.

For non-PNP drivers and intermediate drivers, usually the registry is set up manually. It could be Microsoft, an OEM, or a third party who provides the bus driver. The bus driver normally still uses the registry to load those drivers.

A Bus driver can also be loaded by a "parent" bus driver, creating a "tree" of buses. The exception is the "Root" Bus Driver, or trunk of the tree. The Root Bus Driver is loaded by Device Manager using a registry path value found at a specific registry location:
    [HKEY_LOCAL_MACHINE\Drivers]
    "RootKey"="Drivers\BuiltIn"

The default value is set up by Microsoft. However, it can be changed by an OEM to allow the Root Bus Driver to enumerate drivers in some other registry path.

The above example indicates that the Root Bus driver is located at
    [HKEY_LOCAL_MACHINE\Drivers\Builtin]
Device Manager loads the Root Bus Driver during initialization.

Important: Device Manager makes the Root Bus Driver run TWICE in a system with a two-phase boot.

In Boot Phase One, the Device Manager deletes the Drivers "Active" Key holding any stale driver instances (i.e. HKLM\drivers\Active), then loads the Root Bus Driver with the fixed Bus name "BuiltInPhase1". If this system has a two-phase boot, after the system "Phase 2" Event is signaled, the Device Manager loads the Root Bus Driver again. The second time the Device Manager uses a bus name found in the registry.

Is it possible that a driver can be loaded twice in two phase boot system? The answer is yes.

If a driver is included in HIVE registry and its entries do not include the DWORD "Flags" entry specifying DEVFLAGS_BOOTPHASE_1 (0x00001000), it will be loaded twice. It is important to take this into consideration when specifying the registry entries for a Bus Driver.

In theory, some Bus drivers should be loaded twice.

Bus Driver Access and the CEDDK Bus Functions

A client driver is capable of using its Bus Driver to:
  • do bus address translation between a subordinate Bus and a Parent Bus
  • do Device Power State changes
  • access Configuration Data

There are many reasons to use a Bus Driver. One important reason is to make a Client Driver become bus-agnostic. This means a driver is capable of moving to user mode, or of working on different bus-architectures with the same binary. Some examples of bus-agnostic drivers are COM16550.dll and NE2000.dll. These can work as client drivers of the PCI Bus, Native Bus and PCMCIA bus with the same binary.

Bus Access Functions

In order to get access to its parent Bus Driver, a client driver has to call the CreateBusAccessHandle() function to get a bus driver access handle. This function is usually called by a client driver during its initialization (XXX_Init) because it requires that the client driver pass the "Active Registry Path" as an argument. CloseBusAccessHandle() is used for closing the access handle returned by calling CreateBusAccessHandle(). Usually the CloseBusAccessHandle() function is called before exiting XXX_Deinit. Please refer to MSDN online documentation for detailed information on these functions.

After a Bus Access Handle is created, a Client can use any function which uses this handle as an argument.

CEDDK Functions for Bus Driver operations are provided as wrappers -- they pack the corresponding function parameters and call the Bus Driver with an operation-specific IO Control Code (IOCTL). Microsoft strongly recommends that driver writers use the CEDDK functions instead of calling the Bus Driver directly with the IO Control Code. The parameters for the Bus IO Control Code may change from release to release, but the CEDDK functions (as formal APIs) signatures will not.

Listed below are the CEDDK functions and their corresponding IO Control Codes:

CreateBusAccessHandleCreates an access handle for other CEDDK Bus functions. This results in the Parent bus™ Open() entry being called.

CloseBusAccessHandleCloses the handle which was created by using CreateBusAccessHandle(). This results in the Parent bus™ Close() entry called.

SetDevicePowerState

IOCTL_BUS_SET_POWER_STATE

GetDevicePowerState

IOCTL_BUS_GET_POWER_STATE

TranslateBusAddr

IOCTL_BUS_TRANSLATE_BUS_ADDRESS

TranslateSystemAddr IOCTL_BUS_TRANSLATE_SYSTEM_ADDRESS

SetDeviceConfigurationData

IOCTL_BUS_SET_CONFIGURE_DATA

GetDeviceConfigurationData

IOCTL_BUS_GET_CONFIGURE_DATA

GetChildDeviceRemoveState

IOCTL_BUS_IS_CHILD_REMOVED


SetDevicePowerState() and GetDevicePowerState() are used by a client driver to request that its parent Bus Driver put the client into a certain power state. Although some client drivers do the actual power state change by themselves, but it is the Bus driver's responsibility for putting its client drivers to their effective power states based upon the requests. Before a Bus Driver loads a client driver, it should put client driver's hardware into Power State D0. After the Bus driver unloads the client drivers, it should put the corresponding hardware into Power State D4.

TranslateBusAddr() and TranslateSystemAddr() are used to translate between physical CPU addresses and subordinate Bus addresses. To do so, TranslateBusAddr() should translate the target address from a Subordinate Bus to a Parent Bus. These calls should propagate up all the way to the Root Bus driver. Then Root Bus driver then calls the OAL function HalTranslateBusAddress() to acquire the final CPU-relative physical address. TranslateSystemAddr() works similarly, but in the other direction. The OAL uses HalTranslateSystemAddress() to translate from a CPU address to a Bus address. So, multi-layer bus address translation only can be resolved by TranslateBusAddr() and TranslateSystemAddr().

Before doing a virtual or static system memory mapping function for a driver, the BusTransBusAddrToVirtual() and BusTransBusAddrToStatic() functions use TranslateBusAddr() to translate a Bus address to a CPU(system) address.

IO Control Codes that are not supported by CEDDK

CEDDK provides the BusIoControl() and BusChildIoControl() functions to client drivers. Client drivers can use these two functions to issue a Bus IO Control call directly. The difference with these function is that BusChildIoControl() is used to issue an IO Control call related to client driver which is making the call.

The IOCTL_BUS_ACTIVATE_CHILD and IOCTL_BUS_DEACTIVATE_CHILD control codes are standard IO Control codes for which no wrapper function is implemented in the CEDDK. These IO Control codes can be called by any application if it opens a handle to the bus driver. The two Io Control Codes are used to activate or deactivate a client driver. Note: For legacy reasons not all client drivers can be deactivated.

How a driver's bus name is assigned

A Client Driver's bus name is assigned by its parent Bus Driver.

The Bus Name that Bus Driver assigns follows a simple four-part pattern:
    busname _bus#_device#_function#

Usually, "busname" is assigned to a Bus Driver according to the value of its "BusName" registry entry under the Bus Driver device's registry key. This is value is pre-assigned either by Microsoft or by the OEM that is using the Bus Driver.

The "bus#", "device#" and "function#" are set to the "BusNumber", "DeviceNumber" and "FunctionNumber" registry entry values under the device key for the Client Driver. These registry value are created by the PnP Bus Driver. For non-PnP Bus drivers (for example, the Root Bus Driver), the "bus#" is assigned by the Bus Driver's device registry key. The "device#" and "function#" are then assigned automatically by the Bus driver.

Because the "busname" has to be unique in the system, an appropriate name must be chosen when the system has multiple bus drivers. The following is a list of well-known bus driver names:
  1. Root Bus Driver: "BuiltIn"
  2. PCI Bus Driver: "PCI"
  3. PC Card Bus Driver: "PCCARD"

Power Manageable Drivers and Bus Drivers Power IO Control Codes

There are two different types of Power Manageable Drivers. The first type is a driver which is under the control of the system Power Manager (PM). The second type is a driver which manages its own power. Drivers which are under the control of the system Power Manager have to support the following IO Control Codes:
  • IOCTL_POWER_CAPABILITIES -- The Power Manager uses this IO Control Code to query a driver's supported device power states. After a driver returns from this call with the Device Power States that it supports (D0->D4), and IOCTL_POWER_SET commands (see below) that specify a supported Device Power State should succeed. If the device does not accept the command to change power state, the PM will consider the refusal as a severe error.

  • IOCTL_POWER_QUERY -- (Optional) This function simply returns a driver's current power state.

  • IOCTL_POWER_SET -- The Power Manager uses this IO Control Code to change the driver's power state. Power Manager only specifies valid power states reported by a driver from IOCTL_POWER_CAPABILITIES.

Role the Bus Driver plays in Power Management of a Client Driver

As we described previously, the Client's Bus Driver is responsible for changing the hardware power state. Therefore, it would seem that the best solution would be for the Power Manager to call the Bus Driver directly to have it manage power. In fact, this does not happen. There are two reasons why not:
  1. A Client Driver need to know the current power state in order to perform its function correctly. For example, the Client Driver has to make sure there is no ongoing processing on the hardware or a blocking future function request (if requests are queued) before calling the Bus Driver to turn off the hardware.

  2. Driver before Windows CE 5.0 performed Power Control by itself. To make processing backwards compatible, the Power Manager needs to continue to call the Client Driver directly.

The Power Control commands from the System Power Manager are sent to the client driver. They are propagated to the client's Bus Driver via an Bus IO Control Code. The process is:
  1. PM calls DeviceIoControl (IOCTL_POWER_SET) on the client Driver.

  2. The Client Driver calls the SetDevicePowerState() CEDDK function which translates IOCTL_BUS_SET_POWER_STATE to the bus driver.

  3. The Bus driver determines what to do base on the call from the client driver.

There can be confusion and fear resulting from the driver being simultaneously commanded by I/O functions (IoControl/Read/Write), and the Power Manager IO Control Code. When simultaneous requests happen, something must be done so that the Client driver still performs its functions correct.y. Use of a few CEDDK functions can help resolve the situation by following a general pattern:

Init()
{
hPwrHandle = DDKPwr_Initialize(__in PFN_SETPOWERLEVEL pSetPowerLevelFn,
__in DWORD dwContext,
__in BOOL fAbortOnPMRequests,
__in DWORD dwTimeout );
};

Deinit
{
DDKPwr_Deinitialize(hPwrHandle);
}

Function_Request()
{
HANDLE hLevelHandle = DDKPwr_RequestLevel(hPwrHandle,
__in CEDEVICE_POWER_STATE dx );
¦ // Do some work.
DDKPwr_ReleaseLevel(hPwrHandle, hLevelHandle);
}

PowerMgr_Request(Dx)
{ // From Power IO Control
DDKPwr_SetDeviceLevel(hPwrHandle ,Dx , __in PFN_SETPOWERLEVELCALLBACK pCallbackFn );
}

This pseudocode gives a general reference for how this is done. The released example for how to use the set of CEDDK function can be found public\common\oak\drivers\serial\serpddcm\cserpdd.cpp.

Bus Driver Library

Microsoft provides a Bus Driver Library to allow a user to write a Bus Driver. CEDDK functions pass Bus Io Control Codes to a Bus Driver. There are two different IO Control Codes. The first is targeted at the Bus Driver, the second is targeted at one client driver to control Configuration, Power State and Bus Address translation:
Class DefaultBusDriver {

Public:
// Constructor
// Client Driver Specific function.
// Bus Driver Function.

Protected:
// Container for all Folders of Child Client Driver.
// Child Folder Class Manufacture. };

class DeviceFolder {

public:
// Constructor
// Device Power Function
// Device Configuration Function
// Device Bus Address Translation Function
// Device Driver Load and Unload Function.
};

The DefaultBusDriver and DeviceFolder classes are abstract templates for implementation of a Bus Driver. A Bus Driver should inherit from these two basic classes and modify their virtual functions according to specific needs.

The Bus Library does not provide instantiable DefaultBusDriver and DeviceFolder classes. You must subclass these abstract bases and fill in implementation details. There are some default methods in the DefaultBusDriver implementation to manage a DeviceFolder-based class.

There are a few functions that the Bus Library provides:

DefaultBusDriver Class
  • Forwards device-specific requests to a folder
  • Manages DeviceFolder containers
  • Performs Default Bus Translations for the IOCTL_BUS_TRANSLATE_SYSTEM_ADDRESS and IOCTL_BUS_TRANSLATE_BUS_ADDRESS IO Control Codes. It calls its parent bus driver to translate addresses or calls HalTranslateBusAddress or HalTranslateSystemAddress if it is a Root Bus Driver.
  • Handles the basic IOCTL_BUS_IS_CHILD_REMOVED, IOCTL_BUS_NAME_PREFIX and other IO Control codes.
  • Has a dummy function for PostInit(), which is called by IOCTL_BUS_POSTINIT

DeviceFolder
  • Includes logic for creating a default bus name for use in driver loading and unloading.
  • Perform Default Configuration Functions forwarded by the DefaultBusDriver class through IOCTL_BUS_GET_CONFIGURE_DATA and IOCTL_BUS_SET_CONFIGURE_DATA. It calls HalGetBusDataByOffset or HalSetBusDataByOffset when a request is from PCI Client Device Driver.
  • Has a dummy function for SetPowerState which is called by the DefaultBusDriver through IOCTL_BUS_SET_POWER_STATE. The provided implementation of the PCI Bus Driver shows a good example of how to do SetPowerState for specific hardware.

PCI Bus Driver

The PCI Bus Driver is required to Configure the PCI Bus, Assign Resources, Search for Drivers according to a template, and set Instant Device Loading Registry keys. The details of this implementation are not described here, but the functions used to support Bus IoControl calls from external clients are detailed.

In order to support a Bus IO Control call from a Client Driver the PCI Bus Driver implements the following subclasses of the ones defined in the Bus Driver Library:
class PciDeviceFolder : public DeviceFolder{
virtual BOOL PostInit() ;
...
};
class PciBusEnum : public DefaultBusDriver {
...
};
These classes override their bases in the following ways:
  • PciBusEnum -- Implements the PostInit() function to overwrite the dummy implementation in the parent class. This new implementation calls two sub functions:
    1. Calls AssignChildDriver() which creates one PciDeviceFolder for each Device Instance. This also inserts the folder into a Device Folder container.
    2. Calls ActivateAllChildDriver() which calls DeviceFolder::LoadDevice() to load each client driver in order.

  • PciDeviceFolder -- Implements the SetPowerState() to overwrite the dummy implementation in the parent class. The new method implements its actions according to the PCI PM 1.1 specification.

Root Bus Driver

The default Root Bus Driver is called "BusEnum". This default only implements a simple BusEnum class which inherits its behavior from the DefaultBusDriver class in the Bus Driver library. It does not modify the default DeviceFolder implementation. Therefore, it does not support the SetPowerState() call to a device folder (default implementation is just a dummy).
class BusEnum : public  DefaultBusDriver {
virtual BOOL PostInit() ;
...
};
  • BusEnum -- Implements the PostInit() function to overwrite the dummy implementation in the parent class. This new implementation calls two sub functions:
    • Calls AssignChildDriver() which creates one DeviceFolder for each Device Instance referenced by a sub registry key. It then inserts the folder into a Device Folder container.
    • Calls ActivateAllChildDriver() which calls DeviceFolder::LoadDevice() to load drivers in order.

For the Root Bus to support Power State Setting for Client Driver requests, the SetPowerState() Driver Folder function has to be implemented. The F-Sample (OMAP850) has an example of a platform-specific Root Bus Driver to show it how it can be done.


Copyright (c) 2007 Microsoft Corp. All rights reserved. Reproduced by WindowsForDevices.com with permission. This article was originally published on the Windows CE Base Team Blog, here.



About the author: David Liao has been a software developer for over 20 years, and has worked for Microsoft for the past nine years. During his time at Microsoft, he has specialized in Windows CE device drivers, including the Mode Driver Framework, SD Bus driver re-design, USB 2.0 EHCI stack, PC Card stack, and Windows CE Bus Driver Architect, and BSPs (board support packages), including the design of USB Function Controller driver, USB OTG, PCI, and others. Prior to joining Microsoft, Liao worked for Xerox, Teklogix, and other companies as a DSP Software Developer.



Related stories:

(Click here for further information)


Windows XP for Embedded Applications
This white paper describes the benefits of using Windows XP when developing embedded applications.

A Manager's Guide to Selecting a Mobile Device Operating System
This white paper offers a comparative review of Microsoft Windows CE and Windows Mobile.

Visual Basic 6.0 to .NET Migration
This paper focuses on the methodology and techniques which Infosys (Microsoft Technology Center) has developed for migrating VB 6.0 Applications to .NET. Our approach ensures a smooth, cost effective, and efficient migration.

Mobile Device Security: Securing the Handheld, Securing the Enterprise
This whitepaper identifies security threats to corporate data on mobile devices and details how mobile devices can become a "backdoor" to the enterprise.

Mobile Device Security: The Eight Areas of Risk
It's common knowledge that adding mobile devices to your network increases security risks. There are multiple facets to mobile security, all of which should be paid close attention to. This E-Guide presents a more in depth look into the eight key areas of securing wireless devices.

Quality Assurance and .NET
This paper discusses best practices for functional, regression and load testing of .NET applications.

SCADA Security in Integrated Networks
As businesses leverage their SCADA systems by integrating them into the business networks, they must also assure the security of the SCADA system.

The Advantages of Small Form Factor HMI
HMIs have mutated and changed with new requirements, and they have become more flexible and capable. And while they've been doing that, they've become smaller and more useful.

9 Critical Requirements for Web Application Security
Learn why your Web applications expose dangerous security breaches and what’s required to effectively protect your Web applications and the sensitive information behind them.

 


Got a HOT tip?   please tell us!
Free weekly newsletter
Enter your email...
Click here for a profile of each sponsor:
PLATINUM SPONSORS
(Become a sponsor)

ADVERTISEMENT
(Advertise here)


Updated! The latest Windows-powered...

mobile phones!

other cool
gadgets

HOT TOPICS
Microsoft targets PNDs with new embedded OS
Microsoft tips .NET MF 3.0 highlights
Microsoft previews Windows Embedded Standard
Microsoft offers free Windows CE 6.0 textbook
Microsoft renames embedded operating systems
Microsoft unveils Windows Mobile 6.1
New Atom models target low-cost PCs
REFERENCE GUIDES
Windows Device Showcase
Intro to Windows Embedded
Intro to Shared Source
Real-time Windows Embedded
Windows Embedded books
Join our Windows Embedded discussion forums:
Windows XP Embedded
Windows CE
Windows Mobile


Windows Embedded developer newsgroups
Windows CE
XP Embedded
PocketPC
Smartphone

Microsoft's Windows Embedded resources
Embedded dev center
Mobile dev center
Windows CE tutorials
XP Embedded tutorials
Windows Embedded seminars
Windows Embedded application categories
3rd-party partners


BREAKING NEWS

• Superscalar ARM SoC runs Windows CE
• CE-based nav stack heads for CES
• Windows phone has dual displays
• Cortex-A8 SoC targets netbooks
• Palm "Nova" Linux set for CES debut?
• Editors' retrospective -- Windows-powered Devices in 2008
• Firefox mobile browser alphas released
• Box PC doubles as car computer
• Windows phone has dual active radios
• Windows PMP has dual-core CPU
• COM Express module sports Atom
• "Half-rack" network appliance runs Windows
• Cross-platform NAS runs Windows
• ARM to dominate MIDs?
• Toshiba launches first 512GB SSD


MOST POPULAR (last 90 days)
• "Netbook" uses Intel's Atom N270
• Windows CE takes on Linux in low-end netbooks
• HTC ups Touch resolution
• Microsoft unleashes new embedded OS
• Windows Mobile phone gets 800 x 480 display
• HTC spins WiMAX phone?
• Smart camera sports Atom
• Dual-core AMD netbook gets rave review
• Windows Mobile 7 "delayed"
• GPS phone uses new Marvell "Tavor" chip
MOST POPULAR (Classics from the vault)
Windows XP Embedded USB boot
Troubleshooting Windows XPe's blue screen "Stop 0x0000007B" error
Asus reveals $190 mini notebook
Windows Mobile 6 SDKs available for download
Windows Mobile VPN client plays with Cisco
HTC adds GPS to Windows Mobile Touch line
Microsoft unveils Windows Mobile 6.1
Guide to HTC's Windows Mobile smartphone platforms
• HTC releases Touch Diamond ROM upgrade
Customizing Windows XP Embedded thin clients

Also visit our sister sites:


Sign up for WindowsForDevices.com's...

news feed

Home  |  News  |  Articles  |  Polls  |  Forum  |  Directory  |  About  |  Contact
 

Ziff Davis Enterprise Home | Contact Us | Advertise | Link to Us | Reprints | Magazine Subscriptions | Newsletters
Tech RSS Feeds | White Papers | ROI Calculators | Tech Podcasts | Tech Video | VARs | Channel News

Baseline | Careers | Channel Insider | CIO Insight | DesktopLinux | DeviceForge | DevSource | eSeminars |
eWEEK | Enterprise Network Security | LinuxDevices | Linux Watch | Microsoft Watch | Mid-market | Networking | PDF Zone |
Publish | Security IT Hub | Strategic Partner | Web Buyer's Guide | Windows for Devices

Developer Shed | Dev Shed | ASP Free | Dev Articles | Dev Hardware | SEO Chat | Tutorialized | Scripts |
Code Walkers | Web Hosters | Dev Mechanic | Dev Archives | igrep

Use of this site is governed by our Terms of Service and Privacy Policy. Except where otherwise specified, the contents of this site are copyright © 1999-2008 Ziff Davis Enterprise Holdings Inc. All Rights Reserved. Reproduction in whole or in part in any form or medium without express written permission of Ziff Davis Enterprise is prohibited. Windows is a trademark or registered trademark of Microsoft Corporation in the United States and/or other countries and is used by WindowsForDevices under license from owner. All other marks are the property of their respective owners. WindowsForDevices is an independent publication not affiliated with Microsoft Corporation.