banner



How To Register Interrupt In Linux

12.1. Interrupt Handlers

12.1.1. Interrupt Handlers

Except for the last chapter, everything we did in the kernel so far we've done as a response to a process asking for it, either by dealing with a special file, sending an ioctl(), or issuing a system call. But the chore of the kernel isn't merely to respond to process requests. Some other job, which is every bit every bit of import, is to speak to the hardware connected to the machine.

There are two types of interaction between the CPU and the rest of the computer'due south hardware. The start blazon is when the CPU gives orders to the hardware, the other is when the hardware needs to tell the CPU something. The second, called interrupts, is much harder to implement because it has to be dealt with when user-friendly for the hardware, not the CPU. Hardware devices typically have a very pocket-size amount of RAM, and if yous don't read their information when bachelor, it is lost.

Under Linux, hardware interrupts are called IRQ's (Interrupt Requests)[1]. There are two types of IRQ'south, short and long. A brusk IRQ is 1 which is expected to take a very brusk period of time, during which the balance of the machine will be blocked and no other interrupts volition be handled. A long IRQ is one which can have longer, and during which other interrupts may occur (but non interrupts from the same device). If at all possible, it's meliorate to declare an interrupt handler to exist long.

When the CPU receives an interrupt, information technology stops whatever information technology's doing (unless it'southward processing a more of import interrupt, in which case it will bargain with this one only when the more important 1 is done), saves certain parameters on the stack and calls the interrupt handler. This ways that certain things are non allowed in the interrupt handler itself, because the system is in an unknown land. The solution to this problem is for the interrupt handler to practice what needs to exist done immediately, unremarkably read something from the hardware or ship something to the hardware, and and so schedule the handling of the new data at a later on fourth dimension (this is called the "lesser half") and return. The kernel is then guaranteed to call the bottom half as soon as possible -- and when it does, everything allowed in kernel modules volition be immune.

The way to implement this is to call request_irq() to get your interrupt handler called when the relevant IRQ is received. [2] This function receives the IRQ number, the name of the role, flags, a name for /proc/interrupts and a parameter to pass to the interrupt handler. Usually there is a certain number of IRQs available. How many IRQs there are is hardware dependant. The flags tin can include SA_SHIRQ to signal you're willing to share the IRQ with other interrupt handlers (usually because a number of hardware devices sit on the aforementioned IRQ) and SA_INTERRUPT to bespeak this is a fast interrupt. This function will just succeed if at that place isn't already a handler on this IRQ, or if you're both willing to share.

And so, from inside the interrupt handler, we communicate with the hardware and then utilize queue_work() mark_bh(BH_IMMEDIATE) to schedule the lesser half.

12.i.2. Keyboards on the Intel Compages

The rest of this affiliate is completely Intel specific. If you're not running on an Intel platform, it will not work. Don't even endeavor to compile the lawmaking here.

I had a problem with writing the sample code for this chapter. On one hand, for an example to be useful it has to run on everybody'southward figurer with meaningful results. On the other manus, the kernel already includes device drivers for all of the common devices, and those device drivers won't coexist with what I'1000 going to write. The solution I've found was to write something for the keyboard interrupt, and disable the regular keyboard interrupt handler first. Since information technology is defined every bit a static symbol in the kernel source files (specifically, drivers/char/keyboard.c), there is no style to restore information technology. Before insmod 'ing this code, do on another concluding sleep 120 ; reboot if you value your file organisation.

This lawmaking binds itself to IRQ 1, which is the IRQ of the keyboard controlled under Intel architectures. Then, when it receives a keyboard interrupt, it reads the keyboard'due south status (that'southward the purpose of the inb(0x64) ) and the browse code, which is the value returned by the keyboard. And so, as presently as the kernel thinks information technology'southward viable, it runs got_char which gives the lawmaking of the key used (the offset seven $.25 of the scan code) and whether information technology has been pressed (if the 8th bit is zilch) or released (if information technology's ane).

Example 12-i. intrpt.c

/*  *  intrpt.c - An interrupt handler.  *  *  Copyright (C) 2001 by Peter Jay Salzman  */  /*   * The necessary header files   */  /*   * Standard in kernel modules   */ #include <linux/kernel.h>	/* We're doing kernel work */ #include <linux/module.h>	/* Specifically, a module */ #include <linux/sched.h> #include <linux/workqueue.h> #include <linux/interrupt.h>	/* Nosotros desire an interrupt */ #include <asm/io.h>  #define MY_WORK_QUEUE_NAME "WQsched.c"  static struct workqueue_struct *my_workqueue;  /*   * This will get called by the kernel equally shortly as it's safe  * to do everything commonly allowed by kernel modules.  */ static void got_char(void *scancode) { 	printk(KERN_INFO "Browse Code %x %s.\due north", 	       (int)*((char *)scancode) & 0x7F, 	       *((char *)scancode) & 0x80 ? "Released" : "Pressed"); }  /*   * This function services keyboard interrupts. Information technology reads the relevant  * information from the keyboard and then puts the non fourth dimension critical  * part into the work queue. This will exist run when the kernel considers information technology safe.  */ irqreturn_t irq_handler(int irq, void *dev_id, struct pt_regs *regs) { 	/*  	 * This variables are static because they demand to be 	 * accessible (through pointers) to the bottom half routine. 	 */ 	static int initialised = 0; 	static unsigned char scancode; 	static struct work_struct task; 	unsigned char status;  	/*  	 * Read keyboard condition 	 */ 	status = inb(0x64); 	scancode = inb(0x60);  	if (initialised == 0) { 		INIT_WORK(&task, got_char, &scancode); 		initialised = 1; 	} else { 		PREPARE_WORK(&job, got_char, &scancode); 	}  	queue_work(my_workqueue, &task);  	return IRQ_HANDLED; }  /*   * Initialize the module - register the IRQ handler   */ int init_module() { 	my_workqueue = create_workqueue(MY_WORK_QUEUE_NAME);  	/*  	 * Since the keyboard handler won't co-exist with another handler, 	 * such equally u.s.a., we have to disable it (free its IRQ) before we practise 	 * anything.  Since we don't know where it is, there's no way to 	 * reinstate it later - then the figurer will accept to be rebooted 	 * when nosotros're done. 	 */ 	free_irq(1, Goose egg);  	/*  	 * Asking IRQ 1, the keyboard IRQ, to go to our irq_handler. 	 * SA_SHIRQ means we're willing to have othe handlers on this IRQ. 	 * SA_INTERRUPT tin be used to make the handler into a fast interrupt. 	 */ 	return request_irq(ane,	/* The number of the keyboard IRQ on PCs */ 			   irq_handler,	/* our handler */ 			   SA_SHIRQ, "test_keyboard_irq_handler", 			   (void *)(irq_handler)); }  /*   * Cleanup   */ void cleanup_module() { 	/*  	 * This is only here for completeness. It'due south totally irrelevant, since 	 * we don't have a fashion to restore the normal keyboard interrupt then the 	 * computer is completely useless and has to be rebooted. 	 */ 	free_irq(1, NULL); }  /*   * some work_queue related functions are just available to GPL licensed Modules  */ MODULE_LICENSE("GPL");

Notes

Ezoic

How To Register Interrupt In Linux,

Source: https://www.linuxtopia.org/online_books/Linux_Kernel_Module_Programming_Guide/x1236.html

Posted by: lairdhaddespeame.blogspot.com

0 Response to "How To Register Interrupt In Linux"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel