LECTURE 9 ´Êñ¤Ê³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é

¡û ¤Ï¤¸¤á¤Ë

LECTURE 8 I/O ¥Ý¡¼¥È¤ÎÀ©¸æ ¤Ç¡¢´ðËÜŪ¤Ê¥Ï¡¼¥É¥¦¥§¥¢¤ÎÀ©¸æ¤Ë¤Ä¤¤¤ÆÀâÌÀ¤·¤Þ¤·¤¿¡£¤·¤«¤·¡¢¥Ï¡¼¥É¥¦¥§¥¢À©¸æ¤Ë¤ª¤±¤ë½ÅÍפÊÍ×ÁǤǤ¢¤ë³ä¤ê¹þ¤ß½èÍý¤¬¤Þ¤À»Ä¤Ã¤Æ¤¤¤Þ¤¹¡£

¥Ñ¥é¥ì¥ë¥Ý¡¼¥È¤òÎã¤Ëµó¤²¤ë¤È¡¢¥³¥ó¥È¥í¡¼¥ë¥Ý¡¼¥È¤Î 4 È֥ӥåȤò 1 ¤Ë¤¹¤ë¤³¤È¤Ç³ä¤ê¹þ¤ß¤¬Í­¸ú¤Ë¤Ê¤ê¡¢¥¹¥Æ¡¼¥¿¥¹¥Ý¡¼¥È¤Î 6 ÈÖ¥Ó¥Ã¥È ( ¥Ñ¥é¥ì¥ë¥Ý¡¼¥È¤Î 10 ÈÖ¥Ô¥ó )¤¬ Low ¤«¤é High ¤Ë¤Ê¤ë½Ö´Ö¤Ë³ä¤ê¹þ¤ß¤¬È¯À¸¤·¤Þ¤¹¡£

Á°²ó¼«ºî¤·¤¿ÅŻҲóÏ©¤ò¤½¤Î¤Þ¤Þ»È¤¦¤È¡¢¥×¥Ã¥·¥å¥Ü¥¿¥ó¤ò²¡¤·¤¿¾õÂÖ¤«¤éÎ¥¤·¤¿ºÝ¤Ë¥Ñ¥é¥ì¥ë¥Ý¡¼¥È¤«¤é¤Î³ä¤ê¹þ¤ß¤òȯÀ¸¤µ¤»¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£¤³¤³¤Ç¤Ï¡¢¼«ºî²óÏ©¤ò»È¤Ã¤Æ³ä¤ê¹þ¤ß½èÍý¤Î¼Â¸½ÊýË¡¤òÀâÌÀ¤·¤Þ¤¹¡£

¡û ¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à

LECTURE 8 I/O ¥Ý¡¼¥È¤ÎÀ©¸æ ¤ÇºîÀ®¤·¤¿¼«ºîÅŻҲóÏ©¤ò»È¤Ã¤Æ¡¢³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é¤ò¼Â¸½¤¹¤ë¤¿¤á¤Î¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à irq_io.h¡¢irq_io.c ¡¢irq_main.c ¤Ç¤¹¡£¤Ï¤¸¤á¤Ë ¤Î¥Ú¡¼¥¸¤«¤é¡¢Á´¤Æ¤Î¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à¤ò ¸Ç¤á¤¿ tar ¥Ü¡¼¥ë¤ò¥À¥¦¥ó¥í¡¼¥É¤¹¤ë¤³¤È¤â¤Ç¤­¤Þ¤¹¡£

gcc -DMODULE -D__KERNEL__ -O -c irq_io.c
gcc -DMODULE -D__KERNEL__ -O -c irq_main.c
ld -r -o irq.o irq_main.o irq_io.o

¤È¤·¤Æ¥³¥ó¥Ñ¥¤¥ë¡¿¥ê¥ó¥¯¤ò¹Ô¤¤¤Þ¤¹¡£

³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é°Ê³°¤Ï¡¢LECTURE 8 I/O ¥Ý¡¼¥È¤ÎÀ©¸æ ¤Î»þ¤ÈƱ¤¸Æ°¤­¤ò¤·¤Þ¤¹¡£¥×¥Ã¥·¥å¥Ü¥¿¥ó¤ò²¡¤·¤ÆÎ¥¤·¤¿½Ö´Ö¤Ë³ä¤ê¹þ¤ß¤¬È¯À¸¤·¤Þ¤¹¤¬¡¢³ä¤ê¹þ¤ß¥Ï¥ó¥É¥éÆâ¤Ç°ìÈÖ²¼¤Î LED ¤Î¾õÂÖ¤òȿž¤¹¤ë¤¿¤á¡¢¥×¥Ã¥·¥å¥Ü¥¿¥ó¤ò²¡¤¹Å٤˰ìÈÖ²¼¤Î LED ¤¬ÅÀÅô¡¿¾ÃÅô¤ò·«¤êÊÖ¤¹ÅÀ¤¬°Û¤Ê¤ê¤Þ¤¹¡£

--- Á´ LED ȯ¸÷Ãæ ---

Á´ LED ȯ¸÷Ãæ

°ìÈÖ²¼¤Î LED ¤âÅÀÅô¤¹¤ë¤³¤È¤Ç¡¢Á´Éô¤Î LED ¤¬ÅÀÅô¤·¤Æ¤¤¤ë¾õÂ֤Ǥ¹¡£

