How to bind my platform driver to an ACPI Container device - linux-kernel

My Laptop has following SuperIO device in the SSDT Table:
DefinitionBlock ("", "SSDT", 1, "VENDORx", "TABLEx", 0x00001000)
{
Device (\_SB.PC00.LPCB.SIO0)
{
Name (_HID, EisaId ("PNP0A05") /* Generic Container Device */)
Name (_UID, "SD28301")
}
This ID claimed by the ACPI container driver but I see in /sys/bus/container/* that there is no driver associated with this device.
I wanted to write a platform driver to attach with this device. I have the following in my driver code:
static const struct acpi_device_id sio_device_ids[] = {
{ "PNP0A05", 0},
{ "", 0}
};
MODULE_DEVICE_TABLE(acpi, sio_device_ids);
Upon calling platform_driver_register(), my driver does not get bound to the SIO device. To see if kernel is even trying to match the acpi_device_id entries, I changed PNP0A05 in my kernel code to MHF1234 (custom _HID). Then I inserted an SSDT with a device that had _HID same as acpi_device_id in kernel driver like this: Name (_HID, EisaId ("MHF1234"). Now, upon inserting my driver, the probe function got called so my driver matched with the ACPI device.
Question: How do I match my driver with PNP0A05 device? I see that the ACPI container driver already detected and added this to /sys but there is no driver bound to it. Any hints to debug would be appreciated.

The device is being created by the code under drivers/acpi/container.c. However, it's purely ACPI device for now. The platform devices for ACPI ones are created by acpi_create_platform_device() which is supposed to be called by acpi_bus_attach() (via acpi_default_enumeration() because it's not enumerated by parent). However, container_device_attach() on success returns positive number, i.e. 1, and acpi_bus_attach() skips platform device creation due to the conditional. That's why it's not being represented as platform device and hence may not be enumerated via platform bus.
Besides that, ACPI specification tells us the following: PNP0A05 Generic Container Device. A device whose settings are totally controlled by its ACPI resource information, and otherwise needs no device or bus-specific driver support. This was originally known as Generic ISA Bus Device. This ID should only be used for containers that do not produce resources for consumption by child devices. Any system resources claimed by a PNP0A05 device’s _CRS object must be consumed by the container itself.

Related

How do i add rhproxy to the ACPI Table

i try to use the SPI Bus of my custom board threw windows 10 IoT Enterprise. I use a Intel Atom X5 E3930 CPU on a Congatec SA5 module.
i found the rhproxy driver in the system folder and checkt the boot option of it and i checked if he is running.
-> the result is the proxy is runnung but i can't find it in the device tree and my software example could not open any connection to the SPI device. The Handle of the device is still NULL
i checked the ACPI Table and could not find any entries about the rhproxy.
now my question.
how can i get the ACPI entry for rhproxy or is there any way to modify the ACPI table.
regards
If you need to provide user mode Universal Windows Platform (UWP) API access to simple buses like I2C, GPIO and SPI, you need make sure that ACPI table in your UEFI firmware contains appropriate entries for RHProxy. Please refer to user mode access for more information. You may try to create a .NET app that uses AcpiGenFx to generate ACPI tables, please refer to this document.
thanks for the answer, it was very useful for me.
now i can see my rhproxy at the device manager but i can't get access to my spi bus.
my Spi bus is connected over an PCI bus to my cpu, how do i tell the rhproxy ther will be a device.
static void Main(string[] args)
{
x86Platform platform = Platforms.Createx86Platform(
//ArmPlatform Platform = Platforms.CreateArmPlatform(
OEMID: "MSFT",
OEMTableID: "EDK2",
CreatorID: "MSFT",
Revision: 1,
FileName: "SSDT"
);
platform.SSDT = true;
var rh = platform.AddGenericDevice("RHPX", "MSFT8000", "MSFT8000", 1);
rh.AddSerialPort(AutoAcpi.SerialPortType.Serial, "SPI1", "7270", 0x5AC2);
platform.WriteAsl();
}
this is the code i used to define the proxy.
thanks for your help
Regards

Accessing Platform Device from Userpace

From a general standpoint, I am trying to figure out how to access a platform device from userspace. To be more specific, I have a EMIF controller on and SoC of which I have added to my device tree and I believe it is correctly bound to a pre-written EMIF platform device driver. Now I am trying to figure out how I can access this EMIF device from a userspace application. I have come accross a couple different topics that seem to have some connection to this issue but I cannot quite find out how they relate.
1) As I read it seems like most I/O is done through the use of device nodes which are created by mknod(), do I need to create a device node in order to access this device?
2) I have read a couple threads that talk about writting a Kernel module (Character?, Block?) that can interface with both userspace and the platform device driver, and use it as an intermediary.
3) I have read about the possibility of using mmap() to map the memory of my platform device into my virtual memory space. Is this possible?
4) It seems that when the EMIF driver is instantiated, it calls the probe() fucntion. What functions would a userpace application call in the driver?
It's not completely clear what you're needing to do (and I should caveat that I have no experience with EMIF or with "platform devices" specifically), but here's some overview to help you get started:
Yes, the usual way of providing access to a device is via a device node. Usually this access is provided by a character device driver unless there's some more specific way of providing it. Most of the time if an application is talking "directly" to your driver, it's a character device. Most other types of devices are used in interfacing with other kernel subsystems: for example, a block device is typically used to provide access from a file system driver (say) to an underlying disk drive; a network driver provides access to the network from the in-kernel TCP/IP stack, etc.
There are several char device methods or entry points that can be supported by your driver, but the most common are "read" (i.e. if a user-space program opens your device and does a read(2) from it), "write" (analogous for write(2)) and "ioctl" (often used for configuration/administrative tasks that don't fall naturally into either a read or write). Note that mknod(2) only creates the user-space side of the device. There needs to be a corresponding device driver in the kernel (the "major device number" given in the mknod call links the user-space node with the driver).
For actually creating the device node in the file system, this can be automated (i.e. the node will automatically show up in /dev) if you call the right kernel functions while setting up your device. There's a special daemon that gets notifications from the kernel and responds by executing the mknod(2) system call.
A kernel module is merely a dynamically loadable way of creating a driver or other kernel extension. It can create a character, block or network device (et al.), but then so can a statically linked module. There are some differences in capability mostly because not all kernel functions you might want to use are "exported" to (i.e. visible to) dynamically loaded modules.
It's possible to support mapping of the device memory into user virtual memory space. This would be implemented by yet another driver entry point (mmap). See struct file_operations for all the entry points a char driver can support.
This is pretty much up to you: it depends on what the application needs to be able to do. There are many drivers in the kernel that provide no direct function to user-space, only to other kernel code. As to "probe", there are many probe functions defined in various interfaces. In most cases, these are called by the kernel (or perhaps by a 'higher level "class" driver') to allow the specific driver to discover, identify and "claim" individual devices. They (probe functions) don't usually have anything directly to do with providing access from user-space but I might well be missing something in a particular interface.
You need to create a device node in order to access the device.
The probe function is called when the driver finds a matching device.
For information on platform device API, the following articles could be useful.
The platform device API
Platform devices and device trees

Accessing device configuration space - win kernel PCI device

I'm writing method to get pci device, given vendor id, device id programmatically (just like pci_get_device from Linux kernel).
For that I need to get device object configuration. I read from here for the same: http://msdn.microsoft.com/en-us/library/windows/hardware/ff558707(v=vs.85).aspx
Now to test this, I made fake driver - service installation framework, which will install my I/O device driver and in that from DriverEntry I can test this PCI functionality.
But OS crashes with irql_not_less_or_equal, at
irp = IoBuildSynchronousFsdRequest(IRP_MJ_PNP,
targetObject,
NULL,
0,
NULL,
&event,
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> &ioStatusBlock);
Can anyone tell me what's wrong with that, (I'm calling this from Driver Entry, and passing current installing driver's deviceObject.)
You don't have a valid PDO in DriverEntry(). DriverEntry roughly corresponds to main() in user space application and is called first thing after driver load into memory. DriverEntry main purpose is to register the driver with the OS and its code is independent of actual device(s). You can have a PDO only after the OS has called your initialization callback (after it has recognized your device) - and the callback will be called after DriverEntry completion (actually, the callback should be provided to the OS as part of the driver registration inside the DriverEntry()).

Can Linux USB probe order be changed or controlled?

I am new to Linux and I need to write a USB driver for a device with 2 interfaces. One interface is HID class (3/0/0) with one interrupt in endpoint and a report descriptor. The other interface is vendor defined with 3 bulk endpoints. In my usb_device_id table I have a USB_DEVICE entry with the VID and PID.
When I plug in the device, my xxx_probe function is called for the vendor defined interface but not for the HID interface. Instead, it appears that a built-in driver called 'generic-usb' is taking control of the HID interface.
Is there a way to ensure that my driver probe function is called first?
Why doesn't Linux make multiple passes looking for a more specific driver first (like Windows does)?
Alternatively, can the 'generic-usb' driver be used to receive data on the interrupt endpoint and to set reports and features on the control pipe?
It appears that libusb-1.0.8 allows an application to take control of interfaces on an attached device without the need of a custom driver. So far it appears to provide all the support that I need.

In Linux 2.6 device driver model, what's the entry point of the creation of struct device?

If a USB device driver is loaded, and at some time the device plugs in, then which part of the kernel will create struct device and register it?
When the driver is loaded, the system calls the function, which you assigned in module_init. You will want to call there usb_register(struct usb_driver skel_driver), where skel_driver is a struct with pointers to methods servicing the device, like the probe method.
The probe method is the one which is called, when a new usb device is introduced in to the system. In this place you can fill your struct (usb_skel) with what you will need in the future, initiate a char device or whatever you do, when the device is introduced.
The system mostly won't create anything by itself, it has to have most of the structs prepared and filled with device specific data.
Please see usb-skeleton in lxr for reference and learn to use it, besides read writing usb drivers from LDD.
Cheers

Resources