Пишу драйвер для одного PCI устройства, для ядра 2.4.32. Устройство представляет собой отладочную плату TI. Драйвер запрашивает у устройства передачу данных по DMA. Для этого он записывает в mailbox команду, необходимые данные и вызывает прерывание. Далее устройство считывает mailbox и выставляет ответное прерывание, что данные прочитаны, и начинает передавать данные через DMA. По окончании передачи данных выставляется второе прерывание. Из юзерспейса запрос данных от устройства происходит через IOCTL. В программе из юзерйспейса я создаю нить pthread и в неё дергую ioctl устройства, проблема в том что если я корректно завершаю работу приложения и дожидаюсь завершения нити все работает хорошо, но стоит мне убить приложение некорректно (через kill) или закрыть терминал, то компьютер наглухо виснет. Еще проблема в том что драйвер не работает на SMP машинах :) Ниже привожу код ioctl case IOCTL_GETRAW: volatile DM64LCPCI_pciRegs * pciRegs = (DM64LCPCI_pciRegs *) ((Uint32) regVirt + (DM64LCPCI_PCIREG_BASE - 0x01C00000)); int i,n,CommandCode; SC_GT_ELEMENT *sglmb; char *data; int *r=((int*)ioctl_param); DECLARE_WAITQUEUE(wait, current); CommandCode = RW_CMD_READ_RAW_FRAME; #ifdef _USE_DEBUG printk("Board: got Xfer CMD %i\n",CommandCode); #endif // Here we lock our spin spin_lock(&sl); if (!expack[CommandCode]) init_waitqueue_head(wq+CommandCode); expack[CommandCode]=RW_CARD_CMD(CommandCode); expack[0]=RW_CARD_CMD(CommandCode); mb->HostRequest.CommandCode=RW_HOST_CMD(CommandCode); mb->HostRequest.Info=1; mb->CardRequest[CommandCode].CommandCode=NULL_CMD; mb->CardRequest[CommandCode].Info=0; mb->CardRequest[0].CommandCode=NULL_CMD; sglmb = mb->Sc_Gt_Element; sglmb->Adress = cpu_to_le32(virt_to_bus(pvksdev->raw_buf)); sglmb->Length = cpu_to_le32(0x100000); #ifdef _USE_DEBUG printk("Board: phys of xferBuf = 0x%x\n", mb->Sc_Gt_Element[0].Adress); printk("Board: len of xferBuf = 0x%x\n", mb->Sc_Gt_Element[0].Length); printk("Board: set IRQ%i 4 DSP\n", CommandCode); #endif pciRegs->PCISTATSET = TRIGGER_DSPINT_MASK; sti(); for(i=0;i<0x10000;i++) { if(expack[0]==0x3AEB1C) { #ifdef _USE_DEBUG printk("Board: SGL%i read after %i waiting",CommandCode,i); #endif break; } } if(expack[0]!=0x3AEB1C) { #ifdef _USE_DEBUG printk("Board: cant get SGL%i read!!!",CommandCode);return -2101; #endif } #ifdef _USE_DEBUG printk("Board: releasing spinlock%i...",CommandCode); #endif cli(); spin_unlock(&sl); if(expack[CommandCode]!=0x3AEB1C) { set_current_state(TASK_INTERRUPTIBLE); add_wait_queue(wq+CommandCode, &wait); schedule(); sti(); if(signal_pending(current)) { #ifdef _USE_DEBUG printk("Board: signal%i pending\n",CommandCode); #endif return -2100; } else { #ifdef _USE_DEBUG printk("Board: signal%i not pending\n",CommandCode); #endif } remove_wait_queue(wq+CommandCode, &wait); } else { #ifdef _USE_DEBUG printk("Board: Xfer%i ALREADY done: no need wait\n",CommandCode); #endif } n=mb->CardRequest[CommandCode].Info; #ifdef _USE_DEBUG printk("Board: Receive %d bytes of raw frame\n", n); #endif if (n > 0 && n < 0x100000) copy_to_user(r, (const void*)pvksdev->raw_buf, n); return n; } И еще ниже обработчик прерывания от платы: static void ISR_handler5 (int irq, void * arg, struct pt_regs * flags) { Uint32 status = HAL_CheckPciInterrupt () ; volatile DM64LCPCI_pciRegs * pciRegs = (DM64LCPCI_pciRegs *)((Uint32)regVirt+ (DM64LCPCI_PCIREG_BASE - 0x01c00000)); int i,j,k,l,m,n; IO_REQUEST*r=(IO_REQUEST*)&mb->HostRequest; if (status == 1) { #ifdef _USE_DEBUG printk ("Board: Got DSPIRQ\n") ; #endif r = (IO_REQUEST*)&mb->CardRequest; for( i = 0; i < 5; i++) { if((j=r->CommandCode) != NULL_CMD) { if(expack[i]==j) { expack[i]=0x3AEB1C; if(i) { #ifdef _USE_DEBUG printk("Board: WAKE ch%i ioQ.\n",i); #endif wake_up_interruptible(wq+i);} else { #ifdef _USE_DEBUG printk("Board: SGL ch%i OK.\n",j&0xFF); #endif } } else { r->CommandCode=NULL_CMD; } r->CommandCode=NULL_CMD; } r++; } HAL_PciClearDspInterrupt () ; } return; } Буду признателен за любые советы и замечания.
Ответ на:
комментарий
от idle
Ответ на:
комментарий
от cobold
Ответ на:
комментарий
от anonymous
Ответ на:
комментарий
от idle
Ответ на:
комментарий
от anonymous
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.
Похожие темы
- Форум проблема с обработкой прерывания (2006)
- Форум Определение серийного номера HDD (2004)
- Форум Определение серийного номера HDD (2004)
- Форум Определение серийного номера HDD (2004)
- Форум Валиден ли код? (2018)
- Форум Исследование CryEngine 2 SDK 1.4.0 (2012)
- Форум Обработчик прерывания драйвера UART не вызывается (2015)
- Форум Драйвер чтения и записи (2013)
- Форум вызов generic_make_request из обработчика запросов блочного устройства (2019)
- Форум Передача данных через DMA и PCIe (2020)