--- irq_io.h ---

    1    #ifndef ___irq_io_h_included_
    2    #define ___irq_io_h_included_
    3    
    4    
    5    #define IOPORT_BASE     0x378
    6    #define IOPORT_RANGE    3
    7    
    8    #define IOPORT_DATA     ( IOPORT_BASE + 0 )
    9    #define IOPORT_STATUS   ( IOPORT_BASE + 1 )
   10    #define IOPORT_CONTROL  ( IOPORT_BASE + 2 )
   11    
   12    #define IRQ_NUMBER      7
   13    
   14    #define DATA_LED_1      0
   15    #define DATA_LED_2      1
   16    #define DATA_LED_3      2
   17    #define DATA_PULLUP     3
   18    #define STATUS_ACK      6
   19    #define IRQ_ENABLE      4
   20    
   21    
   22    void
   23    io_write_or( unsigned short port, unsigned int value );
   24    
   25    void
   26    io_write_xor( unsigned short port, unsigned int value );
   27    
   28    void
   29    io_write_set( unsigned short port, unsigned int value );
   30    
   31    int
   32    io_is_button_pressed();
   33    
   34    void
   35    io_enable_irq();
   36    
   37    
   38    #endif /* ___irq_io_h_included_ */
   39    
   40    /* End of irq_io.h */

--- irq_io.c ---

    1    #include <asm/bitops.h>      /* test_and_set_bit, clear_bit */
    2    #include <asm/io.h>          /* outb(), inb() */
    3    #include <asm/system.h>      /* rmb() */
    4    #include "irq_io.h"
    5    
    6    static int lock;
    7    
    8    
    9    /*
   10     * ¸½ºß¤Î»ØÄê¥Ý¡¼¥È¤ÎÃͤȻØÄêÃͤò or ¤·¤¿·ë²Ì¤ò
   11     * »ØÄê¥Ý¡¼¥È¤Ë½ñ¤­¹þ¤à
   12     */
   13    void
   14    io_write_or( unsigned short port, unsigned int value )
   15    {
   16        unsigned int data;
   17    
   18        if ( test_and_set_bit( 0, ( void* )( &lock ) ) != 0 )
   19            return;
   20    
   21        data  = inb( port );
   22        data |= value;
   23        outb( data, port );
   24    
   25        clear_bit( 0, ( void* )( &lock ) );
   26    }
   27    
   28    
   29    /*
   30     * ¸½ºß¤Î»ØÄê¥Ý¡¼¥È¤ÎÃͤȻØÄêÃͤò xor ¤·¤¿·ë²Ì¤ò
   31     * »ØÄê¥Ý¡¼¥È¤Ë½ñ¤­¹þ¤à ( »ØÄê¥Ó¥Ã¥È¤ÎÃÍȿž )
   32     */
   33    void
   34    io_write_xor( unsigned short port, unsigned int value )
   35    {
   36        unsigned int data;
   37    
   38        if ( test_and_set_bit( 0, ( void* )( &lock ) ) != 0 )
   39            return;
   40    
   41        data  = inb( port );
   42        data ^= value;
   43        outb( data, port );
   44    
   45        clear_bit( 0, ( void* )( &lock ) );
   46    }
   47    
   48    
   49    /*
   50     * »ØÄêÃͤò»ØÄê¥Ý¡¼¥È¤Ë½ñ¤­¹þ¤à
   51     */
   52    void
   53    io_write_set( unsigned short port, unsigned int value )
   54    {
   55        if ( test_and_set_bit( 0, ( void* )( &lock ) ) != 0 )
   56            return;
   57    
   58        outb( value, port );
   59    
   60        clear_bit( 0, ( void* )( &lock ) );
   61    }
   62    
   63    
   64    /*
   65     * ¥¹¥Æ¡¼¥¿¥¹¥Ý¡¼¥È¤ÎÃͤòÆɤ߹þ¤ß¡¢ACK ( 10 ÈÖ¥Ô¥ó )
   66     * ¤¬ LOW ¤«¤É¤¦¤«Ä´¤Ù¤ë¡£
   67     */
   68    int
   69    io_is_button_pressed()
   70    {
   71        unsigned int data;
   72    
   73        data = inb( IOPORT_STATUS );
   74        rmb();
   75
   76        if ( ! ( data & ( 1 << STATUS_ACK ) ) )
   77            return 1;
   78    
   79        return 0;
   80    }
   81    
   82    
   83    /*
   84     * ³ä¤ê¹þ¤ß¤òÍ­¸ú¤Ë¤¹¤ë¡£
   85     * ³ä¤ê¹þ¤ßÀ©¸æÍÑ¥Ô¥ó°Ê³°¤Î¥Ô¥ó¤Î¾õÂÖ¤ÏÊѤ¨¤Ê¤¤¡£
   86     */
   87    void
   88    io_enable_irq()
   89    {
   90        unsigned int data;
   91    
   92        if ( test_and_set_bit( 0, ( void* )( &lock ) ) != 0 )
   93            return;
   94    
   95        data  = inb( IOPORT_CONTROL );
   96        data |= ( 1 << IRQ_ENABLE );
   97        outb( data, IOPORT_CONTROL );
   98        
   99        clear_bit( 0, ( void* )( &lock ) );
  100    }
  101    
  102    
  103    /* End of irq_io.c */

