07-16-2013 05:55 AM
I was looking up how to write drivers and I saw that drivers in kernel space usually need to have a certain format - they need init and exit module and they need file operations to read write and what have you, depending on the driver. None of the Xilinx Linux Github repo have any of the file operations .write, .read, .owner, anything. Is there a reason why these drivers are different?
07-16-2013 09:19 AM
The file_operations structure typically only applies to "character" device drivers. Some specific xilnx examples include:
Other types of device drivers tend to have different interfaces, and hence not file_operatons. For example, the xilinx_emacps.c driver (etherent driver) has struct net_device_ops.
So, there is nothing unusual about the Xilinx drivers in this regard. They have init and exit functions, they have platform_device hooks for probing, etc.
07-16-2013 10:30 AM
I see. Thanks for your response. Are the others block drivers then? Or is there not necessarily only these two types? I thought about character drivers because the example I was looking at (Digilent's hands on embedded guide) was writing to the leds and it was writing only characters. That kind of gave me a hint. However I think you made it more clear.
07-16-2013 11:29 AM
Yes, there are all sorts drivers possible in Linux; the char, block, network types are just some of the more common ones. You can really load pretty much anything into a kernel driver, it's all just a question of how that code subsequently gets called.
For example, if two drivers share a lot of common processing logic, then that common portion could be put into its own driver. This new module would do nothing on its own (eg. no init function) but would simply export some functions that can be called from the actual driver. Some of the kernel cryptography functions more-or-less fall into this category.
07-16-2013 01:40 PM
I see. But these are kernel objects right? Similar to the output of a compiled C program? When I do gcc -o myfile.c, I get a.out which is similar to what these drivers are compiled as. I can run a.out but I can't use the functions contained within that file. Is there any way to actually run those functions like you can when you open a character driver as a file and write a char to it?
07-16-2013 03:11 PM
A closer analogy would be gcc -c option, meaning to compile only, not link. Rather than a.out, this produces myfile.o, which is not an executable, but does contain the compiled code. Conceptually, you can think of it as a shared library (*.a or *.DLL).
It is possible to call driver functions directly. However it is seldom a good idea, unless you are very familiar with the code being called. You might very easily side-step some important safety checks, locking restrictions, or other guards.
The better way to trigger the driver is just simply to send data to/from the /dev entry, at least for char and block devices. This is easily done with simple tools like "echo", "cat", and "dd".
07-17-2013 06:02 AM
But these are not to be done recursively aren't they? Wouldn't it be very inefficient to transfer data over the DMA to my hardware peripheral by repeating cats?
07-17-2013 12:47 PM
I was suggesting them mostly for testing purposes. But note that you can send quite large amounts of data even with something simple like "dd". For example it's easy to send megs or gigs of data, without much overhead.
For production use, you will likely have a program that issues read/write commands on /dev/whatever, or it might use mmap() to create a shared memory mapping to avoid needing to copy back and forth from userspace to kernel.