Sample StorPort Virtual Miniport

 

The sample is a StorPort virtual miniport that presents the appearance of 1 or more Fibre Channel Host Bus Adapters (HBA). Under an HBA, the sample creates LUNs/disks, which can be formatted and used by a file system such as NTFS.

A StorPort virtual miniport is much like a StorPort real miniport. A virtual miniport differs in several ways:

1.     The virtual miniport does not control hardware in a way supported by StorPort. It may conceivably control hardware by other means.

2.     Since there is no StorPort support for hardware control, the miniport does not use DMA or DMA operations (via StorPort APIs, that is). There is no Interrupt object or lock.

3.     The miniport can employ any API documented in the WDK for WDM drivers.

A virtual miniport is like a real miniport in important ways:

1.     StorPort as port driver handles PnP and power operations.

2.     StorPort supports the handling of other I/Os with the miniport’s support (through callbacks). That handling makes it possible for miniport-provided LUNs to be handled much as any other disk might be handled, including having a drive letter, mounting a file system and doing open, read/write, close and other kinds of I/O.

3.     StorPort handles the details of I/O queuing when and as needed (e.g., queue depth, pausing, resuming).

4.     Along with ClassPnP, StorPort can retry I/Os.

The sample assumes some familiarity with StorPort miniports. Sample documentation is minimal, consisting of this file and of comments in the sample’s buildable files. The WDK should be studied for more information about miniports.

The files

These are the sample files, with some important routines or pieces noted:

1.       mp.c

a.    DriverEntry()
Gets some resources, call StorPortInitialize().

b.    MpHwFindAdapter()
Gets more resources, sets configuration parameters.

c.     MpHwStartIo()
Entry point for an I/O. This calls the appropriate support routine, e.g., ScsiExecuteMain().

2.       scsi.c

a.     ScsiExecuteMain()
Handles SCSI SRBs with opcodes needed to support file system operations by calling subroutines. Fails SRBs with other opcodes.
Note: In a real-world virtual miniport, it may be necessary to handle other opcodes.

b.    ScsiOpInquiry()
Handles Inquiry, including creating a new LUN as needed.

c.     ScsiOpVPD()
Handles Vital Product Data.

d.    ScsiOpRead()
Beginning of a SCSI Read operation.

e.    ScsiOpWrite()
Beginning of a SCSI Write operation.

f.      ScsiReadWriteSetup()
Sets up a work element for SCSI Read or Write and enqueues the element.

g.     ScsiOpReportLuns()
Handles Report LUNs.

3.       wmi.c

a.     HandleWmiSrb()
Handles WMI SRBs, possibly by calling a subroutine.

b.    QueryWmiDataBlock()
Supports WMI Query Data Block.

c.     ExecuteWmiMethod()
Supports WMI Execute Method.

4.       utils.c

a.     MpQueryRegParameters()
Does registry lookup of parameters.

5.       WkRtn.c

a.     MpGeneralWkRtn()
Handles queued work elements by calling MpWkRtn.

b.     MpWkRtn()
Handles work elements, completes them.

6.       sources: Build directives

a.      Warning level; optimization level.

b.      Files to build.

c.       Include and targetlib directories.

d.      WPP directives.

e.      .inx and MOF handling.

7.       makefile.inc: More build directives

a.      Building .inf file.

b.      MOF handling.

8.       Header files under the inc subdirectory.

a.     mp.h
Main header file.

b.     mpwmi.h
Generated by build.

c.      trace.
WPP directives.

d.      trcmp.ini
More WPP directives.

9.       mp.inx:

Template for building mp.inf. Values under pnpsafe_isa_addreg cause registry settings.

a.     VirtualDiskSize
Size of an in-memory LUN/disk in bytes. If this doesn’t match PhysicalDiskSize, PhysicalDiskSize will override.

b.    PhysicalDiskSize
Size of an in-memory LUN/disk in bytes.

c.     NbrLUNsperHBA
Number of in-memory LUNs/disks.

d.    CombineVirtDisks
Combine the data buffers for in-memory LUNs/disks if set to 1.

10.   mp.mof: WMI class directives.

MSFC class directives are done by including hbaapi.mof, which isn’t in the sample but which should be copied from %WinDir%\system32\wbem on the target system before building.

11.   mp.rc: Resource file, including mp.bmf, the binary (built) form of mp.mof.

12.   ReadMe.htm: This file.

Building

The sample should be built with the Win7 WDK (7600.16385.1) or later. One can build for Win2003, Vista/Win2008 or Win7/Win2008 R2, for x86 or x64, for free or checked. (Win8 Developer Preview has been found to work with the sample built for Win7 x64 free.) The build should complete without errors or warnings.

1.       Open a build window.

2.       Go the sample directory.

3.       Copy hbaapi.mof from %WinDir%\system32\wbem to the sample directory.

4.       For a full build, do bcz. For a build processing only files changed since the last full build, do bz.

5.       If the target system is Win2008 x64 or any later x64 system, the driver binary mp.sys must be signed, e.g., test-signed. Signing is not covered here.

Installing

1.     Once the build and signing (if needed) are done, copy these files to the test (debuggee) system in a working directory:

