02 LED 驅動程式S3C64XX

    #include <linux/module.h>
    #include <linux/kernel.h>
    #include <linux/io.h>
    #include <linux/fs.h>
    #include <asm/uaccess.h>
    #include <linux/miscdevice.h>
    #include <linux/pci.h>
    #include <linux/ioctl.h>
    #include <linux/init.h>
    
    #define DEVICE_NAME "leds0" // (/dev/leds)
    
    #define UGPMCON (*(volatile unsigned long *)S3C64XX_GPMCON)
    #define UGPMDAT (*(volatile unsigned long *)S3C64XX_GPMDAT)
    #define UGPMPUD (*(volatile unsigned long *)S3C64XX_GPMPUD)
    
    static long S3C64XX_GPMCON=0xF4500820;
    static long S3C64XX_GPMDAT=0xF4500824;
    
    #define LED_MAJOR 240
    
    static int led_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
    {
    //      printk(KERN_ALERT"\ncmd = %d  arg = %d \n", cmd, arg);
    
        switch(cmd)
        {
            case 0:
                printk(KERN_ALERT"led%d off\n", arg);
                switch(arg)
                {
                case 0:
                    UGPMDAT |= 0x01;
                    break;
                case 1:
                    UGPMDAT |= 0x02;
                    break;
                case 2:
                    UGPMDAT |= 0x04;
                    break;
                case 3:
                    UGPMDAT |= 0x08;
                    break;
    
                default:
                    break;
                }
                break;
            case 1:
                printk(KERN_ALERT"led%d on\n", arg);
                switch(arg)
                {
                case 0:
                    UGPMDAT &= 0xfe;
                    break;
                case 1:
                    UGPMDAT &= 0xfd;
                    break;
                case 2:
                    UGPMDAT &= 0xfb;
                    break;
                case 3:
                    UGPMDAT &= 0xf7;
                    break;
    
                default:
                    break;
                }
    
                break;
            case 11:
                printk(KERN_ALERT"led all on\n");
                    UGPMDAT &= 0xe0;
                break;
            case 10:
                printk(KERN_ALERT"led all off\n");
                    UGPMDAT |= 0xff;
                break;
    
            default:
                break;
            }
    
        return 0;
    }
    
    struct file_operations led_fops={
        .owner = THIS_MODULE,
        .unlocked_ioctl = led_ioctl,
    };
    
    static struct miscdevice misc = {
    
        .minor = MISC_DYNAMIC_MINOR, //动态设备号
    
        .name = DEVICE_NAME,
    
        .fops = &led_fops,
    
    };
    
    
    static int __init led_init(void)
    {
        int rc;
        rc = misc_register(&misc);
        outl(0x00111111,S3C64XX_GPMCON);
        outl(0xff,S3C64XX_GPMDAT);
    
        if(rc<0)
        {
            printk(KERN_ALERT"register %s char dev error\n","leds");
            return -1;
        }
        printk(KERN_ALERT"OK!\n");
        return 0;
    }
    
    static void __exit led_exit(void)
    {
        unregister_chrdev(LED_MAJOR, "leds");
        printk(KERN_ALERT"module exit\n");
    }
    
    module_init(led_init);
    module_exit(led_exit);
    
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("cw");
    
    

    Makefile

    KERNELDIR :=/home/share/linux/linux3.0/kernel/linux-3.0.1
    #KERNELDIR :=/home/share/linux/linux2.6.36/linux-2.6.36.2-v1.05
    PWD :=$(shell pwd)
    modules:
            $(MAKE) -C $(KERNELDIR) M=$(PWD) modules
    
    modules_install:
          $(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
    obj-m:=led.o
    
    clean:
          rm -rf *.o *~core .depend .*.cmd *.ko *.mod.c .tmp_versions *.order *.symvers
    
    
    

    測試程式

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/ioctl.h>
    int main(int argc, char **argv)
    {
         int on, cmd;
         int led_no;
         int fd;
    
            if (argc != 3 || sscanf(argv[1], "%d", &led_no) != 1 || sscanf(argv[2],"%d", &on) != 1 || led_    no < 0 || led_no > 3) {
                 fprintf(stderr, "Usage: leds led_no 0|1|2|3\n");
                 exit(1);
            }
            fd = open("/dev/leds0", 0);
            if(fd < 0)
                 printf("Can't open /dev/leds!\n");
    
            ioctl(fd, on, led_no);
            close(fd);
    
            return 0;
    }