Multiport Ethernet Device

I am creating a miniport driver for a multiport ethernet device. Are there any strategies in creating one driver for 4 ports? The device will only show up as one device in the device manager. I need it to show up as 4 devices (4 different MACs), and thus, need a way for it to do this.

Generally you would create two drivers:

  1. A (KMDF) Driver associated with the actual device that enumerates 4 child
    [virtual] devices.
  2. A NDIS Miniport Driver associated with the 4 child devices that makes
    them behave as NICs.

It is my understanding that in some cases where resource assignments are not
inter-twined or shared, you can use the ‘in-box’ Multi-Function driver to
act as (1). I have never used MF.INF/MF.SYS so I can’t say much about it.

I have, however, used KMDF to create a Function Driver that enumerates child
sub-function devices that were Network devices. The only complication is
likely to be from the HW design and whatever short-cuts and resource sharing
are employed bringing 4 NICs out of one PCI device.

Good Luck,
Dave Cattley

Thanks. I am working with the ‘Multi-Function driver’ route. We currently use that for a serial device implementation.

One thing I am questionable on is how these show up in device manager. Should I create my own class, or use an existing class, such as Network Adapters, Ports, etc.?

For the child NIC the class will of course be “Net”.

I thought the parent device would be of class “MultiFunction” if using
MF.SYS/INF.

Good Luck,
Dave Cattley

Sounds good to me. I’ll try this out and post an update

It looks like I need to go the route of creating the function driver and the ONE miniport driver, or was it FOUR instances of the miniport driver, and one function driver? I need some background material on this. The problems I foresee are:

  1. Where should the transmit and receive interrupts be handled? Should there be 4 interrupt lines (in the case of 4 ports), and I register for interrupts to NDIS?

  2. Memory allocation problems. What happens if one port fails? Should all of them fail if there is only one initialization handler (as it is one driver)?

I would hope you would need only create on NDIS Miniport Driver. I cannot imagine how you would need to end up with a different driver to service the four ports. They are four of the same, yes? And the interface to the hardware exposes them as some sort of divisible set of resources that are more or less identical except for register offset location and or bit offset location in registers? As for your other questions we cannot possibly answer them. Talk to your hardware guys. If they designed the board such that it partitions the resources without any sharing the you ought to be able to use MF.SYS to carve them up and build an NDIS miniport that talks to the hardware. If they completely ignored how to build a MF PCI device so that an OS can actually deal with it sanely figuring that ‘hey, its only software, they can sort that out in the driver and well it works in our test harness’ then you are stuck. You will need to build the HW access layer for your device in the parent driver and expose an interface on the enumerated PDOs of the child so that you NDIS Miniport can then use the interface to interact with the ‘port’ associated with the PDO. Good Luck,Dave Cattley

The multifunction driver solution is good. The ports access different offsets into the same resources. However, I need to lock access to a register. More so, one of the registers (for each port) points to the same interface, and I need a way to know if one port is already accessing that register.

Any clues on how to do this in software?

You’re not really listening to what Dave Cattley is telling you. If you
need to “lock access” to anything, you can’t use MF.sys. You need to write
a bus driver. All the logic to control your device goes in that driver.
You then enumerate four PDOs, one for each port. Then you supply an NDIS
miniport that just thunks NDIS calls into your bus driver.

Jake Oshins
Windows Kernel Team

This message offers no warranties and confers no rights.

wrote in message news:xxxxx@ntdev…

The multifunction driver solution is good. The ports access different
offsets into the same resources. However, I need to lock access to a
register. More so, one of the registers (for each port) points to the same
interface, and I need a way to know if one port is already accessing that
register.

Any clues on how to do this in software?

> Any clues on how to do this in software?

Two drivers as noted earlier. The Function Driver for the actual HW will
enumerate 4 child PDOs on which you will need to supply an NDIS Miniport
driver. For some inspiration see the Vista/Longhorn WDK (6001) samples
NDISEDGE and PCIDRV. They are in the KMDF samples.

Good Luck,
Dave Cattley