mp.sys, mp.inf, the appropriate WDF coinstaller (e.g., WdfCoInstaller01009.dll for WDK 7600) and devcon.exe

The WDF coinstaller can be found under the appropriate architecture directory in the WDK, e.g., c:\WinDDK\7600.16385.1\redist\wdf\amd64. Similarly, devcon.exe can be found in the WDK, e.g., c:\WinDDK\7600.16385.1\tools\devcon\amd64.

2.     Login to the test system with administrator privileges.

3.     If the driver is test-signed, do bcdedit /set testsigning on in an elevated window and reboot.

4.     In an elevated window on the test system, where the current directory is the working directory, do devcon install mp.inf root\mp. If the system is x64 and if the driver binary is test-signed, say OK to the prompt to install.

5.     If one wants a second (or third …) instance of the virtual HBA, repeat step 4) above. (There will not be a prompt about installing a test-signed driver on a second or later installation.)

Uninstalling

1.       Login as an administrator to the test system.

2.       In an elevated window, do devcon remove root\mp to uninstall the miniport.

3.       In an elevated window, do sc delete mp to remove the driver service.

4.       Delete mp.sys from %WinDir%\system32\drivers.

5.       Reboot.

Exercising the sample

The following assumes that the test system is Win7/Win2008 R2 and that one or more instances of the virtual HBA have been installed (see installation by devcon).

1.       Login as an administrator to the test system.

2.       Start Device Manager (e.g., diskmgmt.msc).

a.     On one of the miniport’s LUNs, where the disk is described as “Unknown,” right-click and choose Online.

b.     Right-click again in the same place and choose Initialize Disk.

c.      Right-click on the same disk, where the disk is described as “Unallocated,” and choose New Simple Volume. Follow the instructions.

d.     Right-click on the same disk, where “New Volume” is shown, and choose Explore, to start Windows Explorer on the newly formatted disk.

3.       Start Windows Explorer

a.      Create a directory.

b.      Under that directory, create a file.

4.       Start Storage Explorer (StorExpl.msc). The miniport will appear under the Servers node. (Note: The miniport will not appear under Fibre Channel Fabrics.)

5.       In an elevated window, start wbemtest.exe.

a.      Click on Connect and connect to root\WMI.

b.      Click on Enum Classes and click OK.

c.       Scroll down to the MSFC classes. Choose one, such as MSFC_FibrePortHBAAttributes.

d.      Click on Instances.

e.      Double-click on an instance.

f.       Click on Show MOF and examine the data.

High-level logic

1.    DriverEntry() gets control because the miniport is a WDM driver for the FDO device object enumerated off the PnP root. DriverEntry() calls StorPortInitialize() with initial configuration parameters. StorPort takes over the miniport’s entry points defined in the driver object, e.g., AddDevice and InternalDeviceIoControl (IRP_MJ_SCSI).

2.     MpHwFindAdapter() gets control as part of the initialization of a virtual HBA. (There is 1 virtual HBA for each installed instance of the miniport.) More configuration parameters are set.

3.     MpHwStartIo() gets control for an I/O in the form of a SCSI Request Block (SRB). The routine calls appropriate subroutines.

a.     ScsiExecuteMain() is the subroutine called for SCSI-type (SRB_FUNCTION_EXECUTE_SCSI) SRBs.

                                                            i.      ScsiOpRead() and ScsiOpWrite() are called for SCSI Read and Write, respectively. Each calls ScsiReadWriteSetup().

                                                            ii.      ScsiReadWriteSetup() creates a work element and enqueues it.

                                                            iii.      MpGeneralWkRtn(), running under a kernel-mode thread in System, dequeues a work element, does the work and calls StorPortNotification() to complete the I/O.

b.      HandleWmiSrb() is the subroutine called for WMI-type (SRB_FUNCTION_WMI) SRBs.

c.       MpHwHandlePnP() is the subroutine called for PnP-type (SRB_FUNCTION_PNP) SRBs.

MpHwStartIo() completes the I/O if it is not completed elsewhere.

4.     MpHwFreeAdapterResources() gets control when the virtual HBA is being removed (Remove Device IRP).

Notes

1.     The backing store for the LUNs is virtual memory. Consequently the contents are lost upon reboot or upon disabling the HBA.

2.     Because there is no DMA object, BuildIo, Interrupt and DPC callbacks from StorPort won’t get control.

3.     The sample has support for MPIO testing in that it allows 2 (or more) virtual HBAs to share buffers for each LUN presented. It is probably best to ignore this feature, which was developed for certain tests. This feature is retained for completeness, but the file mp.inx does not create the registry flag needed to bring MPIO support into play.

4.     Support for virtual miniports was introduced as an update in Win2003 SP1; refer to http://support.microsoft.com/?kbid=943295.

5.     WPP tracing is supported. To get verbose tracing, do (in an elevated window beginning with Vista): tracelog /start myMPTrace /guid #C689C5E6-5219-4774-BE15-9B1F92F949FD /f tracelogoutMP /flags 0xFFFF /level 5 /min 32 /max 64 /UseSystemTime /b 2048