Table of Contents
Please have a look at uio_cif.c
as an
example. The following paragraphs explain the different
sections of this file.
This structure tells the framework the details of your driver, Some of the members are required, others are optional.
const char *name
: Required. The name of your driver as
it will appear in sysfs. I recommend using the name of your module for this.
const 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.
struct uio_port port[ MAX_UIO_PORTS_REGIONS ]
: Required
if you want to pass information about ioports to userspace. For each port
region you need to fill one of the uio_port
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.
int (*irqcontrol)(struct uio_info *info, s32 irq_on)
: Optional. If you need to be able to enable or disable
interrupts from userspace by writing to /dev/uioX
,
you can implement this function. The parameter irq_on
will be 0 to disable interrupts and 1 to enable them.
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.
Sometimes, your device can have one or more port regions which can not be
mapped to userspace. But if there are other possibilities for userspace to
access these ports, it makes sense to make information about the ports
available in sysfs. For each region, you have to set up a
struct uio_port
in the port[]
array.
Here's a description of the fields of struct uio_port
:
char *porttype
: Required. Set this to one of the predefined
constants. Use UIO_PORT_X86
for the ioports found in x86
architectures.
unsigned long start
: Required if the port region is used.
Fill in the number of the first port of this region.
unsigned long size
: Fill in the number of ports in this
region. If size
is zero, the region is considered unused.
Note that you must initialize size
with zero for all unused regions.
Please do not touch the portio
element of
struct uio_port
! It is used internally by the UIO
framework to set up sysfs files for this region. Simply leave it alone.