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 ); }
/* * Adds a slot (specified by h) to the virtual map and sets up the * BAR. */ static int _plx_add_slot_to_map(PLX_DEVICE_OBJECT *device) { PLX_STATUS status; V_MAP.n++; if (!V_MAP.addr) { ASSERT(V_MAP.n == 1); ASSERT(!V_MAP.device); V_MAP.addr = (PLX_UINT_PTR *)malloc(sizeof(PLX_UINT_PTR)); if (!V_MAP.addr) { _plx_log_DEBUG("Unable to allocate %zu bytes for V_MAP.addr array\n", sizeof(PLX_UINT_PTR)); return PLX_MEM; } V_MAP.device = (PLX_DEVICE_OBJECT *)malloc(sizeof(PLX_DEVICE_OBJECT)); if (!V_MAP.device) { _plx_log_DEBUG("Unable to allocate %zu bytes for V_MAP.device array\n", sizeof(PLX_DEVICE_OBJECT)); return PLX_MEM; } V_MAP.events = (PLX_NOTIFY_OBJECT *)malloc(sizeof(PLX_NOTIFY_OBJECT)); if (!V_MAP.events) { _plx_log_DEBUG("Unable to allocate %zu bytes for V_MAP.events array\n", sizeof(PLX_NOTIFY_OBJECT)); return PLX_MEM; } V_MAP.intrs = (PLX_INTERRUPT *)malloc(sizeof(PLX_INTERRUPT)); if (!V_MAP.intrs) { _plx_log_DEBUG("Unable to allocate %zu bytes for V_MAP.intrs array\n", sizeof(PLX_INTERRUPT)); return PLX_MEM; } V_MAP.registered = (boolean_t *)malloc(sizeof(boolean_t)); if (!V_MAP.registered) { _plx_log_DEBUG("Unable to allocate %zu bytes for V_MAP.registered array\n", sizeof(boolean_t)); return PLX_MEM; } } else { status = _plx_resize_map(); if (status != PLX_SUCCESS) { _plx_log_DEBUG("Error resizing V_MAP data.\n"); return status; } } memcpy(&(V_MAP.device[V_MAP.n - 1]), device, sizeof(*device)); status = PlxPci_PciBarMap(&(V_MAP.device[V_MAP.n - 1]), PLX_PCI_SPACE_0, (VOID **)&(V_MAP.addr[V_MAP.n - 1])); if (status != ApiSuccess) { /* Undo memory allocation, etc. here */ _plx_log_DEBUG("Error getting BAR for handle %p\n", &device); _plx_print_more(status); return status; } V_MAP.registered[V_MAP.n - 1] = FALSE_; return PLX_SUCCESS; }