|
¡û ¤Ï¤¸¤á¤Ë
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 ¤¬ÅÀÅô¤·¤Æ¤¤¤ë¾õÂ֤Ǥ¹¡£
--- 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 ¤Î²òÀâ¤Ï½ª¤ï¤ê¤Ç¤¹¡£