📄 xp_osi_queue.c
字号:
| Make sure the channel is still allocated +------------------------------------------------------------------------*/ rc = xp_osi_channel_valid(pGlobal,wChannelId); if(rc == 0) { /*--------------------------------------------------------------------+ | Try to recover from a read pointer error +--------------------------------------------------------------------*/ if(ulInterrupt & XP_INTERRUPT_QSTAT_RPI) { pChannel->Errors.uwReadPointer++; pChannel->wRpiStatus = 1; process_read_pointer(pGlobal,wChannelId); } if(ulInterrupt & XP_INTERRUPT_QSTAT_CRCE) { pChannel->Errors.uwCrc32++; } if(ulInterrupt & XP_INTERRUPT_QSTAT_TSLE) { pChannel->Errors.uwSectionLength++; } if(ulInterrupt & XP_INTERRUPT_QSTAT_PSE) { pChannel->Errors.uwCc++; } }// xp_os_semaphore_signal(); return(rc);}/*----------------------------------------------------------------------------+| XX XXXXXX XXXXXX XXXXX| XXXX XX XX XX XX XX| XX XX XX XX XX XX| XX XX XXXXX XX XX| XXXXXX XX XX XX| XX XX XX XX XX XX| XX XX XX XXXXXX XXXXX+----------------------------------------------------------------------------*//*----------------------------------------------------------------------------+| xp0_queue_allocate+-----------------------------------------------------------------------------+|| DESCRIPTION: define a queue for data delivered on this channel|| PROTOTYPE : short xp0_queue_allocate(| short wChannel_Id,| unsigned long queue_size|| ARGUMENTS : wChannel_Id - the channel id as returned from the| xp0_channel_allocate().| queue_size - minimum size of queue in bytes|| RETURNS : 0 if successful, or non-zero if an error occurs|| ERRORS : XP_ERROR_CHANNEL_INVALID - channel id is not defined| XP_ERROR_OUT_OF_SPACE - space is not available for a| a queue of the requested size|| COMMENTS : defines a queue for use by the channel specified.|+----------------------------------------------------------------------------*/SHORT xp_osi_queue_allocate(GLOBAL_RESOURCES *pGlobal, SHORT wChannelId, ULONG ulQueueSize){ short rc; UCHAR *ppAddr; unsigned long u; ULONG ulQueueTop; ULONG ulQueueBottom; QUEUE_PTR pChannel; UINT32 flag; pChannel = &pGlobal->QueueInfo.XpQueueChData[wChannelId];// xp_os_semaphore_wait(); rc = xp_osi_channel_valid(pGlobal,wChannelId); if(rc == 0) { if(queue_valid(pGlobal,wChannelId) == 0) { rc = XP_ERROR_QUEUE_DEFINED; } } if(rc == 0) { u = ulQueueSize % QUEUE_BLOCK_SIZE; if(u) { ulQueueSize += (QUEUE_BLOCK_SIZE - u); } if(pChannel->wLockAlloc > 0) { FREE(pChannel->pLockData); }//lingh pChannel->hMem = pm_alloc_physical(pGlobal->gpPMRoot,ulQueueSize); if(pChannel->hMem == NULL) return -1; PDEBUG("pm_alloc_physical, phy = %x, logical = %x\n",os_get_physical_address(pChannel->hMem),os_get_logical_address(pChannel->hMem)); ppAddr = MAKE_PLB_ADDR(os_get_physical_address(pChannel->hMem)); pChannel->ulQueueAddr = os_get_physical_address(pChannel->hMem); pChannel->ulQueueSize = ulQueueSize; pChannel->wLockInuse = 0; pChannel->wLockAlloc = 0; pChannel->pLockData = NULL; pChannel->ppLockAddr = NULL; pChannel->ppProcessAddr = ppAddr; xp_osi_queue_reset_errors(pGlobal,wChannelId); /*--------------------------------------------------------------------+ | Write the new queue definition, and initialize the queue state | to disabled +--------------------------------------------------------------------*/ ulQueueBottom = pChannel->ulQueueAddr / QUEUE_BLOCK_SIZE; ulQueueTop = (pChannel->ulQueueAddr + pChannel->ulQueueSize) / QUEUE_BLOCK_SIZE; flag = os_enter_critical_section(); xp_atom_dcr_init_queue(pGlobal->uDeviceIndex,wChannelId, ulQueueTop, ulQueueBottom); os_leave_critical_section(flag); pChannel->State = XP_QUEUE_STATUS_DISABLED; /*--------------------------------------------------------------------+ | Reset the queue. This will cause the hardware to set the | read_address = queue_bottom +--------------------------------------------------------------------*/ rc = xp_osi_queue_control(pGlobal,wChannelId, XP_QUEUE_CONTROL_RESET); }// xp_os_semaphore_signal(); return(rc);}/*----------------------------------------------------------------------------+| xp0_queue_control+-----------------------------------------------------------------------------+|| DESCRIPTION: controls the state of the queue|| PROTOTYPE : short xp0_queue_control(| short wChannel_Id,| XP_QUEUE_CONTROL_TYPE cmd)|| ARGUMENTS : wChannel_Id - the channel id as returned from the| xp0_channel_allocate().| cmd - XP_QUEUE_CONTROL_ENABLE - enable queue| XP_QUEUE_CONTROL_DISABLE - disable queue| XP_QUEUE_CONTROL_RESET - reset the queue|| RETURNS : 0 if successful, or non-zero if an error occurs|| ERRORS : XP_ERROR_CHANNEL_INVALID - channel id is not defined| XP_ERROR_INTERNAL - internal driver error|| COMMENTS : controls the current queue state. XP_QUEUE_CONTROL_DISABLE| prevents the delivery of new data. Existing data in the| queue is undisturbed. XP_QUEUE_CONTROL_ENABLE restarts a| disabled queue. XP_QUEUE_CONTROL_RESET disables the queue,| resets the read/write pointers, and unlocks all locked| sections for the channel.|+----------------------------------------------------------------------------*/SHORT xp_osi_queue_control(GLOBAL_RESOURCES *pGlobal, SHORT wChannelId, XP_QUEUE_CONTROL_TYPE Cmd){ short rc; ULONG ulData; QUEUE_PTR pChannel; UINT32 flag; pChannel = &pGlobal->QueueInfo.XpQueueChData[wChannelId];// xp_os_semaphore_wait(); rc = xp_osi_channel_valid(pGlobal,wChannelId); if(rc == 0) { rc = queue_valid(pGlobal,wChannelId); } if(rc == 0) { switch(Cmd) { case XP_QUEUE_CONTROL_ENABLE: flag = os_enter_critical_section(); xp_atom_dcr_write_register_channel(pGlobal->uDeviceIndex,XP_QCONFIGB_REG_ENBL, wChannelId, 1); os_leave_critical_section(flag); pGlobal->QueueInfo.XpQueueChData[wChannelId].State = XP_QUEUE_STATUS_ENABLED; rc = xp_osi_channel_restart(pGlobal,wChannelId); break; /*----------------------------------------------------------------+ | Write the "stops" register to stop any "in-process" packets | from being delivered. Clear any pending filter operations | Clear the interrupts to get rid of any latent interrupts +----------------------------------------------------------------*/ case XP_QUEUE_CONTROL_DISABLE: ulData = (1 << (31 - wChannelId)); flag = os_enter_critical_section(); xp_atom_dcr_write(pGlobal->uDeviceIndex,XP_DCR_ADDR_QSTOPS, ulData); os_leave_critical_section(flag); xp_osi_filter_process_pending(pGlobal,wChannelId); rc = xp_osi_interrupt_channel_control(pGlobal,wChannelId, XP_INTERRUPT_CONTROL_RESET); flag = os_enter_critical_section(); xp_atom_dcr_write_register_channel(pGlobal->uDeviceIndex,XP_QCONFIGB_REG_ENBL, wChannelId, 0); os_leave_critical_section(flag); pChannel->State = XP_QUEUE_STATUS_DISABLED; break; /*----------------------------------------------------------------+ | Reset the queue, and set the read_addr to the queue bottom. | Remove all the skip and lock records +----------------------------------------------------------------*/ case XP_QUEUE_CONTROL_RESET: if(pChannel->State != XP_QUEUE_STATUS_DISABLED) { rc = xp_osi_queue_control(pGlobal,wChannelId, XP_QUEUE_CONTROL_DISABLE); } ulData = (1 << (31 - wChannelId)); flag = os_enter_critical_section(); xp_atom_dcr_write(pGlobal->uDeviceIndex,XP_DCR_ADDR_QRESETS, ulData); os_leave_critical_section(flag); pChannel->ppReadAddr = MAKE_PLB_ADDR(pChannel->ulQueueAddr); pChannel->ppProcessAddr = MAKE_PLB_ADDR(pChannel->ulQueueAddr); pChannel->wLockInuse = 0; pChannel->ppLockAddr = NULL; break; default: break; } }// xp_os_semaphore_signal(); PDEBUG("xp_osi_channel_restart return\n"); return(rc);}/*----------------------------------------------------------------------------+| xp0_queue_free+-----------------------------------------------------------------------------+|| DESCRIPTION: define a queue for data unloaded on this channel|| PROTOTYPE : short xp0_queue_free(| short wChannel_Id)|| ARGUMENTS : wChannel_Id - the channel id as returned from the| xp0_channel_allocate().|| RETURNS : 0 if successful, or non-zero if an error occurs|| ERRORS : XP_ERROR_CHANNEL_INVALID - channel id is not defined| XP_ERROR_QUEUE_UNDEFINED - queue is not currently defined|| COMMENTS : frees the queue allocated to the channel. All locked| regions are released.|+----------------------------------------------------------------------------*/SHORT xp_osi_queue_free(GLOBAL_RESOURCES *pGlobal,SHORT wChannelId){ short rc; QUEUE_PTR pChannel; pChannel = &pGlobal->QueueInfo.XpQueueChData[wChannelId];// xp_os_semaphore_wait(); /*------------------------------------------------------------------------+ | Check that the wChannel_Id is valid and the queue is currently defined. | Then disable the queue +------------------------------------------------------------------------*/ rc = xp_osi_queue_control(pGlobal,wChannelId, XP_QUEUE_CONTROL_DISABLE); if(rc == 0 && pChannel->hMem != NULL) { //lingh pm_free_physical(pGlobal->gpPMRoot,pChannel->hMem); } pChannel->ulQueueAddr = 0; pChannel->ulQueueSize = 0; pChannel->State = XP_QUEUE_STATUS_UNDEFINED; /*--------------------------------------------------------------------+ | Remove all the skip and lock records +--------------------------------------------------------------------*/ pChannel->wLockInuse = 0; pChannel->ppLockAddr = NULL; if(pChannel->wLockAlloc > 0) { FREE(pChannel->pLockData); pChannel->pLockData = NULL; pChannel->wLockAlloc = 0; }// xp_os_semaphore_signal(); return(rc);}/*----------------------------------------------------------------------------+| xp0_queue_get_config+----------------------------------------------------------------------------*/SHORT xp_osi_queue_get_config(GLOBAL_RESOURCES *pGlobal, SHORT wChannelId, UCHAR **pBQueue, UCHAR **pEQueue) /* queue range is exclusive */{ short rc; UCHAR *plBQueue; UCHAR *plEQueue; QUEUE_PTR pChannel; pChannel = &pGlobal->QueueInfo.XpQueueChData[wChannelId];// xp_os_semaphore_wait(); rc = xp_osi_channel_valid(pGlobal,wChannelId); if(rc == 0) { plBQueue = os_get_logical_address(pChannel->hMem); plEQueue = plBQueue + pChannel->ulQueueSize; *pBQueue = plBQueue; *pEQueue = plEQueue; }// xp_os_semaphore_signal(); return(rc);}/*----------------------------------------------------------------------------+| xp0_queue_get_errors+----------------------------------------------------------------------------*/SHORT xp_osi_queue_get_errors(GLOBAL_RESOURCES *pGlobal, SHORT wChannelId, XP_QUEUE_ERROR_PTR pErrors)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -