Chapter 3. Writing your own kernel module
Prev |  | Next

## Chapter 3. Writing your own kernel module

Please have a look at `uio_cif.c` as an example. The following paragraphs explain the different sections of this file.

## struct uio_info

This structure tells the framework the details of your driver, Some of the members are required, others are optional.

- `char *name`: Required. The name of your driver as it will appear in sysfs. I recommend using the name of your module for this.

- `char *version`: Required. This string appears in `/sys/class/uio/uioX/version`.

- `struct uio_mem mem[ MAX_UIO_MAPS ]`: Required if you have memory that can be mapped with `mmap()`. For each mapping you need to fill one of the `uio_mem` structures. See the description below for details.

- `long irq`: Required. If your hardware generates an interrupt, it's your modules task to determine the irq number during initialization. If you don't have a hardware generated interrupt but want to trigger the interrupt handler in some other way, set `irq` to `UIO_IRQ_CUSTOM`. If you had no interrupt at all, you could set `irq` to `UIO_IRQ_NONE`, though this rarely makes sense.

- `unsigned long irq_flags`: Required if you've set `irq` to a hardware interrupt number. The flags given here will be used in the call to `request_irq()`.

- `int (*mmap)(struct uio_info *info, struct vm_area_struct *vma)`: Optional. If you need a special `mmap()` function, you can set it here. If this pointer is not NULL, your `mmap()` will be called instead of the built-in one.

- `int (*open)(struct uio_info *info, struct inode *inode)` : Optional. You might want to have your own `open()`, e.g. to enable interrupts only when your device is actually used.

- `int (*release)(struct uio_info *info, struct inode *inode)` : Optional. If you define your own `open()`, you will probably also want a custom `release()` function.

Usually, your device will have one or more memory regions that can be mapped to user space. For each region, you have to set up a `struct uio_mem` in the `mem[]` array. Here's a description of the fields of `struct uio_mem`:

- `int memtype`: Required if the mapping is used. Set this to `UIO_MEM_PHYS` if you you have physical memory on your card to be mapped. Use `UIO_MEM_LOGICAL` for logical memory (e.g. allocated with `kmalloc()`). There's also `UIO_MEM_VIRTUAL` for virtual memory.

- `unsigned long addr`: Required if the mapping is used. Fill in the address of your memory block. This address is the one that appears in sysfs.

- `unsigned long size`: Fill in the size of the memory block that `addr` points to. If `size` is zero, the mapping is considered unused. Note that you must initialize `size` with zero for all unused mappings.

- `void *internal_addr`: If you have to access this memory region from within your kernel module, you will want to map it internally by using something like `ioremap()`. Addresses returned by this function cannot be mapped to user space, so you must not store it in `addr`. Use `internal_addr` instead to remember such an address.

Please do not touch the `kobj` element of `struct uio_mem`! It is used by the UIO framework to set up sysfs files for this mapping. Simply leave it alone.

Prev |  | Next
Chapter 2. About UIO | Home | Adding an interrupt handler