So reading through the forums, it looks like my bus driver cannot split resources obtained from a BAR and pass them to the child devices using ‘EvtDeviceResourceRequirementsQuery’. Apparently this what mf.sys does as a arbiter, but this interface is not provided my Microsoft.

  1. I am going to create an interface that stores the offsets into the BAR for each miniport instance, and also keeps track of how many instances have accesses the interface (so I know which port is which). Is this possible?

  2. Also, what is a good way for to create functions for the miniport drivers to access memory only the BUS driver should access? Can I create function pointers in the interface that is passed to drivers accessing the interface? Are these serial accesses or do I need to create a locking scheme.

On 23-Sep-2012 19:04, xxxxx@gmail.com wrote:

So reading through the forums, it looks like my bus driver cannot split resources obtained from a BAR and pass them to the child devices using ‘EvtDeviceResourceRequirementsQuery’. Apparently this what mf.sys does as a arbiter, but this interface is not provided my Microsoft.

  1. I am going to create an interface that stores the offsets into the BAR for each miniport instance, and also keeps track of how many instances have accesses the interface (so I know which port is which). Is this possible?

Yes

  1. Also, what is a good way for to create functions for the miniport drivers to access memory only the BUS driver should access? Can I create function pointers in the interface that is passed to drivers accessing the interface? Are these serial accesses or do I need to create a locking scheme.

This is the advantage of exporting function pointers rather than
pointers directly to the memory. You can do any locking you like.

–pa

Thanks Pavel. I will attempt this design.

Before bumping into ndis+bus driver route, one should consider multiplexing
it at PCI level if you design the HW.

Most if not all multiport ethernet NICs on the market expose to the os as
PCI multi-function device for the *ethernet part* – that’s one MAC per PCI
function.

I do have a ndis+bd solution but it’s solving completely different problems
that have no other viable choice at the time. As I said before, it’s fun to
play with but you will be running into problems depending on how you deploy
it.

Good luck!
Calvin

On Sun, Sep 23, 2012 at 11:46 AM, wrote:

> Thanks Pavel. I will attempt this design.
>
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
>

I think you need to look at the problem differently. As Calvin just said,
on another branch of this thread, most people choose to use PCI.sys as the
driver that breaks out the separate ports and enumerated multiple
NDIS-miniport child devices. This, however, requires adherence to the PCI
spec for each function, and that’s hard to pull off if you didn’t start your
hardware design that way.

Given that you already have a design which has the control of the multiple
ports intermingled, it’s probably best to put all the control logic for the
entire device in your parent bus driver. Don’t try to pass ranges of MMIO
space or interrupts to the child devices. This, in naïve designs, usually
leads to really hard issues to solve later. Just use the NDIS miniports as
thunking layers to call into your bus driver.

Jake Oshins
Windows Kernel Team

This message offers no warranties and confers no rights.

wrote in message news:xxxxx@ntdev…

So reading through the forums, it looks like my bus driver cannot split
resources obtained from a BAR and pass them to the child devices using
‘EvtDeviceResourceRequirementsQuery’. Apparently this what mf.sys does as a
arbiter, but this interface is not provided my Microsoft.

  1. I am going to create an interface that stores the offsets into the BAR
    for each miniport instance, and also keeps track of how many instances have
    accesses the interface (so I know which port is which). Is this possible?

  2. Also, what is a good way for to create functions for the miniport drivers
    to access memory only the BUS driver should access? Can I create function
    pointers in the interface that is passed to drivers accessing the interface?
    Are these serial accesses or do I need to create a locking scheme.

A multifunction device for our design isn’t possible right now. I am working with one of the two options:

  1. The bus driver handles all the hardware access and communicates interrupts to the lower level drivers.

  2. The bus driver handles the functions that need to be locked, and exposes them through interfaces. The miniport driver handles the interrupts.

I know option 1 is the best option, so that may be the actual design used. I have created a bus driver that does option 2 already.

I’m still not sure why I just can assign specific resources (as done in MF.sys) to the child devices, and keep the functions that need to be locked in the interface. Is it because the way it is done in MF.sys is not readily available in documentation?