--- irq_main.c ---

    1    #include <asm/io.h>          /* outb(), inb() */
    2    #include <asm/uaccess.h>     /* copy_from_user, copy_to_user */
    3    #include <linux/fs.h>        /* inode, file, file_operations, ... */
    4    #include <linux/ioport.h>    /* check_region(), request_region(), release_region() */
    5    #include <linux/kernel.h>    /* printk() */
    6    #include <linux/module.h>
    7    #include <linux/sched.h>     /* task_struct */
    8    #include <linux/timer.h> 
    9    
   10    #include "irq_io.h"
   11    
   12    
   13    MODULE_LICENSE( "GPL" );
   14    
   15    
   16    static int   devmajor = 77;
   17    static char* devname  = "chardev";
   18    static char* msg      = "module [irq.o]";
   19    
   20    
   21    /* 100 tick = 1 sec. */
   22    static int timeout = 100; 
   23    MODULE_PARM( timeout, "i" );
   24    
   25    static struct timer_list chardev_timer;
   26    static int timerstop = 0;
   27    
   28    static unsigned int initial_data;
   29    static unsigned int initial_control;
   30    
   31    static void chardev_timer_handler( unsigned long data );
   32    static void chardev_del_timer();
   33    
   34    
   35    /*
   36     * ¥í¥°½ÐÎÏ¥Õ¥©¡¼¥Þ¥Ã¥ÈÍÑ´Ø¿ô
   37     */
   38    static void 
   39    log_format( char* body )
   40    {
   41        if ( current != NULL ) {
   42            printk( KERN_INFO "%s : PID = %-5i cmdline = \"%-10s\" : %s\n", 
   43                msg, current->pid, current->comm, body );
   44        }
   45        else {
   46            printk( KERN_INFO "%s : %s\n", msg, body );
   47        }
   48    }
   49    
   50    /*
   51     * ³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é¡£ËÜÅö¤Ï¤³¤³¤Ç¥¹¥Æ¡¼¥¿¥¹¥Ý¡¼¥È¤òÆɤޤʤ¤¤È
   52     * °Ê¹ß¤Î³ä¤ê¹þ¤ß¤¬ÊÝᤵ¤ì¤ëÌÏÍÍ¡£ËÜ¥µ¥ó¥×¥ë¤Ç¤Ï cat ¤·¤Æ¤¤¤ë´ÖÃæ chardev_read() 
   53     * ¤Ç¥¹¥Æ¡¼¥¿¥¹¥Ý¡¼¥È¤òÆɤि¤áÂç¾æÉס£ËÜʸ¤ÎÀâÌÀ»²¾È¡£
   54     */
   55    static void
   56    chardev_interrupt( int irq, void* dev_id, struct pt_regs* regs )
   57    {
   58        io_write_xor( IOPORT_DATA, ( 1 << DATA_LED_3 ) );
   59    }
   60    
   61    /* 
   62     * ¥¿¥¤¥Þ¡¼ÅÐÏ¿½èÍý 
   63     */
   64    static void 
   65    chardev_timer_register( void )
   66    {
   67        init_timer( &chardev_timer );
   68    
   69        chardev_timer.expires  = jiffies + timeout;
   70        chardev_timer.data     = ( unsigned long )jiffies;
   71        chardev_timer.function = chardev_timer_handler;
   72    
   73        add_timer( &chardev_timer );
   74    }
   75    
   76    
   77    /*
   78     * ¥¿¥¤¥Þ¡¼ºï½ü´Ø¿ô
   79     * ¥¿¥¤¥ÞÄä»ß¥Õ¥é¥°¤òÀßÄꤷ¡¢del_timer_sync ¤Ç´û¸¤Î¥¿¥¤¥Þ¡¼´Ø¿ô¤ò
   80     * ºï½ü¤¹¤ë¡Ê¼Â¹ÔÃæ¤Î¾ì¹ç¤Ï½ªÎ»¤¹¤ë¤Þ¤ÇÂԤġˡ£
   81     */
   82    static void
   83    chardev_del_timer()
   84    {
   85        timerstop = 1;
   86        del_timer_sync( &chardev_timer );
   87    }
   88    
   89    
   90    /* 
   91     * ¥¿¥¤¥à¥¢¥¦¥È½èÍý 
   92     */
   93    static void 
   94    chardev_timer_handler( unsigned long data )
   95    {
   96        io_write_xor( IOPORT_DATA, ( 1 << DATA_LED_2 ) );
   97    
   98        if ( timerstop ) {
   99            printk( KERN_INFO "%s : Timer is not to be restarted.\n", msg );
  100            return;
  101        }
  102    
  103        chardev_timer_register();
  104    }
  105    
  106    
  107    /*
  108     * open()
  109     */
  110    static int 
  111    chardev_open( struct inode* inode, struct file* filp )
  112    {
  113        log_format( "open()  called" );
  114        return 0;
  115    }
  116    
  117    
  118    /*
  119     * release()
  120     */
  121    static int 
  122    chardev_release( struct inode* inode, struct file* filp )
  123    {
  124        log_format( "close() called" );
  125        return 0;
  126    }
  127    
  128    
  129    /*
  130     * read()
  131     */
  132    static ssize_t 
  133    chardev_read( struct file* filp, char* buf, size_t count, loff_t* pos )
  134    {
  135        char status[32];
  136        int copy_len = 0;
  137        int len = 0;
  138    
  139        log_format( "read()  called" );
  140    
  141        if ( *pos == 0 ) {
  142            if ( io_is_button_pressed() )
  143                len = sprintf( status, "[Switch] pressed.\n" );
  144            else
  145                len = sprintf( status, "[Switch] NOT pressed.\n" );
  146        }
  147    
  148        copy_len = ( len > count ) ? count : len;
  149    
  150        if ( copy_to_user( buf, status, copy_len ) ) {
  151            log_format( "copy_to_user failed\n" );
  152            return -EFAULT;
  153        }
  154    
  155        *pos += copy_len;
  156    
  157        return copy_len;
  158    }
  159    
  160    
  161    /*
  162     * write()
  163     */
  164    static ssize_t 
  165    chardev_write( struct file* filp, const char* buf, size_t count, loff_t* pos )
  166    {
  167        log_format( "write() called" );
  168        io_write_xor( IOPORT_DATA, ( 1 << DATA_LED_1 ) );
  169        return count;
  170    }
  171    
  172    
  173    static struct file_operations chardev_fops = 
  174    {
  175        owner   : THIS_MODULE,
  176        read    : chardev_read,
  177        write   : chardev_write,
  178        open    : chardev_open,
  179        release : chardev_release,
  180    };
  181    
  182    
  183    /*
  184     * ¥â¥¸¥å¡¼¥ë¤Î½é´ü½èÍý
  185     * insmod »þ¤Ë¸Æ¤Ð¤ì¤ë
  186     */
  187    int 
  188    init_module( void )
  189    {
  190        EXPORT_NO_SYMBOLS;
  191    
  192        if ( register_chrdev( devmajor, devname, &chardev_fops ) ) {
  193            log_format( "register_chrdev failed" );
  194            return -EBUSY;
  195        }
  196    
  197    
  198        if ( request_region( IOPORT_BASE, IOPORT_RANGE, devname ) == NULL ) {
  199            log_format( "request_region returned NULL" );
  200            unregister_chrdev( devmajor, devname );
  201            return -EBUSY;
  202        }
  203    
  204    
  205        if ( request_irq( IRQ_NUMBER, chardev_interrupt, 0, devname, NULL ) ) {
  206            log_format( "request_irq failed" );
  207            release_region( IOPORT_BASE, IOPORT_RANGE );
  208            unregister_chrdev( devmajor, devname );
  209            return -EBUSY;
  210        }
  211    
  212        initial_data    = inb( IOPORT_DATA );
  213        initial_control = inb( IOPORT_CONTROL );
  214    
  215        io_write_or( IOPORT_DATA, ( 1 << DATA_PULLUP ) );
  216        io_enable_irq();
  217    
  218        chardev_timer_register();
  219    
  220        log_format( "loaded  into kernel" );
  221        return 0;
  222    }
  223    
  224    
  225    /*
  226     * ¥â¥¸¥å¡¼¥ë¤Î²òÊü½èÍý
  227     * ¥â¥¸¥å¡¼¥ë¤Î»²¾È¿ô¤¬ 0 ¤Ç¤¢¤ì¤Ð¡¢rmmod »þ¤Ë¸Æ¤Ð¤ì¤ë
  228     */
  229    void 
  230    cleanup_module( void )
  231    {
  232        chardev_del_timer();
  233        free_irq( IRQ_NUMBER, NULL );
  234    
  235        io_write_set( IOPORT_CONTROL, initial_control );
  236        io_write_set( IOPORT_DATA,    initial_data );
  237    
  238        release_region( IOPORT_BASE, IOPORT_RANGE );
  239    
  240        if ( unregister_chrdev( devmajor, devname ) ) {
  241            log_format( "unregister_chrdev failed" );
  242            /* Âкö̵¤· ... */
  243        }
  244    
  245        log_format( "removed from kernel" );
  246    }
  247    
  248    
  249    /* End of irq_main.c */

