LINUX.ORG.RU

проблема с обработкой прерывания


0

0

помогите студенту дописать драйвер :)

дошел до обработки прерываний, нужно по прерыванию запускать пользовательский поток. Че-то написал, но куски кода ниже не работают... :(

///////////////////////////////////////////////////////////////
static void my_wait_irq(int n_dev)
{
u32* LPCI_4C = (u32*) (my_device_table.DeviceInfo[n_dev].MemBase[0]+0x4C);
*LPCI_4C |= 0x49; // разблокировать прерывания на карточке
printk(KERN_ERR "wait for interrupt...\n", n_dev);
interruptible_sleep_on(&my_queue);
}

static void my_int_handler(int irq, void *dev_id, struct pt_regs *regs)
{
u32* LPCI_4C = (u32*)(((my_device_info_t*)dev_id)->MemBase[0]+0x4C);

if(*LPCI_4C & 0x24) {
*LPCI_4C &= ~0x40; // блокируем прерывания на карте
printk(KERN_ERR "interrupt %d seems to be catched!!! :)\n", irq);
wake_up_interruptible(&my_queue);
}
}

static int my_request_irq(int dev_no)
{
char name[sizeof("mydev00") + 1];
int ret, irq;

irq = my_device_table.DeviceInfo[dev_no].IRQ;

sprintf(name, "mydev%d", dev_no);
ret = request_irq(irq, my_int_handler, SA_SHIRQ, name, &my_device_table.DeviceInfo[dev_no]);

if(ret) {
printk(KERN_ERR "%s failed to allocate irq %d\n", name, irq);
};

return ret;
}

static int my_ioctl(struct inode *inode, struct file *filp, unsigned int cmd, unsigned long arg)
{
.......
switch(cmd) {
.......
case MY_IOCTL_WAIT_IRQ:
my_wait_irq(n_dev);
break;
.......
return -EINVAL;
};

return ret;
}
///////////////////////////////////////////////////////////////

в юзеровской программе я посылаю MY_IOCTL_WAIT_IRQ и, по плану, после того, как упраление вернется, стоит вызов "обработчика". Но управление не возвращается... %(

помогите, плз :)

anonymous
Ответ на: комментарий от metawishmaster

забыл сказать, ядро - стандартное поставки RH9 (такое условие)
да с ним в остальном, дроде как все ок...

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

> Не правильно! 0 - для конфиг рег. PLX (обычно). Попробуй 3. ok, сейчас попробую...

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

Да... и для регистров устройства не забудь либо базовый адрес к char'у привести, или смещение <<2...

Для INTCSR используй 0x4C и пиши в него 0x40...

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

> как ремапишь ?

я ремапю только в юзер-спейс...
static int mkopci_mmap(struct file *filp, struct vm_area_struct *vma)
{
	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;

	if (offset >= __pa(high_memory) || (filp->f_flags & O_SYNC))
		vma->vm_flags |= VM_IO;
	vma->vm_flags |= VM_RESERVED;

	if (remap_page_range(vma, vma->vm_start, offset, vma->vm_end-vma->vm_start, pgprot_noncached(vma->vm_page_prot)))
		return -EAGAIN;

	return 0;
}


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

> я ремапю только в юзер-спейс...

И что ты ремапишь ??? 

Сделай так:

base1 = pci_resource_start(dev, 3); // Адрес регистров устр-ва
..................................
static int mkopci_mmap (..... {

  virt_rg = __va(base1);
............ Делаешь проверки
  vma->vm_flags |= VM_RESERVED;
  remap_pfn_range(vma, vma->vm_start, page_to_pfn(virt_to_page(virt_rg)),
  vma->vm_end - vma->vm_start, vma->vm_page_prot)
}

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

не получилось :(

> И что ты ремапишь ???
всю память карточки в юзер-спейс (по требованию соответствующей проги). Драйвер только предоставляет память и _должен_ предоставлять прерывания, а вся функциональная нагрузка - на библиотеке времени исполнения...

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

Покажи полностью метод mmap в драйвере и вызов mmap в user-space...

И как получаешь базовые адреса регистров контроллера и карточки...

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

> в смысле, remap_pfn_range появилось только в 2.6.10...

Попробуй io_remap_pfn_range

Ещё попробуй вместо 
remap_pfn_range - remap_page_range, только в третьем аргументе не делай 
page_to_pfn(), а так оставь как я писал..

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

опа... танцы с бубном вокруг Вашего кода привели к такой "мутации": remap_page_range(vma, vma->vm_start, virt_to_phys(virt_rg), vma->vm_end - vma->vm_start, vma->vm_page_prot)

но включаю LPCI_4C из US... раньше на консоль сыпалось, что прерывание не его, теперь говорит, его. Но и как раньше было, в бесконечном цикле... Правда, сейчас контроллер не 9052, а 9050 (вечером поменял, жалко, что тот уже далеко...)

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

> раньше на консоль сыпалось, что прерывание не его, теперь говорит, его. Но и как раньше было, в бесконечном цикле...

Не понял... Ты ща в обработчике анализируешб статус регистр и видишь, что прерывание твое ?

> remap_page_range(vma, vma->vm_start, virt_to_phys(virt_rg), vma->vm_end - vma->vm_start, vma->vm_page_prot)

Для remap_pfn... ты делал 
virt_rg = __va(...Mem[n])
Ща этого не делай, а вот так:
emap_page_range(vma, vma->vm_start,  ...Mem[n],.....

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

ага... 

 59 static void mkopci_int_handler(int irq, void *dev_id, struct pt_regs *regs)
 60 {
 61     u32* LPCI_4C;
 62     LPCI_4C = (u32*)((BYTE*)((mkopcilnx_device_info_t*)dev_id)->MemBase[0]+0x4C);
 63
 64     if(*LPCI_4C & 0x24) {
 65         *LPCI_4C &= ~0x40;
 66         printk(KERN_ERR "mkopci: interrupt %d seems to be catched!!! :)\n", irq);
 67         wake_up_interruptible(&mkopci_queue);
 68     } else {
 69         printk(KERN_ERR "mkopci: is there any interrupts??\n");
 70         return;
 71     }
 72 }

только  сейчас обратил внимание на то, что мне не нравится, что тут MemBase и вспомнил, что в rtx тоже не получалось с MemBase, там были LinBase - уже ремапленые адреса...

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

> там были LinBase - уже ремапленые адреса...

Конечно... Для MemBase[0], если используешь его в драйвере, делай

pci_reg = ioremap_nocache(...MemBase[0]) и в драйвере! по нему обращайся...

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

Aiee!(c)kernel :)

получилось!!! Спасибо всем, и отдельное огромное спасибо eraser'у! :)

ну намучался я с этим... прерывания гораздо красивее(и быстрее!) получились в реализации для RTX %(
но зато там остальное выглядит довольно паршиво, по сравнению с linux'ом... я уже не говорю о еще худшем виде драйверов для 95 и NT

в общем, linux rocks :)

Еще раз, всем спасибо, и отдельная благодарность лично eraser'у :)

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