Code for Linux device driver development (3)

Source: Internet
Author: User

1. C code:

 

# Include <Linux/module. h>
# Include <Linux/types. h>
# Include <Linux/fs. h>
# Include <Linux/errno. h>
# Include <Linux/mm. h>
# Include <Linux/sched. h>
# Include <Linux/init. h>
# Include <Linux/cdev. h>
# Include <ASM/IO. h>
# Include <ASM/system. h>
# Include <ASM/uaccess. h>

# Define globalmem_size 0x1000
# Define mem_clear 0x01
# Define globalmem_major 254

Static globalmem_major = globalmem_major;

Struct globalmem_dev
{
Struct cdev;
U8 mem [globalmem_size];
Struct semaphore SEM;
};

Struct globalmem_dev * globalmem_devp;

Int globalmem_open (struct inode * inode, struct file * filp)
{
Filp-> private_data = globalmem_devp;
Return 0;
}

Int globalmem_release (struct inode * inode, struct file * filp)
{
Return 0;
}

Static ssize_t globalmem_read (struct file * filp, char _ User * Buf, size_t count, loff_t * PPOs)
{
U32 P = * PPOs;
Int ret = 0;

Struct globalmem_dev * Dev = filp-> private_data;

If (P> = globalmem_size ){
Return count? -Enxio: 0;
}

If (count> globalmem_size-p ){
Count = globalmem_size-P;
}

If (down_interruptible (& Dev-> SEM )){
Return-erestartsys;
}

If (copy_to_user (BUF, (void *) (Dev-> mem + p), count )){
Ret =-efault;
} Else {
* PPOs + = count;
Ret = count;
Printk (kern_info "read % d byte (s) from % d/N", Count, P );
}

Up (& Dev-> SEM );

Return ret;
}

Static ssize_t globalmem_write (struct file * filp, const char _ User * Buf, size_t count, loff_t * PPOs)
{
U32 P = * PPOs;
Int ret = 0;

Struct globalmem_dev * Dev = filp-> private_data;

If (P> = globalmem_size ){
Return count? -Enxio: 0;
}

If (down_interruptible (& Dev-> SEM )){
Return-erestartsys;
}

If (count> globalmem_size-p ){
Count = globalmem_size-P;
}

If (copy_from_user (Dev-> mem + P, Buf, count )){
Ret =-efault;
} Else {
* PPOs + = count;
Ret = count;
Printk (kern_info "writtem % d byte (s) from % d/N", Count, P );
}

Up (& Dev-> SEM );

Return ret;
}

Static loff_t globalmem_llseek (struct file * filp, loff_t offset, int orig)
{
Loff_t ret;
Switch (orig)
{
Case 0:
If (offset <0 ){
Ret =-einval;
Break;
}

If (u32) Offset> globalmem_size ){
Ret-filp-> f_pos;
Break;
}

Filp-> f_pos = (u32) offset;
Ret = filp-> f_pos;
Break;

Case 1:
If (filp-> f_pos + offset)> globalmem_size ){
Ret =-einval;
Break;
}

If (filp-> f_pos + offset) <0 ){
Ret =-einval;
Break;
}

Filp-> f_pos + = offset;
Ret = filp-> f_pos;
Break;

Default:
Ret =-einval;
}
Return ret;
}

Static int globalmem_ioctl (struct inode * inodep, struct file * filp, u32 cmd, u32 Arg)
{
Struct globalmem_dev * Dev = filp-> private_data;
Switch (CMD)
{
Case mem_clear:
If (down_interruptible (& Dev-> SEM )){
Return-erestartsys;
}

Memset (Dev-> MEM, 0, globalmem_size );

Up (& Dev-> SEM );

Printk (kern_info "globalmem is set to zero/N ");
Break;

Default:
Return-einval;
}

Return 0;
}

Static const struct file_operations globalmem_fops =
{
. Owner = this_module,
. Llseek = globalmem_llseek,
. Read = globalmem_read,
. Write = globalmem_write,
. IOCTL = globalmem_ioctl,
. Open = globalmem_open,
. Release = globalmem_release,
};

Static void globalmem_setup_cdev (struct globalmem_dev * Dev, int index)
{
Int err, devno = mkdev (globalmem_major, index );

Cdev_init (& Dev-> cdev, & globalmem_fops );
Dev-> cdev. Owner = this_module;
Dev-> cdev. Ops = & globalmem_fops;
Err = cdev_add (& Dev-> cdev, devno, 1 );
If (ERR ){
Printk (kern_notice "error % d adding globalmem % d/N", err, index );
}
}

Int globalmem_init (void)
{
Int result;
Dev_t devno = mkdev (globalmem_major, 0 );

If (globalmem_major ){
Result = register_chrdev_region (devno, 1, "globalmem ");
} Else {
Result = alloc_chrdev_region (& devno, 0, 1, "globalmem ");
Globalmem_major = major (devno );
}

If (result <0 ){
Return result;
}

Globalmem_devp = kmalloc (sizeof (struct globalmem_dev), gfp_kernel );
If (! Globalmem_devp ){
Result =-enomem;
Goto fail_malloc;
}
Memset (globalmem_devp, 0, sizeof (struct globalmem_dev ));

Globalmem_setup_cdev (globalmem_devp, 0 );
Init_mutex (& globalmem_devp-> SEM );
Return 0;

Fail_malloc: unregister_chrdev_region (devno, 1 );
Return result;
}

Void globalmem_exit (void)
{
Cdev_del (& globalmem_devp-> cdev );
Kfree (globalmem_devp );
Unregister_chrdev_region (mkdev (globalmem_major, 0), 1 );
}

Module_author ("Alex Xia ");
Module_license ("dual BSD/GPL ");

Module_param (globalmem_major, Int, s_irugo );

Module_init (globalmem_init );
Module_exit (globalmem_exit );

 

2. Run. Sh

 

#! /Bin/sh
Make-C/lib/modules/2.6.31-22-generic/build/M = $ (PWD) Modules

 

 

3. Clean. Sh

 

#! /Bin/sh
RM *. Mod. C *. O *. Ko *. Mar *. sym *. ord *

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.