Dynamic Kernels: Discovery
init_module() calls the function skel_find() to perform the dirty task of detecting if a board is there. The function is very device specific, because each device must be probed for its peculiar features; thus, I won't try to show code to perform the actual probing, but only IRQ autodetection.
Unfortunately, some peripherals can't tell which IRQ line they're configured to use, thus forcing the user to write the IRQ number on the command line of insmod, or to hardcode the number in the software itself. Both these approaches are bad practice, because you just can't plug the board (after setting the jumpers) and load the driver. The only way to autodetect the IRQ line for these devices is a trial-and-error technique, which is, of course, only viable if the hardware can be instructed to generate interrupts.
The code in Listing 2 shows skel_find(), complete with IRQ autodetection. Some details of IRQ handling may appear obscure to some readers, but they will be clarified in the next article. To summarize, this code cycles through each of the possible IRQ lines, asking to install a handler, and looks to see if interrupts are actually generated by the board.
The field hwirq in the hardware structure represents the useable interrupt line, while the field irq is only valid when the line is active (after request_irq()). As explained in the last issue, it makes no sense to keep hold of an IRQ line when the device is not in use; that's why two fields are used.
Please note that I wrote this code as a work-around for the limitations of one of my hardware boards; if your hardware is able to report the IRQ line it's going to use, it's much better to use that information instead. The code is quite stable, anyway, if you are able to tailor it to your actual hardware. Fortunately, most good hardware is able to report its own configuration.
After the module has been loaded and the hardware has been detected, we must see how the device is acted upon. This means introducing the role of fops and filp: these little beasts are the most important data structures—actually, variable names—used in interfacing the device driver with the kernel.
fops is the name usually devoted to a struct file_operations. The structure is a jump table (structure of pointers to functions), and each field refers to one of the different operations performed on a filesystem node (open(), read(), ioctl(), etc.).
A pointer to your own fops is passed to the kernel by means of register_chrdev(), so that your functions will be called whenever one of your nodes is acted upon. We already wrote that line of code, but didn't show the actual fops. Here it is:
struct file_operations skel_fops {
skel_lseek,
skel_read,
skel_write,
NULL, /* skel_readdir */
skel_select,
skel_ioctl,
skel_mmap,
skel_open,
skel_close
};
Each NULL entry in your fops means that you're not going to offer that functionality for your device (select is special, in this respect, but I won't expand on it), each non-NULL entry must be a pointer to a function implementing the operation for your device. Actually, there exist a few more fields in the structure, but our example will live with the default NULL value (the C compiler fills up an incomplete structure with zero bytes without issuing any warning). If you are really interested in them, you can look at the structure's definition in <linux/fs.h>. filp is the name usually devoted to one of the arguments passed by the kernel to any function in your fops, namely a struct file *. The file structure is used to keep all the available status information about an “open file”, beginning with a call to open() and up to a call to close(). If the device is opened multiple times, different filps will be used for each instance: this means that you'll need to use your own data structure to keep hardware information about your devices. The code fragments within this installment already use an array of Skel_Hw, to hold information about several boards installed on the same computer. What is missing, then, is a way to embed hardware information in the file structure, in order to instruct the driver to operate on the right device. The field private_data exists in struct file just for that task, and is a pointer to void. You'll make private_data point to your hardware information structure when skel_open() gets invoked. If you need to keep some extra information private to each filp (for example, if two device nodes access the same hardware in two different ways), then you'll need a specific structure for private_data, which must be kmalloc()ed on open and kfree()ed on close. The implementations of open() and close() that we'll see later, work in this way.
Today’s modular x86 servers are compute-centric, designed as a least common denominator to support a wide range of IT workloads. Those generic, virtualized IT workloads have much different resource optimization requirements than hyperscale and cloud applications. They have resulted in a “one size fits all” enterprise IT architecture that is not optimized for a specific set of IT workloads, and especially not emerging hyperscale workloads, such as web applications, big data, and object storage. In this report, you will learn how shifting the focus from traditional compute-centric IT architectures to an innovative disaggregated fabric-based architecture can optimize and scale your data center.
Sponsored by AMD
Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6
Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.
Learn more about catching the bad guy in this free white paper.
Sponsored by DLT Solutions
Free Webinar: Linux Backup and Recovery
Most companies incorporate backup procedures for critical data, which can be restored quickly if a loss occurs. However, fewer companies are prepared for catastrophic system failures, in which they lose all data, the entire operating system, applications, settings, patches and more, reducing their system(s) to “bare metal.” After all, before data can be restored to a system, there must be a system to restore it to.
In this one hour webinar, learn how to enhance your existing backup strategies for better disaster recovery preparedness using Storix System Backup Administrator (SBAdmin), a highly flexible bare-metal recovery solution for UNIX and Linux systems.
| Making Linux and Android Get Along (It's Not as Hard as It Sounds) | May 16, 2013 |
| Drupal Is a Framework: Why Everyone Needs to Understand This | May 15, 2013 |
| Home, My Backup Data Center | May 13, 2013 |
| Non-Linux FOSS: Seashore | May 10, 2013 |
| Trying to Tame the Tablet | May 08, 2013 |
| Dart: a New Web Programming Experience | May 07, 2013 |
- RSS Feeds
- New Products
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- Drupal Is a Framework: Why Everyone Needs to Understand This
- A Topic for Discussion - Open Source Feature-Richness?
- Home, My Backup Data Center
- Developer Poll
- Dart: a New Web Programming Experience
- May 2013 Issue of Linux Journal: Raspberry Pi
- What's the tweeting protocol?
- Reply to comment | Linux Journal
1 hour 28 min ago - Reply to comment | Linux Journal
2 hours 15 min ago - Web Hosting IQ
3 hours 48 min ago - Thanks for taking the time to
5 hours 25 min ago - Linux is good
7 hours 23 min ago - Reply to comment | Linux Journal
7 hours 40 min ago - Web Hosting IQ
8 hours 10 min ago - Web Hosting IQ
8 hours 11 min ago - Web Hosting IQ
8 hours 11 min ago - Reply to comment | Linux Journal
11 hours 12 min ago




Comments
Where are functions defined
Hello,
In which file are all the functions which are declared in the struct file_operations e.g open(), read();
Regards
Anil
Wherever You Like
Those functions have to be supplied by you. So you can put them wherever seems most appropriate for your code.
Mitch Frazier is an Associate Editor for Linux Journal.