multiple devices, single driver

Alexander Boettcher alexander.boettcher at genode-labs.com
Thu Oct 25 14:16:35 CEST 2018


On 25.10.18 09:38, Joel Nider wrote:
>> On 23.10.18 14:50, Joel Nider wrote:
>>> I have been looking at several drivers in Genode, and they all seem to 
> 
>>> have static data - specifically a Heap object and Root object.  I am 
>>> wondering with this kind of setup, is it possible to manage more than 
> one 
>>> device with a single driver?
>>
>> of course. As described in the Genode book [0] in chapter 3.2.3, the
>> root object provides the implementation just of the interface. Whenever
>> a client connects to a service (like a driver for nic, ahci, nvme, usb
>> etc.) a session is established via this interface. The driver may
>> associate (typically does so depending on your specified policy) one
>> specific device it drives to this session - as done e.g. for drivers
>> handling multiple devices, e.g. ahci, nvme, usb.
> 
> I will give you my situation as a specific example. I am writing a driver 
> for a PCIe attached NIC (x86 platform). Let us say that I have 2 physical 
> NICs in my machine with the same device ID and vendor ID. I have specified 
> in my config file that I have a driver called "nic_drv", without 
> specifying the PCIe address (copied from the example in 
> repos/os/run/ping.run).
> 
> When the driver starts, I can enumerate the PCIe devices through the 
> Platform::Connection object that is instantiated from the 'env' object. I 
> see all PCIe devices of class 'NET' (even other NICs that I don't want my 
> driver to handle). So far so good. I can filter through the devices by 
> requesting the capability (with Platform::Device_client) and I can read 
> the device ID and vendor ID and pick the devices I want to handle.

Actually, in this case, I would not encourage to implement it in one
driver. The network cards are independent (as opposed for devices on a
ahci controller) from each other, so just start/instantiate the driver
two times. With that you cleanly isolate the network data.

For that to work, you have to configure the platform driver (the guard
to the PCIe bus on Genode) [0] to hand out the first driver one network
card (described as PCI bus device function) and for the second driver
the other network card (described by another PCI bus device function).

[0]
https://github.com/genodelabs/genode/blob/master/repos/os/src/drivers/platform/spec/x86/README

> Now I have a list of several devices that I want my driver handle. If I 
> understand you correctly, I should have only one Root object (and one Heap 
> object). That implies I should also only call parent().announce() once. 
> But then how do I instantiate my Nic::Session_component once per device? 
> What is happening so far, is that some time after I call 
> parent().announce(), my Nic::Session_component derived class gets 
> instantiated, and the constructor is called. But I have no way of knowing 
> which device it is meant to handle, since there is no mechanism for 
> passing the device capability to Nic::Session_component. In addition, I 
> only see this constructor being called once. I expected to see one 
> constructor per PCIe device. This causes further problems such as not 
> being able to map the mmio region since the size and base address are not 
> known until I query the PCIe BAR, and there is no 'new' operator 
> available, which means to me I'm doing something fundamentally wrong.
> 
> So what is the correct way to build the driver such that I get an object 
> per device (and the object knows the device)?

As said, I would not go further this route in your case, since what you
are asking for does not match your use-case.

Nevertheless, it is possible, as example look into the ahci driver [1].
In short, when a client calls you, the _create_session method is called,
there you need some differentiator to decide, which session gets which
device.

[1] repos/os/src/drivers/ahci/main.cc

In the ahci driver case one has to configure it by a label and a device
argument in the policy. Analogously, for the network driver it could
hypothetical look like this :

<start name="my_nic_drv">
 ...
 <provides><service name="Nic"/></provides>
 <config>
   <policy label="network-black" device="1" />
   <policy label="network-red" device="2" />
 </config>
</start>

<start name="client-a">
...
  <route>
     ...
     <service name="Nic">
       <child name="my_nic_drv" label="network-black"/>
     </service
  </route>
</start>

<start name="client-b">
...
  <route>
     ...
     <service name="Nic">
       <child name="my_nic_drv" label="network-red"/>
     </service
  </route>
</start>

In your _create_session method implementation you would evaluate for the
device arguments and knows which device to which client belongs.

Further, as you can see in the ahci driver, you can of course use 'new'
if you specify a allocator.


Hope it helps,

Alex.

-- 
Alexander Boettcher
Genode Labs

https://www.genode-labs.com - https://www.genode.org

Genode Labs GmbH - Amtsgericht Dresden - HRB 28424 - Sitz Dresden
Geschäftsführer: Dr.-Ing. Norman Feske, Christian Helmuth



More information about the users mailing list