/** * interrupt_wait() will wait on the PCI interrupt line and determine if GPIO * input or DMA requested the interrupt * * @return 1 if success 0 if failure */ int interrupt_wait(U32 * interrupt) { int rc; /*clear and reset interrupt structure*/ memset(&plx_intr, 0, sizeof (PLX_INTERRUPT)); /*set interrupt structure*/ plx_intr.LocalToPci = 1; //set bit 11 // plx_intr.PciMain = 1; // Bit 8 -- should already been on /*enable interrupt on PLX bridge*/ rc = PlxPci_InterruptEnable(&fpga_dev, &plx_intr); // sets PCI9056_INT_CTRL_STAT if (rc != ApiSuccess) PlxSdkErrorDisplay(rc); /*register for interrupt with kernel*/ rc = PlxPci_NotificationRegisterFor(&fpga_dev, &plx_intr, &plx_event); if (rc != ApiSuccess) PlxSdkErrorDisplay(rc); /*wait for interrupt*/ int waitrc = PlxPci_NotificationWait(&fpga_dev, &plx_event, FPGA_TIMEOUT); /*cancel interrupt notification*/ rc = PlxPci_NotificationCancel(&fpga_dev, &plx_event); if (rc != ApiSuccess) PlxSdkErrorDisplay(rc); /*disable interrupt*/ rc = PlxPci_InterruptDisable(&fpga_dev, &plx_intr); // sets PCI9056_INT_CTRL_STAT if (rc != ApiSuccess) PlxSdkErrorDisplay(rc); /*handle return code of wait function*/ if (waitrc == ApiWaitTimeout) { *interrupt = TIMEOUT_INT; return TRUE; } else if (waitrc == ApiSuccess) { *interrupt = INP_INT; return TRUE; } else if (waitrc == ApiWaitCanceled) { record("Wait canceled\n"); return FALSE; } else { record("Wait returned an unknown value\n"); return FALSE; } }
/*Uses PLX API to write to memory locations on FPGA*/ int poke_gpio(U32 offset, U32 data) { RETURN_CODE rc; //return code U32 return_val = TRUE; /*write data to device*/ rc = PlxPci_PciBarSpaceWrite(&fpga_dev, bar_index, offset, &data, bar_sz_buffer, type_bit, FALSE); /*Check if write was successful*/ if (rc != ApiSuccess) { record("*ERROR* - API failed to write to device \n"); PlxSdkErrorDisplay(rc); return_val = FALSE; } return return_val; }
/*peeks into PCI BAR memory space and places it in data_buf*/ int peek_gpio(U32 offset, U32 * data_buf) { RETURN_CODE rc; //return code U32 return_val = TRUE; /*read data from device*/ rc = PlxPci_PciBarSpaceRead(&fpga_dev, bar_index, offset, data_buf, bar_sz_buffer, type_bit, FALSE); /*Check if write was successful*/ if (rc != ApiSuccess) { record("*ERROR* - API failed to read from device \n"); PlxSdkErrorDisplay(rc); return_val = FALSE; } return return_val; }
/****************************************************************************** * * Function : main * * Description: The main entry point * *****************************************************************************/ int main( void ) { S16 DeviceSelected; PLX_STATUS rc; PLX_DEVICE_KEY DeviceKey; PLX_DEVICE_OBJECT Device; ConsoleInitialize(); Cons_clear(); Cons_printf( "\n\n" "\t\t PLX Local->PCI Interrupt Sample Application\n" "\t\t January 2008\n\n" ); /************************************ * Select Device ************************************/ DeviceSelected = SelectDevice( &DeviceKey ); if (DeviceSelected == -1) { ConsoleEnd(); exit(0); } rc = PlxPci_DeviceOpen( &DeviceKey, &Device ); if (rc != ApiSuccess) { Cons_printf("\n ERROR: Unable to find or select a PLX device\n"); PlxSdkErrorDisplay(rc); _Pause; ConsoleEnd(); exit(-1); } Cons_clear(); Cons_printf( "\nSelected: %04x %04x [b:%02x s:%02x f:%x]\n\n", DeviceKey.DeviceId, DeviceKey.VendorId, DeviceKey.bus, DeviceKey.slot, DeviceKey.function ); // Verify chip is supported switch (DeviceKey.PlxChip) { case 0x9050: case 0x9030: case 0x9080: case 0x9054: case 0x9056: case 0x9656: case 0x8311: break; default: Cons_printf( "ERROR: Device (%04X) does not support generic Local-to-PCI interrupt\n", DeviceKey.PlxChip ); goto _Exit_App; } /************************************ * Perform the DMA ************************************/ InterruptTest( &Device ); /************************************ * Close the Device ***********************************/ _Exit_App: PlxPci_DeviceClose( &Device ); _Pause; Cons_printf("\n\n"); ConsoleEnd(); exit(0); }
void InterruptTest( PLX_DEVICE_OBJECT *pDevice ) { PLX_STATUS rc; PLX_INTERRUPT PlxInterrupt; PLX_NOTIFY_OBJECT NotifyObject; Cons_printf( "Description:\n" " This sample demonstrates how to use the PLX API for\n" " notification of the generic Local->PCI interrupts (e.g. LINTi#).\n" " The interrupt trigger must be initiated by the\n" " OEM hardware. PLX software is not able to manually\n" " assert the interrupt since its source is OEM-dependent.\n" "\n" " Press any key to start...\n" "\n" ); Cons_getch(); Cons_printf(" Register for notification...... "); // Clear interrupt fields memset(&PlxInterrupt, 0, sizeof(PLX_INTERRUPT)); // Setup to wait for either generic interrupt PlxInterrupt.LocalToPci = (1 << 0) | (1 << 1); rc = PlxPci_NotificationRegisterFor( pDevice, &PlxInterrupt, &NotifyObject ); if (rc != ApiSuccess) { Cons_printf("*ERROR* - API failed\n"); PlxSdkErrorDisplay(rc); } else { Cons_printf("Ok\n"); } /*********************************************************** * This loop will loop only one time. It is provided here to * demonstrate which code should be placed within the loop * if waiting for the interrupt multiple times. * Note that the generic L->P interrupt must constantly be * re-enabled since the PLX driver will mask it. **********************************************************/ do { Cons_printf(" Enable interrupt(s)............ "); rc = PlxPci_InterruptEnable( pDevice, &PlxInterrupt ); if (rc != ApiSuccess) { Cons_printf("*ERROR* - API failed\n"); PlxSdkErrorDisplay(rc); } else { Cons_printf("Ok\n"); } Cons_printf( "\n" " -- You may now trigger the interrupt --\n" "\n" ); Cons_printf(" Wait for interrupt event....... "); rc = PlxPci_NotificationWait( pDevice, &NotifyObject, 120 * 1000 ); switch (rc) { case ApiSuccess: Cons_printf("Ok (Int received)\n"); /************************************************ * * Custom code to clear the OEM source of the * interrupt should be placed here. Another option * is to modify the PLX driver interrupt handler * to perform the souce clear. In that case, it * will not constantly need to be masked/re-enabled. * ***********************************************/ break; case ApiWaitTimeout: Cons_printf("*ERROR* - Timeout waiting for Int Event\n"); break; case ApiWaitCanceled: Cons_printf("*ERROR* - Interrupt event cancelled\n"); break; default: Cons_printf("*ERROR* - API failed\n"); PlxSdkErrorDisplay(rc); break; } Cons_printf(" Check notification status...... "); rc = PlxPci_NotificationStatus( pDevice, &NotifyObject, &PlxInterrupt ); if (rc == ApiSuccess) { Cons_printf("Ok (triggered ints:"); if (PlxInterrupt.LocalToPci & (1 << 0)) Cons_printf(" L->P 1"); if (PlxInterrupt.LocalToPci & (1 << 1)) Cons_printf(" L->P 2"); Cons_printf(")\n"); } else { Cons_printf("*ERROR* - API failed\n"); PlxSdkErrorDisplay(rc); } } while (0); // Release the interrupt wait object Cons_printf(" Cancelling Int Notification.... "); rc = PlxPci_NotificationCancel( pDevice, &NotifyObject ); if (rc != ApiSuccess) { Cons_printf("*ERROR* - API failed\n"); PlxSdkErrorDisplay(rc); } else { Cons_printf("Ok\n"); } }
/*sets up the memory used in powering the instrument*/ int init_gpio() { int rc; char msg[255]; gpio_out_state.val = 0; gpio_out_state.bf.tcs1 = 1; // initialize TCS systems to one to ensure that they are off. gpio_out_state.bf.tcs2 = 1; // The TCS systems use inverse logic. gpio_out_state.bf.tcs3 = 1; U32 mask = 0x00000002; unsigned int i; for (i = 0; i < 32; i++) { power_subsystem_mask[i] = mask; mask = mask << 1; } mask = 0x00000001; for (i = 0; i < NUM_CONTROL_GPIO; i++) { gpio_control_mask[i] = mask; mask = mask << 1; } /*initialize bar properties*/ bar_index = (U8) GPIO_BAR_INDEX; bar_sz_buffer = PLX_BUFFER_WIDTH; type_bit = BitSize32; /*Read current BAR properties*/ rc = PlxPci_PciBarProperties(&fpga_dev, bar_index, &bar_properties); /*Check if bar properties were read successfully*/ if (rc != ApiSuccess) { record("*ERROR* - API failed, unable to read BAR properties \n"); PlxSdkErrorDisplay(rc); return FALSE; } /*reset FPGA so interrupts are delivered appropriately*/ reset_fpga(); /*initialize dma channel*/ // initializeDMA(); This is moved to the beginning of fpga.c /*enable GPIO pins on the FPGA*/ // poke_gpio(GPIO_I_INT_ENABLE, 0x87FFFFFF); // Enable all input gpio interrupts poke_gpio(GPIO_I_INT_ENABLE, 0x83FFFFFF); // Disable ddr2 error signal /*initialize acknowledge register*/ poke_gpio(GPIO_I_INT_ACK, 0xFFFFFFFF); // Initialize the system // WriteDword(&fpga_dev, 2, GPIO_I_INT_ENABLE, input_gpio_int_en); // Disable all the input gpio interrupts // input_gpio_int_ack = 0xFFFFFFFF; // WriteDword(&fpga_dev, 2, GPIO_I_INT_ACK, input_gpio_int_ack); // Acknowledge all active interrupts, if any input_gpio_int_ack = 0x00000000; WriteDword(&fpga_dev, 2, GPIO_I_INT_ACK, input_gpio_int_ack); // output_gpio |= 0x00003000; // Set output_gpio value to display LED value 3 // WriteDword(&fpga_dev, 2, 0x14, output_gpio) output_ddr2_addr = 0x003FFFFC; WriteDword(&fpga_dev, 2, OUTPUT_DDR2_ADDRESS_ADDR, output_ddr2_addr); // Sets the DDR2 address to zero (currently unused) output_ddr2_ctrl = 0x00000000; WriteDword(&fpga_dev, 2, OUTPUT_DDR2_CTRL_ADDR, output_ddr2_ctrl); // Set the Data Manager control signal to zero /*set camera interface to simulated or real*/ if (config_values[image_sim_interface] == 0) { gpio_out_state.bf.camer_mux_sel = 0; // Simulated camera interface } else { gpio_out_state.bf.camer_mux_sel = 1; // actual ROE camera interface } sprintf(msg, "Camera mux is: %d\n", gpio_out_state.val); record(msg); rc = poke_gpio(OUTPUT_GPIO_ADDR, gpio_out_state.val); if (rc == FALSE) { record("Error writing GPIO output\n"); } init_shutter(); return TRUE; }
/****************************************************************************** * * Function : main * * Description: The main entry point * *****************************************************************************/ int main( void ) { S16 DeviceSelected; PLX_STATUS rc; PLX_DEVICE_KEY DeviceKey; PLX_DEVICE_OBJECT Device; ConsoleInitialize(); Cons_clear(); Cons_printf( "\n\n" "\t\t PLX DMA Sample Application\n\n" ); /************************************ * Select Device ************************************/ DeviceSelected = SelectDevice_DMA( &DeviceKey ); if (DeviceSelected == -1) { ConsoleEnd(); exit(0); } rc = PlxPci_DeviceOpen( &DeviceKey, &Device ); if (rc != ApiSuccess) { Cons_printf("\n ERROR: Unable to find or select a PLX device\n"); PlxSdkErrorDisplay(rc); _Pause; ConsoleEnd(); exit(-1); } Cons_clear(); Cons_printf( "\nSelected: %04x %04x [b:%02x s:%02x f:%x]\n\n", DeviceKey.DeviceId, DeviceKey.VendorId, DeviceKey.bus, DeviceKey.slot, DeviceKey.function ); /************************************ * Perform the DMA ************************************/ if (((DeviceKey.PlxChip & 0xF000) == 0x8000) && (DeviceKey.PlxChip != 0x8311)) { PerformDma_8000( &Device ); } else { Cons_printf( "ERROR: DMA not supported by the selected device (%04X)\n", DeviceKey.PlxChip ); goto _Exit_App; } /************************************ * Close the Device ***********************************/ _Exit_App: PlxPci_DeviceClose( &Device ); _Pause; Cons_printf("\n\n"); ConsoleEnd(); exit(0); }
void PerformDma_8000( PLX_DEVICE_OBJECT *pDevice ) { U8 *VaBar0 = 0; U8 DmaChannel; U16 UserInput; U32 LoopCount; U32 PollCount; U32 OffsetDmaCmd; U32 ElapsedTime_ms; VOID *BarVa; double Stat_TxTotalCount; double Stat_TxTotalBytes; BOOLEAN bInterrupts; PLX_STATUS status; struct timeb StartTime, EndTime; PLX_DMA_PROP DmaProp; PLX_INTERRUPT PlxInterrupt; PLX_DMA_PARAMS DmaParams; PLX_PHYSICAL_MEM PciBuffer; PLX_NOTIFY_OBJECT NotifyObject; Cons_printf("\n\n"); Cons_printf("Please select a DMA channel (0-3) --> "); Cons_scanf("%hd", &UserInput); if (UserInput >= 4) { Cons_printf("ERROR: Unsupported DMA channel, test aborted\n"); return; } DmaChannel = (U8)UserInput; // Set offset of DMA command register OffsetDmaCmd = 0x200 + (DmaChannel * 0x100) + 0x38; // Determine whether to use interrupts or polling Cons_printf("Use interrupts(i) or poll(p) [i/p]? --> "); UserInput = Cons_getch(); Cons_printf("%c\n\n", UserInput); if (UserInput == 'i' || UserInput == 'I') bInterrupts = TRUE; else bInterrupts = FALSE; /************************************************************** * *************************************************************/ Cons_printf(" Allocate DMA buffer............ "); // Set buffer request size PciBuffer.Size = (8 * 1024 * 1024); // Allocate a buffer status = PlxPci_PhysicalMemoryAllocate( pDevice, &PciBuffer, TRUE // Smaller buffer ok ); if (status != ApiSuccess) { Cons_printf("*ERROR* - API failed\n"); PlxSdkErrorDisplay(status); return; } Cons_printf("Ok (size=%d KB)\n", (PciBuffer.Size >> 10)); /************************************************************** * *************************************************************/ // Open the DMA channel Cons_printf(" Open Channel %i for DMA......... ", DmaChannel); status = PlxPci_DmaChannelOpen( pDevice, DmaChannel, NULL ); if (status == ApiSuccess) { Cons_printf("Ok\n"); } else { Cons_printf("*ERROR* - API failed\n"); PlxSdkErrorDisplay(status); } // Get current DMA properties Cons_printf(" Get DMA propeties.............. "); status = PlxPci_DmaGetProperties( pDevice, DmaChannel, &DmaProp ); if (status != ApiSuccess) { Cons_printf("*ERROR* - API failed\n"); PlxSdkErrorDisplay(status); goto _ExitDmaTest; } Cons_printf("Ok\n"); // Update any DMA properties Cons_printf(" Set DMA propeties.............. "); // Set to support 128B TLP read request size DmaProp.MaxSrcXferSize = PLX_DMA_MAX_SRC_TSIZE_128B; status = PlxPci_DmaSetProperties( pDevice, DmaChannel, &DmaProp ); if (status != ApiSuccess) { Cons_printf("*ERROR* - API failed\n"); PlxSdkErrorDisplay(status); goto _ExitDmaTest; } Cons_printf("Ok\n"); /************************************************************** * *************************************************************/ if (bInterrupts) { Cons_printf(" Register for notification...... "); // Clear interrupt fields memset( &PlxInterrupt, 0, sizeof(PLX_INTERRUPT) ); // Setup to wait for selected DMA channel PlxInterrupt.DmaDone = (1 << DmaChannel); status = PlxPci_NotificationRegisterFor( pDevice, &PlxInterrupt, &NotifyObject ); if (status != ApiSuccess) { Cons_printf("*ERROR* - API failed\n"); PlxSdkErrorDisplay(status); return; } Cons_printf( "Ok\n" ); } else { Cons_printf(" Map BAR 0 for register access.. "); status = PlxPci_PciBarMap( pDevice, 0, &BarVa ); if (status != ApiSuccess) { Cons_printf("*ERROR* - API failed\n"); PlxSdkErrorDisplay(status); return; } Cons_printf("Ok (VA=%p)\n", BarVa); VaBar0 = BarVa; } /***************************************** * * Transfer the Data * *****************************************/ Cons_printf("\n\n"); Cons_printf(" --- Performing DMA transfers (Press ESC to halt) ---\n"); // Clear DMA data memset(&DmaParams, 0, sizeof(PLX_DMA_PARAMS)); DmaParams.AddrSource = PciBuffer.PhysicalAddr; DmaParams.AddrDest = PciBuffer.PhysicalAddr + (PciBuffer.Size / 2); DmaParams.ByteCount = PciBuffer.Size / 2; // If polling, disable DMA interrupt if (bInterrupts == FALSE) DmaParams.bIgnoreBlockInt = TRUE; LoopCount = 0; // Reset stats Stat_TxTotalCount = 0; Stat_TxTotalBytes = 0; // Get initial start time ftime( &StartTime ); do { // Periodically display statistics if ((LoopCount & 0x0000003F) == 0) { // Get end time ftime( &EndTime ); // Calculate elapsed time in milliseconds ElapsedTime_ms = (((U32)EndTime.time * 1000) + EndTime.millitm) - (((U32)StartTime.time * 1000) + StartTime.millitm); if (ElapsedTime_ms >= (UPDATE_DISPLAY_SEC * 1000)) { // Display statistics if (ElapsedTime_ms != 0) { Cons_printf( " Transfers: %0.0lf Bytes: %0.2lf MB Time: %ldms Rate:%6.3lf MB/s\n", Stat_TxTotalCount, Stat_TxTotalBytes / (1 << 20), ElapsedTime_ms, ((Stat_TxTotalBytes * 1000) / (double)ElapsedTime_ms) / (double)(1 << 20) ); } // Reset stats Stat_TxTotalCount = 0; Stat_TxTotalBytes = 0; // Check for user cancel if (Cons_kbhit()) { if (Cons_getch() == 27) goto _ExitDmaTest; } // Get new start time ftime( &StartTime ); } } status = PlxPci_DmaTransferBlock( pDevice, DmaChannel, &DmaParams, 0 // Don't wait for completion ); if (status != ApiSuccess) { Cons_printf("*ERROR* - API failed\n"); PlxSdkErrorDisplay(status); goto _ExitDmaTest; } if (bInterrupts) { status = PlxPci_NotificationWait( pDevice, &NotifyObject, DMA_TIMEOUT_SEC * 1000 ); switch (status) { case ApiSuccess: break; case ApiWaitTimeout: Cons_printf("*ERROR* - Timeout waiting for Int Event\n"); goto _ExitDmaTest; case ApiWaitCanceled: Cons_printf("*ERROR* - Interrupt event cancelled\n"); goto _ExitDmaTest; default: Cons_printf("*ERROR* - API failed\n"); PlxSdkErrorDisplay(status); goto _ExitDmaTest; } } else { PollCount = 1000000; // Poll for DMA completion do { PollCount--; if ((PlxReg(VaBar0, OffsetDmaCmd) & (1 << 30)) == 0) break; } while (PollCount != 0); // Check if DMA is truly complete if (PollCount == 0) { Cons_printf("*ERROR* - Timeout waiting for DMA to complete\n"); goto _ExitDmaTest; } } // Update statistics Stat_TxTotalCount++; Stat_TxTotalBytes += PciBuffer.Size / 2; LoopCount++; } while (1); _ExitDmaTest: Cons_printf("\n ------------------\n"); // Release the interrupt wait object if (bInterrupts) { Cons_printf(" Cancelling Int Notification.... "); status = PlxPci_NotificationCancel( pDevice, &NotifyObject ); if (status != ApiSuccess) { Cons_printf("*ERROR* - API failed\n"); PlxSdkErrorDisplay(status); } else { Cons_printf("Ok\n"); } } // Close DMA Channel Cons_printf(" Close DMA Channel.............. "); status = PlxPci_DmaChannelClose( pDevice, DmaChannel ); if (status == ApiSuccess) { Cons_printf("Ok\n"); } else { Cons_printf("*ERROR* - API failed\n"); PlxSdkErrorDisplay(status); } // Release DMA buffer PlxPci_PhysicalMemoryFree( pDevice, &PciBuffer ); }
/****************************************************************************** * * Function : Do_DMA_Test * * Description: The main entry point * *****************************************************************************/ int Do_DMA_Test( U32 NTSrcAddr, U32 NTDestAddr, U32 NTSize, PLX_DEVICE_OBJECT *pNTDevice ) { S8 DeviceSelected; PLX_STATUS rc; PLX_DEVICE_KEY DeviceKey; PLX_DEVICE_OBJECT Device; U16 LutIndex = 0xffff; U16 ReqId; U32 flags = 0; /************************************ * Select Device ***********************************/ DeviceSelected = SelectDevice_DMA( &DeviceKey ); if (DeviceSelected == -1) { ConsoleEnd(); exit(0); } rc = PlxPci_DeviceOpen( &DeviceKey, &Device ); if (rc != ApiSuccess) { Cons_printf("\n ERROR: Unable to find or select a PLX device\n"); PlxSdkErrorDisplay(rc); _Pause; ConsoleEnd(); exit(-1); } Cons_printf( "\nSelected: %04x %04x [b:%02x s:%02x f:%x]\n\n", DeviceKey.DeviceId, DeviceKey.VendorId, DeviceKey.bus, DeviceKey.slot, DeviceKey.function ); // Must add the DMA device ReqID to the NT LUT ReqId = ((U16)DeviceKey.bus << 8) | (DeviceKey.slot << 3) | (DeviceKey.function & 0x03); PlxPci_Nt_LutAdd( pNTDevice, &LutIndex, ReqId, flags ); /************************************ * Perform the DMA ************************************/ if (((DeviceKey.PlxChip & 0xF000) == 0x8000) && (DeviceKey.PlxChip != 0x8311)) { PerformDma_8000( &Device, NTSrcAddr, NTDestAddr, NTSize ); } else { Cons_printf( "ERROR: DMA not supported by the selected device (%04X)\n", DeviceKey.PlxChip ); goto _Exit_App; } /************************************ * Close the Device ***********************************/ _Exit_App: PlxPci_DeviceClose( &Device ); _Pause; Cons_printf("\n\n"); return 0; }