LINUX.ORG.RU

Сообщения sigill

 

pci driver

Пишу драйвер для одного 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;
}

Буду признателен за любые советы и замечания.

>>>

sigill
()

ATAPI

Необходимо ATAPI CD-ROM драйву, по ATAPI отсылать комманду (не стандартную). Есть софт под Windows который это делает, теперь мне надо сделать тоже самое в Linux. Так как экспиренса особого нет в Linux ATAPI специфики, у меня возник вопрос. Можно ли из userspace отослать произвольную ATAPI команду ATAPI устройству. Или для этого нужно писать/модифицировать драйвер. Как варинт есть идея модифицировать драйвер ide-cd. Есть ли еще варианты?

sigill
()

resolv.conf

Есть pppd работающий в режиме on demand. И программа которая по некоторому событию начинает соединяться с удалённым сервером. Когда pppd установил соединение он переписывает файл resolv.conf, прописываю туда адреса DNS серверов провайдера. А программа ресолвит имена через gethostbyname и даже после того как файл resolv.conf был переписан не может отресолвить имя удаленного хоста. Только если прервать работу программы и запустить её заново, всё ресолвиться замечательно. Вопрос, как заставить программу без перезапуска обновлять информацию о DNS серверах?

sigill
()

Вопрос по драйверу для PCI устройства

Есть плата с DSP процессором от SpectrumDigital. У платы есть PCI
интерфейс. Вместе с платой шёл пример работы с PCI сделанный с помощью
Jungo, в примере можно почитать/пописать память устройства и.т.д. 
Теперь мне бы хотелось написать драйвер для этой платы под Linux, 
который для начала мог бы моргать светодиодами на самой плате. Я 
написал простой дарйвер, который находит эту плату, определяет её 
ресурсы (там два MMIO) и делает ioremap. Теперь я хотел бы через 
writeb записать в регистр определящий состояние светодиодов своё 
значение. 

В примере идущим с платой есть файл dm642_lib.h
в нём есть следующие определения.

#define kBaseAddr_CE0    (0x80000000u)
#define kBaseAddr_CE1    (0x90000000u)
#define kBaseAddr_CE2    (0xA0000000u)
#define kBaseAddr_CE3    (0xB0000000u)

#define kFpgaAmrOffs           (0x00080010)
#define kFpgaAmrBaseAddress    (kBaseAddr_CE1 + kFpgaAmrOffs)

enum
{
    kFamrOffs_OSDCR = kFpgaAmrOffs,  // OSD Control Reg       => 0x9008_0010
    kFamrOffs_DMATLR,                // DMA Threshold LSB Reg => 0x9008_0011
    kFamrOffs_DMATMR,                // DMA Threshold MSB Reg => 0x9008_0012
    kFamrOffs_ISR,                   // Interrupt Status Reg
    kFamrOffs_IER,                   // Interrupt Enable Reg
    kFamrOffs_GPIODR,                // GPIO Direction Reg
    kFamrOffs_GPIOSR,                // GPIO Status Reg
    kFamrOffs_LEDR,                  // LED Reg
    kFamrOffs_FPR,                   // Flash Page Reg        => 0x9008_0018

    kFamrOffs_RESERVED,              // Reserved (19 - 1E)

    kFamrOffs_FVR = kFpgaAmrOffs + 0xF  // FPGA Version Reg   => 0x9008_001F
};


И когда из программы-примера (того что в комплекте) пишу по адресу 
0x90080017 своё значение, то светодиоды меняют своё состояние. 
Соотвественно у меня такой вопрос как мне имея на руках адрес 
полученный через ioremap(mmio_start, mmio_len) записать по адресу 
0x90080017 своё значение в драйвере под Linux?
sigill
()

Кулинарный, так сказать ОПРОС :)

Интересуют кулинарные предпочтения ЛОРовцев. Проще говоря, кто что любит покушать и приготовить. Рецепты фирменных блюд приветствуются :)

sigill
()

RSS подписка на новые темы