LINUX.ORG.RU

IRQ 8 request irq

 , , .ko


0

2

Приветствую. Такое дело. Пишу модуль ядра Linux. Нужно определить собственный обработчик прерывания IRQ 8 (прерывание часов реального времени). Но дело в том, что request_irq возращает -16 (Resource busy) при попытке определить свой обработчик аппартного прерывания. Притом, ради интереса, попытался определить обработчик IRQ1 ( прерывание клавиатуры) - все работает -> код по идее правильный.

Кто подскажет, как можно определить свой обработчик для данного прерывания?

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/sched.h>
#include <linux/workqueue.h>
#include <linux/interrupt.h>

#define DRIVER_AUTHOR "Some author"
#define DRIVER_DESC   "Some driver desription"

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

static unsigned long irq1;
static unsigned long irq8;

int init_module()
{
	printk( KERN_INFO "some_module loaded\n");
	int result;
	   
    result = request_irq(1, irq1h, IRQF_PROBE_SHARED | IRQF_SHARED, "keyb0", (void*) (&irq1) );
	
    if( result < 0 )
    {
    	printk( KERN_WARNING "some_module: warning %i\n", result); 
    	return result;
    }
    
    result = request_irq(8, irq8h, IRQF_PROBE_SHARED , "alarm0", (void*) (&irq8) );
	
    if( result < 0 )
    {
    	printk( KERN_WARNING "some_module: warning %i\n", result); 
    	return result;
    }
    

	return 0;
}

void beep()
{
	
}

void irq1h(int irq, void *dev_id, struct pt_regs *regs)
{
	printk( KERN_WARNING  "some_module: IRQ1 received\n");
	printk( KERN_INFO "some_module: scan code: %x\n", inb( 0x60 ));
}

void irq8h(int irq, void *dev_id, struct pt_regs *regs)
{
	printk(KERN_INFO "some_module: IRQ8 received\n");	
	
}

void alarm_beep()
{
	
}

void cleanup_module()
{
	//cleaning 
	free_irq( 8, &irq8 );
	free_irq( 1, &irq1 );
	printk( KERN_INFO "some_module: cleanup\n");
}
 
MODULE_LICENSE("GPL");

libastral.so глючит. Выдаёт всё время «дело в таймаутах...» и так бесконечно. Даже и не знаю чего посоветовать.

vahtu ()

Например, берёте исходники ядра, компилируете его и запускаетесь на нём (лучше на эмуляторе каком-нибудь). Загружаете модуль. Словили ошибку, пошли в код ядра, посмотрели где происходит ошибка, поставили printk с выводом полезной инофрмации, перекомпилировали ядро, запустились, посмотрели на вывод printk и внесли исправления в свой код. Там дело может быть просто в том, что все обработчики должны быть согласованы. А у вас просто флагов не хватает. То есть, если там уже стоит обработчик IRQF_SHARED, то нельзя назначить обработчик без этого флага.

PS. Может нужно просто впихнуть флаг IRQF_TIMER.

anonymous ()
Ответ на: комментарий от vahtu

Пока я никак не работал с оборудованием, я только пытался назначить пустой обработчик, который передает сообщение ядру. Потом там появится логика будильника.

anonymous (14.10.2012 22:45:13), а как узнать , какие флаги нужно передавать?

denisnet ()
Ответ на: комментарий от denisnet

Наверное, только в исходники ядра смотреть. А вообще, попробуйте поставить флаги (IRQF_SHARED | IRQF_PERCPU).

Для общего развития можно почитать Linux Device Drivers (3-е издание и выше) про прерывания.

anonymous ()

request_irq возращает -16 (Resource busy)

Занят он, человеческим языком же написано. В чем проблема посмотреть

cat /proc/interrupts

?

ttnl ★★★★★ ()
Ответ на: комментарий от ttnl

Да понимаю я этот человеческий язык. Как может быть занять девайс - я понимаю. Но как может быть занято «что-то» которое вешает прерывания - я не понимаю.

В interrupts висит на 8 rtc0. Но модуля такого нет, наверное в ядре. А вот на IRQ 1 висит i8042 ( Intel 8042 - контроллер клавиатуры ). Так это никак же не мешает мне добавить свой обработчик перывания, после чего там висит уже i8042, keyb0 (мой).

И еще момент, насколько я понял, эти обработчики ставятся в какую-то очередь, а не подменяется вектор прерываний как в DOS. Я правильно понял?

denisnet ()
Ответ на: комментарий от denisnet

В interrupts висит на 8 rtc0

IRQ8 берет drivers/char/rtc.c или drivers/rtc/rtc-cmos.c (второй более предпочтителен и скорее всего он и используется). Оба драйвера вызывают request_irq() без IRQF_SHARED, а значит свой обработчик вы повесить уже не можете.

Посмотрите теперь в drivers/input/serio/i8042.c, обработчики ставят флаг shared.

И еще момент, насколько я понял, эти обработчики ставятся в какую-то очередь, а не подменяется вектор прерываний как в DOS. Я правильно понял?

Да. Но очередь может быть больше одного, только если все обработчики ставят IRQF_SHARED.

hexdump01010101 ()
Ответ на: комментарий от hexdump01010101

Спасибо. А вот такой флаг что мне даст: IRQF_PROBE_SHARED. И еще, как можно избижать этот неприятный момент с rtc.c? Перекомпилить ядро? И где прописывается, какой именно драйвер RTC будет подгружаться?

denisnet ()
Ответ на: комментарий от hexdump01010101

И такой вопрос возник, есть ли функция, которая позволит переопределить некоторые обработчики на свои, наример, как в моем случае, для IRQ8.

denisnet ()
Ответ на: комментарий от hexdump01010101

Скомпилировал ядро с измененным rtc-cmos.c (просто rtc не было ). Поставил там вместо 0 - IRQF_SHARED. Но проблему это не решило.

denisnet ()
Ответ на: комментарий от ttnl

Все, разобрался. Переписал драйвер, скомпилировал ядро, установил модули, перезагрузил с него - все работает. Только странно, изменяя время в виртуальной машине, изменяется время компьютера.

denisnet ()
Ответ на: комментарий от denisnet

Собственно, ядро тоже перекомпилировал, изменил cmos-rtc.c, флаг 0 заменил на IRQF_SHARED.

denisnet ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.