¡û ¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à¤ÎÀâÌÀ

¤Ç¤Ï¡¢¥µ¥ó¥×¥ë¥×¥í¥°¥é¥à¤Ë¤Ä¤¤¤ÆÀâÌÀ¤·¤Æ¤¤¤­¤Þ¤¹¡£ LECTURE 8 I/O ¥Ý¡¼¥È¤ÎÀ©¸æ ¤Ç¾Ò²ð¤·¤¿ hw_io.h¡¢ hw_io.c¡¢ hw_main.c ¤ò¥Ù¡¼¥¹¤ËɬÍפʲսê¤ò Äɲä·¤Æ hw_ ¤ò irq_ ¤ËÊѤ¨¤¿¤À¤±¤Ê¤Î¤Ç¡¢Äɲòսê¤Ë¤Ä¤¤¤ÆÀâÌÀ¤·¤Þ¤¹¡£


--- irq_io.h ---

  • 12 ¹ÔÌÜ

    ¥Ñ¥é¥ì¥ë¥Ý¡¼¥È¤«¤é¤Î³ä¤ê¹þ¤ßÄÌÃΤ˻ÈÍѤµ¤ì¤ë³ä¤ê¹þ¤ßÈÖ¹æ¤ò¥Þ¥¯¥íÄêµÁ¤·¤Æ¤¤¤Þ¤¹¡£ ¥Ù¡¼¥¹¥¢¥É¥ì¥¹¤¬°Û¤Ê¤ë¾ì¹ç¤Ï¡¢³ä¤ê¹þ¤ßÈÖ¹æ¤â°Û¤Ê¤ë¤Î¤ÇÃí°Õ¤·¤Æ¤¯¤À¤µ¤¤¡£

  • 19 ¹ÔÌÜ

    ¥Ñ¥é¥ì¥ë¥Ý¡¼¥È¤Ï½é´ü¾õÂ֤Ǥϳä¤ê¹þ¤ß¤¬Ìµ¸ú¤Ë¤Ê¤Ã¤Æ¤¤¤ë¤¿¤á¡¢¥×¥í¥°¥é¥àÆâ ¤ÇÍ­¸ú¤Ë¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡£¥³¥ó¥È¥í¡¼¥ë¥Ý¡¼¥È¤Î 4 ÈÖ¥Ó¥Ã¥È ( Âбþ¤¹¤ë¥Ô¥ó¤Ï¤¢¤ê¤Þ¤»¤ó ) ¤ò 1 ¤Ë¤¹¤ë¤³¤È¤Ç³ä¤ê¹þ¤ß¤¬Í­¸ú¤Ë¤Ê¤ê¤Þ¤¹¡£¤³¤³¤Ç¤Ï 4 È֥ӥåȤòɽ¤¹¥Þ¥¯¥í¤ò ÄêµÁ¤·¤Æ¤¤¤Þ¤¹¡£

  • 34 ¡Á 35 ¹ÔÌÜ

    ³ä¤ê¹þ¤ß¤òÍ­¸ú¤Ë¤¹¤ë io_enable_irq ¤Î¥×¥í¥È¥¿¥¤¥×¤òÄɲ䷤Ƥ¤¤Þ¤¹¡£


--- irq_io.c ---

  • 83 ¡Á 100 ¹ÔÌÜ ( io_enable_irq )

    ¥Ñ¥é¥ì¥ë¥Ý¡¼¥È¤«¤é¤Î³ä¤ê¹þ¤ß¤òÍ­¸ú¤Ë¤¹¤ë´Ø¿ô¤Ç¤¹¡£ ¥³¥ó¥È¥í¡¼¥ë¥Ý¡¼¥È¤Î 4 È֥ӥåȤò 1 ¤Ë¤·¡¢¤½¤ì°Ê³°¤Î¥Ó¥Ã¥È¤Î¾õÂÖ¤ò ÊѤ¨¤Ê¤¤Íͤˤ·¤Æ¤¤¤Þ¤¹¡£