> I’m still not sure why I just can assign specific resources (as done in MF.sys) to the child devices, and keep the functions that need to be locked in the interface. Things will get very interesting if you need to access that shared register at DIRQL (or synchronized with one or all of the ISRs). At some point your design boils down to a HW abstraction layer (potentially very ‘thin’). What does it matter if it is in the PDO accessed via an interface or in your miniport? Sure, NDIS can parse out the resources for you, provide a ISR, etc. but so can KMDF. There may be other subtle reasons why letting NDIS think it is dealing with HW could not be what you want. For example I think resources associated with the PDO will cause NDIS to behave as the power policy owner. I can’t recall if that is precisely true or even if it will have any effect but perhaps Mr. Tippet, Mr. Hollan, or someone with far less memory rot than I would be so kind as to comment. Good Luck,Dave Cattley

> There may be other subtle reasons why letting NDIS think it is dealing with HW could not be what you want.? For example? I think resources associated with the PDO?will cause NDIS to behave as the power policy owner.?
?
NDIS is always the power policy owner. Its decisions are based on the DEVICE_CAPABILITIES structure that the bus hands up, not the presence/absence of resources.

There isn’t actually much that changes in NDIS if you hide the resources in the PDO, vs exposing them in the FDO. Obviously, the APIs you’ll use are spelled differently - WdfInterruptCreate vs NdisMRegisterInterruptEx. Beyond that, RST is the only thing I can think of that breaks when you hide your resources in the PDO. ( http://msdn.microsoft.com/library/ff570441 ) RST is not an *essential* feature, but it can be helpful if you are a 1Gbps part targeting client OSes.

USB gadgets (for example) do not expose their resources to NDIS, so they serve as a proof of concept for the NDIS interaction. These gadgets interact with the network stack just fine. (RST does not work with USB gadgets, but fortunately they rarely seem to indicate more than 480Mbps of traffic for some mysterious reason.)

I created a PDO in my bus driver for my miniport driver. For some reason I cannot obtain the interface created by my bus driver. It keeps failing with STATUS_NOT_SUPPORTED. Below is my code:

----- BUS DRIVER CODE ----
WDF_QUERY_INTERFACE_CONFIG_INIT(
&query_interface_config,
(PINTERFACE) &sel_3390_mac_interface,
&GUID_TOASTER_INTERFACE_STANDARD,
NULL);

// If you need multiple interfaces, you can call WdfDeviceAddQueryInterface
// multiple times to add additional interfaces.
status = WdfDeviceAddQueryInterface(device, &query_interface_config);

----- MINIPORT CODE -----
Driver Entry —>
nt_status = WdfDriverCreate(
DriverObject,
RegistryPath,
WDF_NO_OBJECT_ATTRIBUTES,
&config,
&driver);

Initialize Hanlder ---->
// NdisMGetDeviceProperty function enables us to get the:
// PDO - created by the bus driver to represent our device.
// FDO - created by NDIS to represent our miniport as a function
// driver.
// NextDeviceObject - deviceobject of another driver (BUS Driver)
// attached to us at the bottom.
// But if we were to talk to a driver that we
// are attached to as part of the devicestack then NextDeviceObject
// would be our target DeviceObject for sending read/write Requests.
NdisMGetDeviceProperty(
MiniportAdapterHandle,
&adapter->pdo,
&adapter->fdo,
&adapter->next_device_object,
NULL,
NULL);

nt_status = WdfDeviceMiniportCreate(
WdfGetDriver(),
WDF_NO_OBJECT_ATTRIBUTES,
adapter->fdo,
adapter->next_device_object,
adapter->pdo,
&adapter->wdf_device);
if (!NT_SUCCESS(nt_status))
{
status = NDIS_STATUS_FAILURE;
break;
}

nt_status = WdfFdoQueryForInterface( <– fails with STATUS_NOT_SUPPORTED
adapter->wdf_device,
&GUID_TOASTER_INTERFACE_STANDARD,
(PINTERFACE) &adapter->bus_interface,
sizeof(TOASTER_INTERFACE_STANDARD),
1,
NULL);// InterfaceSpecific Data

xxxxx@gmail.com wrote:

I created a PDO in my bus driver for my miniport driver. For some reason I cannot obtain the interface created by my bus driver. It keeps failing with STATUS_NOT_SUPPORTED. Below is my code:

Well, I can tell you that this pattern works, because I’ve done it.
You’re sure the device stack is correct? The bus driver exposes a PDO,
and your miniport is loaded on top of that PDO? You’re sure you’ve set
up your “sel_3390_mac_interface” correctly? You’ve defined Size and
Version correctly?


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.