xxxmatrixxx
Интересующийся
Сообщений: 3
|
|
« : 13 Февраль, 2018, 11:16:13 » |
|
Всем добрый день!!! Есть плата с шиной Pci Express, в данной плате реализована работа MSI прерываний я написал драйвер под Linux, разрешение MSI прерываний осуществляется через функцию pci_msi_anable и все хорошо работало, пока не появилась потребность переписать драйвер под QNX 6.5.0 X86 по документации на pci server(стандартный, что устанавливается вместе с QNX), достаточно просто передать флаг PCI_USE_MSI в функцию pci_attach_device и все само настроится... но вот только не работает... const struct sigevent *irq_handler(void *arg, int id) { printf("\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n"); printf("\nDEV_MIL_DRV_UDx: irq_handler(): begin.\n"); fflush(stdout);
uint32_t ri, mi, mci, rci; DEVICE_MIL *dm; int eu = 0; dm = (DEVICE_MIL *)arg;
struct sigevent event; int i = 0,err = 0;
//максируем прерывание InterruptMask(dm->irq_num,id); //////////////////////////////////// !!!code!!! ///////////////////////////////////// InterruptUnmask(dm->irq_num,id); return 0; }
static __inline__ int pci_detect_card(void) { unsigned int minor = 0, devfunc, bus; int status; int i;
uint32_t addr_dma_lo, addr_dma_hi;
// создаем поток для драйвера(должны быть root права) ThreadCtl( _NTO_TCTL_IO, 0 );
printf("\nDEV_MIL_DRV_UDx: try attach to pci-server..");
// подключение к pci серверу pci_hndl = pci_attach(0);
if (pci_hndl == -1) { printf("\nDEV_MIL_DRV_UDx: error unable to attach pci"); perror("\npci_attach:"); printf("\nDEV_MIL_DRV_UDx: DEVICE DON'T CREATE"); return - 1; }
printf("\nDEV_MIL_DRV_UDx: pci_attach good");
plata_cnt = 0;
do{ // проверяем, что слишком много устройств найдено if(plata_cnt >= MINOR_CNT){ printf("\nDEV_MIL_DRV_UDx: find MAX device(%d) -> exit find device",MINOR_CNT); return 0; } //заполняем структуру для поиска memset( &device_mil[minor].pci_info, 0, sizeof( device_mil[minor].pci_info ) ); device_mil[minor].pci_info.VendorId = VENDOR_ID; device_mil[minor].pci_info.DeviceId = DEVICE_ID_UDx;
// начинаем поиск устройства на шине pci status=pci_find_device(device_mil[minor].pci_info.DeviceId,device_mil[minor].pci_info.VendorId,minor,&bus,&devfunc ); if (status!=PCI_SUCCESS){ device_mil[minor].pci_info.DeviceId = DEVICE_ID_mPCIe; status=pci_find_device(device_mil[minor].pci_info.DeviceId,device_mil[minor].pci_info.VendorId,minor,&bus,&devfunc ); if (status!=PCI_SUCCESS){ if(minor == 0) // если нет ни одного устройства на шине { printf("\nDEV_MIL_DRV_UDx: don't find device"); goto err1; } else{ printf("\nDEV_MIL_DRV_UDx: find %d device",plata_cnt); return 0; } } }
// запоминаем индекс устройства device_mil[minor].minor = minor; plata_cnt++; // увеличиваем общее количество устройств
printf("\nDEV_MIL_DRV_UDx: pci_find_device good"); printf("\nDEV_MIL_DRV_UDx: Find device(Vendor_ID = %x, Device_ID = %x, Minor = %d)",device_mil[minor].pci_info.DeviceId,device_mil[minor].pci_info.VendorId, minor); device_mil[minor].vendor_id = device_mil[minor].pci_info.VendorId; device_mil[minor].device_id = device_mil[minor].pci_info.DeviceId;
// подключение к pci устройству device_mil[minor].pci_dev_hndl = pci_attach_device(NULL,( PCI_SHARE | PCI_SEARCH_VENDEV | PCI_INIT_ALL | PCI_INIT_IRQ | PCI_MASTER_ENABLE | PCI_USE_MSI),minor,&device_mil[minor].pci_info); if(device_mil[minor].pci_dev_hndl == NULL){ printf("\nDEV_MIL_DRV_UDx: error attach device"); perror("\npci_attach_device:"); goto err2; }
printf("\nDEV_MIL_DRV_UDx: pci_attach_device good");
printf("\nDEV_MIL_DRV_UDx: SUMMARY INFO DEVICE"); printf("\nDEV_MIL_DRV_UDx: Device_ID = 0x%x",device_mil[minor].pci_info.DeviceId); printf("\nDEV_MIL_DRV_UDx: Vendor_ID = 0x%x",device_mil[minor].pci_info.VendorId); printf("\nDEV_MIL_DRV_UDx: Bus Number = 0x%x",device_mil[minor].pci_info.BusNumber); printf("\nDEV_MIL_DRV_UDx: Device Function = 0x%x",device_mil[minor].pci_info.DevFunc); printf("\nDEV_MIL_DRV_UDx: Device Class = 0x%x",device_mil[minor].pci_info.Class); printf("\nDEV_MIL_DRV_UDx: Device IRQ = 0x%x(%d)",device_mil[minor].pci_info.Irq,device_mil[minor].pci_info.Irq); printf("\nDEV_MIL_DRV_UDx: MSI REG = 0x%x",device_mil[minor].pci_info.msi); device_mil[minor].bars = 0; for(i =0; i < 6; i++){ printf("\nDEV_MIL_DRV_UDx: BAR%d Address = 0x%x, Size = 0x%x",i,(uint32_t)(device_mil[minor].pci_info.CpuBaseAddress[i]),(uint32_t)(device_mil[minor].pci_info.BaseAddressSize[i])); // смотрим, что за бар у нас if ((PCI_IS_MEM(device_mil[minor].pci_info.CpuBaseAddress[i])) && (device_mil[minor].pci_info.CpuBaseAddress[i]!=0x00000000)){ printf("\nDEV_MIL_DRV_UDx: BAR%d is Memory",i); device_mil[minor].bars++; } else if((PCI_IS_IO(device_mil[minor].pci_info.CpuBaseAddress[i])) && (device_mil[minor].pci_info.CpuBaseAddress[i]!=0x00000000)){ printf("\nDEV_MIL_DRV_UDx: BAR%d is I/O",i); device_mil[minor].bars++; } } // инициализаци bar0 if ((PCI_IS_MEM(device_mil[minor].pci_info.CpuBaseAddress[0])) && (device_mil[minor].pci_info.CpuBaseAddress[0]!=0x00000000)){ printf("\nDEV_MIL_DRV_UDx: BAR0 is Memory"); printf("\nDEV_MIL_DRV_UDx: BAR0 Address = 0x%x, Size = 0x%x",(uint32_t)(device_mil[minor].pci_info.CpuBaseAddress[0]),(uint32_t)(device_mil[minor].pci_info.BaseAddressSize[0])); // физический адрес device_mil[minor].base_addr0 = PCI_MEM_ADDR(device_mil[minor].pci_info.CpuBaseAddress[0]); printf("\nDEV_MIL_DRV_UDx: PCI_MEM_ADDR BAR0 Address = 0x%lx",(unsigned long int)device_mil[minor].base_addr0); // виртуальный адрес device_mil[minor].base_addr = mmap_device_memory(NULL, device_mil[minor].pci_info.BaseAddressSize[0], PROT_NOCACHE | PROT_READ | PROT_WRITE, 0, device_mil[minor].base_addr0); printf("\nDEV_MIL_DRV_UDx: mmap_device_memory base_addr0 = 0x%lx,base_addr = 0x%lx",(unsigned long int)device_mil[minor].base_addr0,(unsigned long int)device_mil[minor].base_addr); if ( device_mil[minor].base_addr == MAP_FAILED ) { printf("\nDEV_MIL_DRV_UDx: mmap device memory failed"); perror( "\nmmap_device_memory for physical address failed" ); goto err2; } } else { printf("\nDEV_MIL_DRV_UDx: BAR0 is BAD"); goto err2; }
printf("\nDEV_MIL_DRV_UDx: allocate BAR0");
// выделяем память под dma device_mil[minor].addr_dma = mmap(0,SIZE_DMA,(PROT_READ | PROT_WRITE | PROT_NOCACHE), MAP_ANON | MAP_PHYS ,NOFD,0); if(device_mil[minor].addr_dma == MAP_FAILED){ printf("\nDEV_MIL_DRV_UDx: dma mmap failed"); perror("\nmmap:"); goto err3; } if( mem_offset64(device_mil[minor].addr_dma,NOFD,SIZE_DMA,(off64_t *)&device_mil[minor].addr_dma_1,0) != 0){ printf("\nDEV_MIL_DRV_UDx: don't get physical address"); perror("\nmem_offset:"); goto err4; }
printf("\nDEV_MIL_DRV_UDx: DMA addr_dma1 = 0x%lx,addr_dma = 0x%lx",(unsigned long int)device_mil[minor].addr_dma_1,(unsigned long int)device_mil[minor].addr_dma); //memset(device_mil[minor].addr_dma, 0x12, SIZE_DMA); // clear DMA addr_dma_lo = (device_mil[minor].addr_dma_1 & 0xffffffff); // low part address DMA addr_dma_hi = (device_mil[minor].addr_dma_1 >> 32) & 0xffffffff; // hi part address DMA *(uint32_t*)(device_mil[minor].base_addr + DMA_DATA_BASE) = addr_dma_lo; *(uint32_t*)(device_mil[minor].base_addr + DMA_DATA_BASE_HI) = addr_dma_hi; printf("\nDEV_MIL_DRV_UDx: to address = 0x%lx was written 0x%x", (long unsigned int)(device_mil[minor].base_addr + DMA_DATA_BASE),(unsigned int) addr_dma_lo); printf("\nDEV_MIL_DRV_UDx: to address = 0x%lx was written 0x%x", (long unsigned int)(device_mil[minor].base_addr + DMA_DATA_BASE_HI), (unsigned int)addr_dma_hi); printf("\nDEV_MIL_DRV_UDx: allocate DMA");
//записываем номер MSI прерывания device_mil[minor].irq_num = device_mil[minor].pci_info.Irq; if(device_mil[minor].pci_info.msi) printf("\nDEV_MIL_DRV_UDx: MSI enable, MSI irq is %d",device_mil[minor].irq_num); else printf("\nDEV_MIL_DRV_UDx: !!! MSI DON'T ENABLE, YOU MUST DON'T USE INTERRUPT FOR WORK WITH MODULE!!!");
//регистрируем обработчик прерывания device_mil[minor].di.int_id = InterruptAttach(device_mil[minor].irq_num,irq_handler,&device_mil[minor],sizeof(device_mil[minor]),_NTO_INTR_FLAGS_END | _NTO_INTR_FLAGS_TRK_MSK); if(device_mil[minor].di.int_id == -1) { printf("\nDEV_MIL_DRV_UDx: error interrupt attach"); perror("\nInterruptAttach:"); goto err4; }
// определяем тип и преобразуем его device_mil[minor].dev_type = ((*(uint32_t*)(device_mil[minor].base_addr + 0x1034)) >> 24) & 0xFF; printf("\nDEV_MIL_DRV_UDx: DEVICE TYPE = 0x%x", device_mil[minor].dev_type); switch (device_mil[minor].dev_type){ case 0x03: device_mil[minor].dev_type = PCIe_1553UD; break; case 0x23: device_mil[minor].dev_type = PCIe_1553UD2; break; case 0x43: device_mil[minor].dev_type = PCIe_1553UD4; break; default: printf("\nDEV_MIL_DRV_UDx: error device type"); goto err5; break; }
sprintf((char *)&device_mil[minor].dev_name, "/dev/%s_%d",MIL1553UDx_DRIVER_MASKNAME,minor); printf("\nDEV_MIL_DRV_UDx: device path with name is %s",device_mil[minor].dev_name); status = pthread_mutex_init(&device_mil[minor].mutex_dma,NULL); if(status != EOK) { printf("\nDEV_MIL_DRV_UDx: error pthread mutex init %d",status); perror("\npthread_mutex_init:"); goto err5; } printf("\nDEV_MIL_DRV_UDx: DEVICE CREATE GOOD"); fflush(stdout); minor++; }while(1);
// подчищаем текущее устройство err5: for(minor = 0; minor < plata_cnt; minor++) InterruptDetach(device_mil[minor].di.int_id); err4: for(minor = 0; minor < plata_cnt; minor++) munmap(device_mil[minor].addr_dma, SIZE_DMA); err3: for(minor = 0; minor < plata_cnt; minor++) munmap_device_memory(device_mil[minor].base_addr, device_mil[minor].pci_info.BaseAddressSize[0]); err2: for(minor = 0; minor < plata_cnt; minor++) pci_detach_device(device_mil[minor].pci_dev_hndl); err1: pci_detach(pci_hndl);
printf("\nDEV_MIL_DRV_UDx: DEVICE DON'T CREATE"); return -1; }
я изменил загрузчик QNX, чтобы он загружал startup-apic и pci-bios-v2(qnxbasesmp-apic.build) # # The build file for QNX Neutrino booting on a PC # [linker="ntox86-ld -T$QNX_TARGET/x86/lib/nto.link %(h!=0, -Ttext 0x%t%)%(d!=0, -Tdata 0x%d%) -o%o %i %[M -L%^i -uinit_%n -lmod_%n%]"] [virtual=x86,bios +compress] boot = { # Reserve 64k of video memory to handle multiple video cards startup-apic -v -s64k
# PATH is the *safe* path for executables (confstr(_CS_PATH...)) # LD_LIBRARY_PATH is the *safe* path for libraries (confstr(_CS_LIBPATH)) # i.e. This is the path searched for libs in setuid/setgid executables. PATH=/proc/boot:/bin:/usr/bin:/opt/bin LD_LIBRARY_PATH=/proc/boot:/lib:/usr/lib:/lib/dll:/opt/lib procnto-smp-instr }
[+script] startup-script = { # To save memory make everyone use the libc in the boot image! # For speed (less symbolic lookups) we point to libc.so.3 instead of libc.so procmgr_symlink ../../proc/boot/libc.so.3 /usr/lib/ldqnx.so.2
# Default user programs to priorty 10, other scheduler (pri=10o) # Tell "diskboot" this is a hard disk boot (-b1) # Tell "diskboot" to use DMA on IDE drives (-D1) # Start 4 text consoles buy passing "-n4" to "devc-con" (-o) # By adding "-e" linux ext2 filesystem will be mounted as well. [pri=10o] PATH=/proc/boot diskboot -b1 -D1 -odevc-con,-n4 -odevc-con-hid,-n4 }
# Include the current "libc.so". It will be created as a real file using # its internal "SONAME", with "libc.so" being a symlink to it. The symlink # will point to the last "libc.so.*" so if an earlier libc is needed # (e.g. libc.so.1) add it before the this line. libc.so libhiddi.so libusbdi.so
# Include all the files for the default filesystems libcam.so io-blk.so cam-disk.so fs-qnx4.so fs-qnx6.so fs-dos.so fs-ext2.so cam-cdrom.so fs-cd.so fs-udf.so fs-nt.so fs-mac.so
# USB for console driver devu-ehci.so devu-ohci.so devu-uhci.so devh-usb.so devh-ps2ser.so
[data=copy] seedres pci-bios=pci-bios-v2 devb-eide devb-umass devb-ahci devb-mvSata devb-adpu320 devb-aha8 umass-enum [search=${QNX_TARGET}/etc] umass-enum.cfg io-usb io-hid diskboot slogger fesh devc-con devc-con-hid
# These files will be unlinked after the system has started # to release the memory back to the system. They are only # needed during boot. If needed later on, they will be loaded # from the boot device. unlink_list={ /proc/boot/devb-* }
в драйвере подключаюсь к pci server и инициализирую msi прерывания, затем подключаю обработчик прерывания, но в обработчик прерывания драйвер не заходит(нет сообщений из обработчика), причем я точно знаю, что с модуля tlp пакет msi сообщения уходит, именно на стороне QNX оно игнорируется или блокируется лог pci -vvv после загрузки драйвера Class = Communication (Other) Vendor ID = a203h, Unknown Device ID = 9472h, Unknown Unknown PCI index = 0h Class Codes = 078000h Revision ID = 3h Bus number = 3 Device number = 0 Function num = 0 Status Reg = 10h Command Reg = 507h I/O space access enabled Memory space access enabled Bus Master enabled Special Cycle operations ignored Memory Write and Invalidate disabled Palette Snooping disabled Parity Error Response disabled Data/Address stepping disabled SERR# driver enabled Fast back-to-back transactions to different agents disabled PCI INTx disabled Header type = 0h Single-function BIST = 0h Build-in-self-test not supported Latency Timer = 0h Cache Line Size= 8h un-cacheable BAR - 0 [Mem] = f7d80000h 64bit length 524288 enabled Subsystem Vendor ID = a203h Subsystem ID = 9472h Max Lat = 0ns Min Gnt = 0ns PCI Int Pin = INT A Interrupt line = 4 CPU Interrupt = 104h Capabilities Pointer = 40h Capability ID = 1h - Power Management Capabilities = 7e03h - 8h Capability ID = 5h - Message Signaled Interrupts Capabilities = 81h - fee00000h Enabled Capability ID = 10h - PCI Express Capabilities = 1h - 288fc0h Device Dependent Registers: 0x040: 0148 037e 0800 0000 0558 8100 0000 e0fe 0x050: 0000 0000 5200 0000 1000 0100 c08f 2800 0x060: 1028 0b00 11f4 0300 0000 1110 0000 0000 0x070: 0000 0000 0000 0000 0000 0000 0000 0000 ... 0x0f0: 0000 0000 0000 0000 0000 0000 0000 0000
лог загрузки драйвера DEV_MIL_DRV_UDx: try attach to pci-server.. DEV_MIL_DRV_UDx: pci_attach good DEV_MIL_DRV_UDx: pci_find_device good DEV_MIL_DRV_UDx: Find device(Vendor_ID = 9472, Device_ID = a203, Minor = 0) DEV_MIL_DRV_UDx: pci_attach_device good DEV_MIL_DRV_UDx: SUMMARY INFO DEVICE DEV_MIL_DRV_UDx: Device_ID = 0x9472 DEV_MIL_DRV_UDx: Vendor_ID = 0xa203 DEV_MIL_DRV_UDx: Bus Number = 0x3 DEV_MIL_DRV_UDx: Device Function = 0x0 DEV_MIL_DRV_UDx: Device Class = 0x78000 DEV_MIL_DRV_UDx: Device IRQ = 0x104(260) DEV_MIL_DRV_UDx: MSI REG = 0x1 DEV_MIL_DRV_UDx: BAR0 Address = 0xf7d80004, Size = 0x80000 DEV_MIL_DRV_UDx: BAR0 is Memory DEV_MIL_DRV_UDx: BAR1 Address = 0x0, Size = 0x0 DEV_MIL_DRV_UDx: BAR2 Address = 0x0, Size = 0x0 DEV_MIL_DRV_UDx: BAR3 Address = 0x0, Size = 0x0 DEV_MIL_DRV_UDx: BAR4 Address = 0x0, Size = 0x0 DEV_MIL_DRV_UDx: BAR5 Address = 0x0, Size = 0x0 DEV_MIL_DRV_UDx: BAR0 is Memory DEV_MIL_DRV_UDx: BAR0 Address = 0xf7d80004, Size = 0x80000 DEV_MIL_DRV_UDx: PCI_MEM_ADDR BAR0 Address = 0xf7d80000 DEV_MIL_DRV_UDx: mmap_device_memory base_addr0 = 0xf7d80000,base_addr = 0x40100000 DEV_MIL_DRV_UDx: allocate BAR0 DEV_MIL_DRV_UDx: DMA addr_dma1 = 0xbc800000,addr_dma = 0x8400000 DEV_MIL_DRV_UDx: to address = 0x40101000 was written 0xbc800000 DEV_MIL_DRV_UDx: to address = 0x40101004 was written 0x0 DEV_MIL_DRV_UDx: allocate DMA DEV_MIL_DRV_UDx: MSI enabled, MSI IRQ is 260 DEV_MIL_DRV_UDx: DEVICE TYPE = 0x43 DEV_MIL_DRV_UDx: device path with name is /dev/PCIe_1553UDx_0 DEV_MIL_DRV_UDx: DEVICE CREATE GOOD DEV_MIL_DRV_UDx: find 1 device DEV_MIL_DRV_UDx: attach resource manager for device with name /dev/PCIe_1553UDx_0 DEV_MIL_DRV_UDx: resource manager attach, minor = 0 DEV_MIL_DRV_UDx: start pool 1 threads DEV_MIL_DRV_UDx: io_open DEV_MIL_DRV_UDx: minor = 0
уважаемые форумчане, был ли у кого опыт включения MSI прерываний под QNX 6.5.0 X86, поделитесь, пожалуйста опытом, 2 недели уже бьюсь, пока результата никакого? спасибо, жду вашего ответа
|