--- irq_main.c ---

  • 29 ¹ÔÌÜ

    irq_main.c ¤Ç¤Ï¥³¥ó¥È¥í¡¼¥ë¥Ý¡¼¥È¤Ø¤Î½ñ¤­¹þ¤ß¤â¹Ô¤¦°Ù¡¢ ¥³¥ó¥È¥í¡¼¥ë¥Ý¡¼¥È¤Î½é´ü¾õÂÖÊݸÍÑÊÑ¿ô¤òÄɲ䷤Ƥ¤¤Þ¤¹¡£

  • 50 ¡Á 59 ¹ÔÌÜ ( chardev_interrupt )

    ³ä¤ê¹þ¤ßȯÀ¸»þ¤Ë¼Â¹Ô¤µ¤ì¤ë³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é¤Ç¤¹¡£ÅÐÏ¿ÊýË¡¤Ï¸å½Ò¤·¤Þ¤¹¤¬¡¢ ¤³¤³¤Ç¤Ï³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é¤Î·Á¼°¤ò³Ð¤¨¤Æ¤ª¤¤¤Æ¤¯¤À¤µ¤¤¡£

    ³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é¤Ï¡¢°Ê²¼¤Î¥×¥í¥È¥¿¥¤¥×¤Ë½¾¤Ã¤Æ¼ÂÁõ¤·¤Þ¤¹¡£

    void interrupt_func( int irq, void* dev_id, struct pt_regs* regs );
    
    

    irq ¤Ï³ä¤ê¹þ¤ßÈÖ¹æ¤Ç¤¹¡£dev_id ¤Ë¤ÏÅÐÏ¿»þ¤ËÀßÄꤷ¤¿¥Ý¥¤¥ó¥¿¤¬¤½¤Î¤Þ¤ÞÅϤµ¤ì¤Þ¤¹¡£ ¤Þ¤¿¡¢regs ¤ÏľÁ°¤Î CPU ¥³¥ó¥Æ¥­¥¹¥È¤¬³ÊǼ¤µ¤ì¤Æ¤¤¤Þ¤¹¤¬¡¢¤³¤³¤Ç¤Ï¿¨¤ì¤Þ¤»¤ó¡£

    chardev_interrupt ¤Ç¤Ï¡¢io_write_xor ¤Ë¤è¤Ã¤Æ°ìÈÖ²¼¤Î LED ¤Î¾õÂÖ¤òȿž¤·¤Æ¤¤¤Þ¤¹¡£¤³¤ì¤Ë¤è¤ê¡¢³ä¤ê¹þ¤ß¤¬È¯À¸¤¹¤ëÅÙ ( ¥×¥Ã¥·¥å¥Ü¥¿¥ó¥¹¥¤¥Ã¥Á¤ò²¡¤·¤ÆÎ¥¤¹ÅÙ ) ¤Ë°ìÈÖ²¼¤Î LED ¤¬ÅÀÅô¡¿¾ÃÅô¤ò·«¤êÊÖ¤·¤Þ¤¹¡£

    2008/08/11 Äɵ­¡£¥Ñ¥é¥ì¥ë¥Ý¡¼¥È¤Î³ä¤ê¹þ¤ß¤ò»È¤¦¾ì¹ç¡¢¥¹¥Æ¡¼¥¿¥¹¥Ý¡¼¥È¤Î¥Ó¥Ã¥È 6 -ACK ¤¬ Low ¤«¤é High ¤ËÊѤï¤ëºÝ¤Ë³ä¤ê¹þ¤ß¤¬È¯À¸¤·¤Þ¤¹¤¬¡¢¤³¤Î»þ¤Ë¥¹¥Æ¡¼¥¿¥¹¥Ý¡¼¥È¤Î¥Ó¥Ã¥È 2 -IRQ Status ¤¬ 0 ¤Ë¤Ê¤ëÍͤǤ¹¡£¤³¤³¤ò 1 ¤Ë¥»¥Ã¥È¤·¤Ê¤¤¤È¡¢°Ê¹ß¤Î³ä¤ê¹þ¤ß¤¬ÊÝα¤Ë¤Ê¤Ã¤Æ¤·¤Þ¤¤¤Þ¤¹¡£1 ¤Ë¥»¥Ã¥È¤¹¤ë¤¿¤á¤Ë¤Ï¡¢¥¹¥Æ¡¼¥¿¥¹¥Ý¡¼¥È¤ÎÆɤ߹þ¤ß¤¬É¬ÍפǤ¹¡£ËÜ¥µ¥ó¥×¥ë¤Ç¤Ï¡¢¥Ç¥Ð¥¤¥¹¥Õ¥¡¥¤¥ë¤ò cat ¤¹¤ë¤³¤È¤Ç chardev_read() ¤Ë¤Æ¥¹¥Æ¡¼¥¿¥¹¥Ý¡¼¥È¤ÎÆɤ߹þ¤ß¤ò¹Ô¤¦¤¿¤á¡¢¤½¤ÎÅÙ¤Ë -IRQ Status ¤¬ 1 ¤Ë¤Ê¤ë¤Î¤Ç³ä¤ê¹þ¤ß¤¬·Ñ³¤·¤ÆȯÀ¸¤·¤Þ¤¹¡£¤·¤«¤·¡¢¤³¤ÎÍͤÊÉûºîÍѤǤϤʤ¯¤­¤Á¤ó¤È³ä¤ê¹þ¤ß¤ò°·¤¦¤¿¤á¤Ë¤Ï¡¢³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é¤Ë¤Æ¥¹¥Æ¡¼¥¿¥¹¥Ý¡¼¥È¤ÎÆɤ߽Ф·¤ò¹Ô¤¦É¬Íפ¬¤¢¤ê¤Þ¤¹¡£ÌÚ¸¶¤µ¤ó¡¢¤¢¤ê¤¬¤È¤¦¤´¤¶¤¤¤Þ¤·¤¿¡£

    ³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é¼ÂÁõ»þ¤Ë¹Íθ¤¹¤Ù¤­ÅÀ¤È¤·¤Æ¡¢¤Þ¤º¤¢¤Þ¤êĹ»þ´Ö¤ËÅϤë½èÍý ¤ò¹Ô¤ï¤Ê¤¤Íͤˤ·¤Æ¤¯¤À¤µ¤¤¡£³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é¼Â¹ÔÃæ¤Ï¡¢Æ±³ä¤ê¹þ¤ßÈÖ¹æ¤Î³ä¤ê¹þ¤ß ¤¬Ìµ¸ú¤Ë¤Ê¤Ã¤Æ¤¤¤ë¤¿¤á¡¢Ê£¿ô²ó¤Î³ä¤ê¹þ¤ßȯÀ¸¤òÀµ¾ï¤Ë°·¤¨¤Ê¤¯¤Ê¤Ã¤Æ¤·¤Þ¤¤¤Þ¤¹¡£ ³ä¤ê¹þ¤ß¤ò·Àµ¡¤È¤·¤¿Ä¹»þ´Ö¤Î½èÍý¤¬É¬Íפʾì¹ç¤Ï¡¢³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é¤Ç ¥¿¥¹¥¯¥ì¥Ã¥È¤È¸Æ¤Ð¤ì¤ëµ¡Ç½¤òµ¯Æ°¤·¡¢¥¿¥¹¥¯¥ì¥Ã¥È¤Ë¤ÆĹ»þ´Ö¤«¤«¤ë½èÍý¤ò¹Ô¤¤¤Þ¤¹¡£ ¤½¤·¤Æ³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é¼«ÂΤϿ×®¤Ë½ªÎ»¤¹¤ëÍͤˤ·¤Þ¤¹¡£¥¿¥¹¥¯¥ì¥Ã¥È¤Ë¤Ä¤¤¤Æ¤Ï¡¢ ¼¡²ó¤ËÀâÌÀ¤·¤Þ¤¹¡£

    ¤Þ¤¿¡¢¥×¥í¥»¥¹¥³¥ó¥Æ¥­¥¹¥È ( read ¤ä write Åù¤Î¥×¥í¥»¥¹¤«¤é¼Â¹Ô¤µ¤ì¤ë´Ø¿ô¤Î¼Â¹Ô¾õÂÖ ) ¤È³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é¤È¤Î´Ö¤ÇÇÓ¾½èÍý¤ò¹Ô¤¦¾ì¹ç¤Ï¡¢Ãí°Õ¤¹¤ëɬÍפ¬¤¢¤ê¤Þ¤¹¡£

    ¤Þ¤º¡¢¥»¥Þ¥Õ¥©¤Ï¥×¥í¥»¥¹¤È´ØÏ¢ÉÕ¤±¤é¤ì¤ë¤¿¤á»ÈÍѤ¹¤ë¤³¤È¤¬¤Ç¤­¤Þ¤»¤ó¡£ ¤Þ¤¿¡¢Ê£¿ô¥×¥í¥»¥¹´Ö¤ÎÇÓ¾½èÍýÍѤËÄ̾ï¤Î¥¹¥Ô¥ó¥í¥Ã¥¯¤ò¹Ô¤¦¤È¡¢read Åù¤Î´Ø¿ô¤Ë¤ª¤¤¤Æ ¥¹¥Ô¥ó¥í¥Ã¥¯¤ò¼èÆÀ¤·¤¿¸å¤Ë³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é¤¬µ¯Æ°¤·¡¢³ä¤ê¹þ¤ß¥Ï¥ó¥É¥éÆâ¤Ç ¥¹¥Ô¥ó¥í¥Ã¥¯¼èÆÀÂÔ¤Á¤Ë¤Ê¤ë¤³¤È¤Ç¥Ç¥Ã¥É¥í¥Ã¥¯¤òµ¯¤³¤·¤Æ¤·¤Þ¤¤¤Þ¤¹¡£

    ¤³¤ÎÍͤʾì¹ç¤Ï¡¢¥í¥Ã¥¯¼èÆÀÃæ¤Î¥í¡¼¥«¥ë CPU ¤Î³ä¤ê¹þ¤ß¤ò̵¸ú¤Ë¤¹¤ë spin_lock_irqsave / spin_unlock_irqrestore ¤ò»ÈÍѤ·¤Þ¤¹¡£

    #include <linux/spinlock.h>
    spin_lock_irqsave( spinlock_t* lock, unsigned long flags );
    spin_unlock_irqrestore( spinlock_t* lock, unsigned long flags );
    
    

    spin_lock_irqsave ¤Î flags ¤Ï¡¢³ä¤ê¹þ¤ß¤ò̵¸ú¤Ë¤¹¤ëľÁ°¤Î³ä¤ê¹þ¤ß¾õÂÖ¤ò ³ÊǼ¤¹¤ëÎΰè¤Ç¤¹¡£¥Ý¥¤¥ó¥¿¤Ç¤Ï¤Ê¤¤ÅÀ¤ËÃí°Õ¤·¤Æ¤¯¤À¤µ¤¤¡£¤³¤³¤ÇÂàÈò¤·¤¿³ä¤ê¹þ¤ß¾õÂÖ¤ò spin_unlock_irqrestore ¤Ë»ØÄꤹ¤ë¤³¤È¤Ç¡¢³ä¤ê¹þ¤ß¾õÂÖ¤ò¸µ¤ËÌ᤹¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£

    read Åù¤Î¥×¥í¥»¥¹¥³¥ó¥Æ¥­¥¹¥È¤Ë¤ª¤¤¤Æ spin_lock_irqsave / spin_unlock_irqrestore ¤ò»È¤¦¤³¤È¤Ç¡¢¥×¥í¥»¥¹¥³¥ó¥Æ¥­¥¹¥È¤Ç¤Î¥í¥Ã¥¯¼èÆÀÃæ¤Ï³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é¤¬µ¯Æ°¤»¤º¡¢ ¶¥¹ç¤òÈò¤±¤ë¤³¤È¤¬¤Ç¤­¤Þ¤¹¡£Æ±¤¸³ä¤ê¹þ¤ßÈÖ¹æ¤ËÂФ¹¤ë³ä¤ê¹þ¤ß¤¬Æó½Å¤Ë½èÍý¤µ¤ì¤ë¤³¤È¤Ï ¤Ê¤¤ ( ³Î¤«¡£¡£¡£ ) ¤¿¤á¡¢³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é¤¬°ì¤Ä¤Ç¤¢¤ì¤Ð¤½¤ÎÃæ¤Ç¤Ï spin_lock / spin_unlock ¤ÇÎɤ¤¤«¤â¤·¤ì¤Þ¤»¤ó¡£¤·¤«¤·¡¢Ê£¿ô¤Î³ä¤ê¹þ¤ßÈÖ¹æ¤ËÂФ¹¤ë ³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é´Ö¤ÇÇÓ¾¤ò¹Ô¤¦¾ì¹ç¤Ï¡¢³ä¤ê¹þ¤ß¥Ï¥ó¥É¥éÆâ¤Ç¤â spin_lock_irqsave / spin_unlock_irqrestore ¤ò»È¤Ã¤Æ³ä¤ê¹þ¤ß¤ò¶Ø»ß¤¹¤ë¤Ù¤­¤«¤â¤·¤ì¤Þ¤»¤ó¡£ ¤³¤ÎÊÕ¤êÉ®¼Ô¤Ï¤¢¤Þ¤êÄɵᤷ¤Æ¤¤¤Ê¤¤¤Î¤Ç¡¢É¬Íפʾì¹ç¤Ï³Æ¼«¤ÇÄ´ºº¤·¤Æ¤ß¤Æ¤¯¤À¤µ¤¤¡£

    ¤Ê¤ª¡¢irq_main.c ¤Ç¤Ï¡¢ ¥¿¥¤¥à¥¢¥¦¥È¥Ï¥ó¥É¥é¤È¤ÎÇÓ¾½èÍý¤â¤¢¤ë¤¿¤á irq_io.c Æâ¤Ç¤Î test_and_set_bit / clear_bit ¤Ë¤è¤Ã¤Æ½èÍý¤·¤Æ¤¤¤Þ¤¹¡£

  • 183 ¡Á 222 ¹ÔÌÜ ( init_module )

    205 ¡Á 210 ¹ÔÌܤǡ¢request_irq ¤Ë¤è¤Ã¤Æ³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é¤òÅÐÏ¿¤·¤Æ¤¤¤Þ¤¹¡£ ÅÐÏ¿¤ÈƱ»þ¤Ë³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é¤¬Í­¸ú¤Ë¤Ê¤ê¤Þ¤¹¤¬¡¢¥Ç¥Ð¥¤¥¹¤¬ open ¤µ¤ì¤Æ¤¤¤Ê¤±¤ì¤Ð ³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é¤¬É¬Íפʤ¤Íͤʾì¹ç¤Ï¡¢init_module ¤Ç¼Â¹Ô¤¹¤ëɬÍפϤʤ¤¤Ç¤¹¡£ irq_main.c ¤Ç¤Ï¡¢¥æ¡¼¥¶¥×¥í¥»¥¹¤È¤Ï̵´Ø·¸¤Ë À©¸æ¤ò¹Ô¤¦É¬Íפ¬¤¢¤ë¤¿¤á¡¢init_module ¤Ç request_irq ¤ò¼Â¹Ô¤·¤Æ¤¤¤Þ¤¹¡£

    #include <linux/sched.h>
    int request_irq( unsigned int irq, 
                     void (*handler)( int, void*, struct pt_regs* ),
                     unsigned long flags,
                     const char* dev_name,
                     void* dev_id );
    
    

    irq ¤Ï³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é¤òÅÐÏ¿¤¹¤ë³ä¤ê¹þ¤ßÈÖ¹æ¤Ç¡¢handler ¤Ï³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é ¤Î¥Ý¥¤¥ó¥¿¤ò»ØÄꤷ¤Þ¤¹¡£flags ¤Ï¡¢0 ¤¢¤ë¤¤¤Ï linux/sched.h ¤ÇÄêµÁ¤µ¤ì¤Æ¤¤¤ë °Ê²¼¤ÎÄê¿ô¤òÀßÄꤷ¤¿¥Ó¥Ã¥È¥Þ¥¹¥¯¤ò»ØÄꤷ¤Þ¤¹¡£

    Äê¿ô̾ ÀâÌÀ
    SA_INTERRUPT ¥í¡¼¥«¥ë CPU ¤Ë¤ª¤±¤ë³ä¤ê¹þ¤ß¸¡½Ð¤ò̵¸ú¤Ë¤·¤Æ¡¢³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é¤òµ¯Æ°¤¹¤ë
    SA_SHIRQ ³ä¤ê¹þ¤ßÈֹ椬ʣ¿ô¥Ç¥Ð¥¤¥¹´Ö¤Ç¶¦Í­²Äǽ¤Ç¤¢¤ë¡£¤³¤ì¤ò»ØÄꤹ¤ë¾ì¹ç¡¢ dev_id ¤Ë NULL ¤ò»ØÄꤷ¤Æ¤Ï¤Ê¤é¤º¡¢¤«¤Ä³Æ dev_id ¤Ï¥æ¥Ë¡¼¥¯¤Ç¤Ê¤±¤ì¤Ð¤Ê¤é¤Ê¤¤ ( ³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é¤ò¼±Ê̤¹¤ëɬÍפ¬¤¢¤ë¤¿¤á )¡£¤Þ¤¿¡¢Æ±¤¸³ä¤ê¹þ¤ßÈÖ¹æ¤Ç Ê£¿ô¤Î³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é¤¬µ¯Æ°¤µ¤ì¤ë¤¿¤á¡¢¥Ï¥ó¥É¥éÆâ¤Ç³ä¤ê¹þ¤ß¾õÂÖ¤òÁàºî¤·¤Æ¤Ï ¤¤¤±¤Ê¤¤
    SA_SAMPLE_RANDOM À¸À®¤µ¤ì¤¿³ä¤ê¹þ¤ß¤¬¡¢¥·¥¹¥Æ¥à¤Î¥¨¥ó¥È¥í¥Ô¡¼À¸À®¤Ë»È¤ï¤ì¤ë¡£¥¨¥ó¥È¥í¥Ô¡¼¤ÏÍð¿ô¤ÎÀ¸À®¸»¤È¤Ê¤ê¡¢°Å¹æ½èÍýÅù¤Ç¿¿¤ÎÍð¿ô¤òɬÍפȤ¹¤ë¥½¥Õ¥È¥¦¥§¥¢¤ÇɬÍפȤʤ롣³ä¤ê¹þ¤ß¤Î¥¿¥¤¥ß¥ó¥°¤¬Í½Â¬²Äǽ¤Ê¾ì¹ç¤ä¡¢³°Éô¤«¤éÁàºî²Äǽ¤Ç¤¢¤ë¾ì¹ç¤Ï¡¢¥¨¥ó¥È¥í¥Ô¡¼¤ÎÊ£»¨¤µ¤ò²¼¤²¤Æ¤·¤Þ¤¦¤¿¤á¡¢¤³¤Î¥Õ¥é¥°¤ò»ØÄꤷ¤Æ¤Ï¤¤¤±¤Ê¤¤

    dev_name ¤Ï /proc/interrupts ¤Ë¤ª¤¤¤Æ³ä¤ê¹þ¤ßÈÖ¹æ¤Î½êÍ­¼Ô¤È¤·¤Æ»ÈÍѤµ¤ì¤ëʸ»úÎó¤ò»ØÄꤷ¤Þ¤¹¡£ ¤Þ¤¿¡¢dev_id ¤Ï³ä¤ê¹þ¤ß¶¦Í­»þ¤Ë³ä¤ê¹þ¤ß¥Ï¥ó¥É¥é¤ò¼±Ê̤¹¤ë¤¿¤á¤Î¥æ¥Ë¡¼¥¯¤Ê¼±ÊÌ»Ò¤È¤Ê¤ë ¥Ç¡¼¥¿¤Ø¤Î¥Ý¥¤¥ó¥¿¤ò»ØÄꤷ¤Þ¤¹¡£³ä¤ê¹þ¤ß¶¦Í­»þ¤Ë¤Ï¡¢dev_id ¤ò NULL ¤Ë¤·¤Æ¤Ï¤¤¤±¤Þ¤»¤ó¡£ ¶¦Í­¤·¤Ê¤¤¾ì¹ç¤Ï NULL ¤Ç¤â¹½¤¤¤Þ¤»¤ó¡£¤³¤³¤Ç»ØÄꤷ¤¿¥Ý¥¤¥ó¥¿¤Ï¡¢³ä¤ê¹þ¤ß¥Ï¥ó¥É¥éµ¯Æ°»þ¤Ë °ú¿ô¤È¤·¤ÆÅϤµ¤ì¤Þ¤¹¡£

    212 ¡Á 213 ¹ÔÌܤǤϡ¢ºÇ¸å¤Ë½é´ü¾õÂÖ¤ËÌ᤹°Ù¤Ë¥Ç¡¼¥¿¥Ý¡¼¥È¤ª¤è¤Ó ¥³¥ó¥È¥í¡¼¥ë¥Ý¡¼¥È¤Î¾õÂÖ¤òÊݸ¤·¤Æ¤¤¤Þ¤¹¡£

    216 ¹ÔÌÜ¤Ç io_enable_irq ¤Ë¤è¤Ã¤Æ¡¢¥Ñ¥é¥ì¥ë¥Ý¡¼¥È¤«¤é¤Î³ä¤ê¹þ¤ß¤òÍ­¸ú¤Ë¤·¤Æ¤¤¤Þ¤¹¡£ ¤³¤ì°Ê¹ß¡¢¥×¥Ã¥·¥å¥Ü¥¿¥ó¤ò²¡¤·¤¿¾õÂÖ¤«¤éÎ¥¤·¤¿ºÝ¤Ë¡¢³ä¤ê¹þ¤ßÈÖ¹æ 7 ÈÖ ( ¤ª»È¤¤¤Î´Ä¶­¤Ë¤è¤Ã¤Æ°Û¤Ê¤ê¤Þ¤¹ ) ¤Î³ä¤ê¹þ¤ß¤¬È¯À¸¤·¤Þ¤¹¡£

  • 225 ¡Á 246 ¹ÔÌÜ ( cleanup_module )

    233 ¹ÔÌܤǡ¢free_irq ¤Ë¤è¤Ã¤Æ³ä¤ê¹þ¤ß¥Ï¥ó¥É¥éÅÐÏ¿¤òºï½ü¤·¤Æ¤¤¤Þ¤¹¡£

    #include <linux/sched.h>
    void free_irq( unsigned int irq, void* dev_id );
    
    

    ³ä¤ê¹þ¤ßÈÖ¹æ¤Î»ÈÍѤ¬½ª¤ï¤Ã¤¿¤é¡¢free_irq ¤ò»È¤Ã¤Æɬ¤º²òÊü¤·¤Æ¤¯¤À¤µ¤¤¡£

    ¤Þ¤¿¡¢235 ¡Á 256 ¹ÔÌܤǥǡ¼¥¿¥Ý¡¼¥È¤ª¤è¤Ó¥³¥ó¥È¥í¡¼¥ë¥Ý¡¼¥È¤ò ½é´ü¾õÂÖ¤ËÌᤷ¤Æ¤¤¤Þ¤¹¡£

°Ê¾å¤Ç irq_io.h¡¢irq_io.c¡¢irq_main.c ¤Î²òÀâ¤Ï½ª¤ï¤ê¤Ç¤¹¡£