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"); } }
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 ); }