📄 xp_osi_queue.c
字号:
{ short rc; QUEUE_PTR pChannel; pChannel = &pGlobal->QueueInfo.XpQueueChData[wChannelId]; rc = xp_osi_channel_valid(pGlobal,wChannelId); if(rc) { return(rc); } memcpy(pErrors, &pChannel->Errors, sizeof(XP_QUEUE_ERROR_TYPE)); return(0);}/*----------------------------------------------------------------------------+| xp0_queue_get_size+----------------------------------------------------------------------------*/SHORT xp_osi_queue_get_size(GLOBAL_RESOURCES *pGlobal,SHORT wChannelId, ULONG *pQueueSize){ short rc; QUEUE_PTR pChannel; pChannel = &pGlobal->QueueInfo.XpQueueChData[wChannelId];// xp_os_semaphore_wait(); rc = xp_osi_channel_valid(pGlobal,wChannelId); if(rc == 0) { *pQueueSize = pChannel->ulQueueSize; }// xp_os_semaphore_signal(); return(rc);}/*----------------------------------------------------------------------------+| xp0_queue_lock_data+-----------------------------------------------------------------------------+|| DESCRIPTION: add a skip or lock record to the channel data|| PROTOTYPE : static short xp0_queue_lock_data(| short wChannel_Id,| XP_QUEUE_MODE_TYPE mode,| unsigned char *b_addr,| unsigned char *e_addr)|| ARGUMENTS : wChannel_Id - the channel id as returned from the| xp0_channel_allocate().| mode - LOCK the record or SKIP the record| b_addr - starting address of the region| e_addr - ending address+1 of the region|| RETURNS :|| COMMENTS : This function processes requests to lock or skip records| The SKIP records only update the address of the last| data address processed. LOCK records are added in sorted| order to the lock list. mine whether the end of the| this region is the same as the start of the region to| reserve and the mode is equivalent.|+----------------------------------------------------------------------------*/SHORT xp_osi_queue_lock_data(GLOBAL_RESOURCES *pGlobal,SHORT wChannelId, /* channel to lock region in */XP_QUEUE_MODE_TYPE Mode, /* LOCK or SKIP */UCHAR *ppBAddr, /* start of region to lock */UCHAR *ppEAddr) /* end of region to lock */{ short rc=0; SHORT wIndex; /* location to add new node */ short i, j; SHORT wLockAlloc; QUEUE_LOCK_TYPE *pLockData; QUEUE_PTR pChannel;// xp_os_semaphore_wait(); pChannel = &pGlobal->QueueInfo.XpQueueChData[wChannelId]; /*------------------------------------------------------------------------+ | Save the address of the most recent data processed. This gets used | when the last 'lock' record is unlocked and determines where the | hardware read pointer is moved. +------------------------------------------------------------------------*/ pChannel->ppProcessAddr = ppEAddr; /*------------------------------------------------------------------------+ | If we've used all the available records allocate more space +------------------------------------------------------------------------*/ if(Mode == XP_QUEUE_MODE_LOCK) { if(pChannel->wLockInuse >= pChannel->wLockAlloc) { if (pChannel->wLockAlloc == 0) { wLockAlloc = 128 / sizeof (QUEUE_LOCK_TYPE); pLockData = MALLOC (wLockAlloc * sizeof (QUEUE_LOCK_TYPE)); if(pLockData == NULL) { pChannel->Errors.uwInternal++; rc = XP_ERROR_INTERNAL; } else { pChannel->pLockData = pLockData; pChannel->wLockAlloc = wLockAlloc; } } else { /* we can not realloc it */ pChannel->Errors.uwInternal++; rc = XP_ERROR_INTERNAL; } } if(rc == 0) { if(pChannel->wLockInuse == 0) { pChannel->ppLockAddr = ppBAddr; wIndex = 0; } /*----------------------------------------------------------------+ | Find the location to insert a new node. Since the list is | in sorted order, the node which wraps is always the last one | in the list +----------------------------------------------------------------*/ else { for(wIndex=0; wIndex<pChannel->wLockInuse; wIndex++) { if(ppBAddr < pChannel->pLockData[wIndex].ppBAddr) { break; } } if(wIndex < pChannel->wLockInuse) { /* 05/16/98 */ /*--------------------------------------------------------+ | Shift all the records down to make room for the node | to insert at index location 'i'. +--------------------------------------------------------*/ for(i=pChannel->wLockInuse, j=i-1; i>wIndex; i--, j--) { pChannel->pLockData[i] = pChannel->pLockData[j]; } } } pChannel->pLockData[wIndex].ppBAddr = ppBAddr; pChannel->pLockData[wIndex].ppEAddr = ppEAddr; pChannel->wLockInuse++; } } /*------------------------------------------------------------------------+ | If there are no locked records, then move the read pointer to the | end of the skip +------------------------------------------------------------------------*/ else if(pChannel->wLockInuse == 0) { update_read_pointer(pGlobal,wChannelId, ppEAddr); }// xp_os_semaphore_signal(); return(rc);}/*----------------------------------------------------------------------------+| xp0_queue_reset_errors+----------------------------------------------------------------------------*/SHORT xp_osi_queue_reset_errors(GLOBAL_RESOURCES *pGlobal, SHORT wChannelId){ short rc; QUEUE_PTR pChannel; pChannel = &pGlobal->QueueInfo.XpQueueChData[wChannelId]; rc = xp_osi_channel_valid(pGlobal,wChannelId); if(rc) { return(rc); } memset(&pChannel->Errors, 0, sizeof(XP_QUEUE_ERROR_TYPE)); return(0);}/*----------------------------------------------------------------------------+| xp0_queue_unlock+----------------------------------------------------------------------------*/SHORT xp_osi_queue_unlock(GLOBAL_RESOURCES *pGlobal, SHORT wChannelId, SHORT wBIndex, SHORT wEIndex){ short rc; short i; ULONG ulBytes; QUEUE_PTR pChannel; pChannel = &pGlobal->QueueInfo.XpQueueChData[wChannelId]; for(i=wEIndex; i>=wBIndex; i--) { if(pChannel->pLockData[i].ppBAddr <= pChannel->pLockData[i].ppEAddr) { ulBytes = pChannel->pLockData[i].ppEAddr - pChannel->pLockData[i].ppBAddr; } else { ulBytes = pChannel->ulQueueSize - (pChannel->pLockData[i].ppBAddr - pChannel->pLockData[i].ppEAddr); } if ((rc = xp_osi_queue_unlock_data(pGlobal,wChannelId, pChannel->pLockData[i].ppBAddr, ulBytes)) != 0) { return(rc); } } return(0);}/*----------------------------------------------------------------------------+| xp0_queue_unlock_data+-----------------------------------------------------------------------------+|| DESCRIPTION: define a queue for data unloaded on this channel|| PROTOTYPE : short xp0_queue_unlock_data(| short wChannel_Id,| unsigned char *buffer,| unsigned long length)|| ARGUMENTS : wChannel_Id - the channel id as returned from the| xp0_channel_allocate().| buffer - address of data being unlocked| length - number of bytes to unlock|| RETURNS : 0 if successful, nonzero otherwise.|| COMMENTS : This function notifies the driver when the application| has finished using the space (buffer [ 0..length-1].| The buffer address always observes the data bounaries| provided during the notification phase. Locked sections| may be unlocked in any order.| NOTE: locked regions are not released when a queue| is disabled but are released upon a queue reset. A queue| may be disabled, and re-enabled without disturbing any| locked sections.|+----------------------------------------------------------------------------*/SHORT xp_osi_queue_unlock_data(GLOBAL_RESOURCES *pGlobal, SHORT wChannelId, UCHAR *ppBAddr, ULONG ulLength){ short rc; UCHAR *ppEAddr; ULONG ulAddr; ULONG ulBQueue=0; ULONG ulEQueue=0; QUEUE_PTR pChannel=NULL; /* pointer to channel record */// xp_os_semaphore_wait(); rc = xp_osi_channel_valid(pGlobal,wChannelId); if(rc == 0) { pChannel = &pGlobal->QueueInfo.XpQueueChData[wChannelId]; /*--------------------------------------------------------------------+ | Check if queue is currently active +--------------------------------------------------------------------*/ switch(pChannel->State) { case XP_QUEUE_STATUS_ENABLED: case XP_QUEUE_STATUS_DISABLED: case XP_QUEUE_STATUS_RPI: break; case XP_QUEUE_STATUS_UNDEFINED: rc = XP_ERROR_QUEUE_UNDEFINED; break; default: rc = XP_ERROR_INTERNAL; break; } } /*------------------------------------------------------------------------+ | if we don't have any locked record, then we cannot unlock any records +------------------------------------------------------------------------*/ if(rc == 0) { if(pChannel->wLockInuse == 0) { rc = XP_ERROR_QUEUE_ADDRESS; } else if(ulLength == 0) { rc = XP_ERROR_QUEUE_REGION_SIZE; } } /*------------------------------------------------------------------------+ | Determine the start and end address of the space being freed +------------------------------------------------------------------------*/ if(rc == 0) { ulAddr = (ULONG)ppBAddr; //lingh ulBQueue = pChannel->ulQueueAddr; ulEQueue = ulBQueue + pChannel->ulQueueSize; if(ulAddr < ulBQueue) { pChannel->Errors.uwQueueAddress++; rc = XP_ERROR_QUEUE_ADDRESS; } } if(rc == 0) { if(ulLength > pChannel->ulQueueSize) { pChannel->Errors.uwQueueAddress++; rc = XP_ERROR_QUEUE_ADDRESS; } } /*------------------------------------------------------------------------+ | Adjust address to end of space to unlock. Watch for the queue wrap. +------------------------------------------------------------------------*/ if(rc == 0) { ulAddr += ulLength; if(ulAddr >= ulEQueue) { ulAddr = (unsigned long) ulBQueue + (ulAddr - ulEQueue); } ppEAddr = MAKE_PLB_ADDR(ulAddr); rc = unlock_data(pGlobal,wChannelId, ppBAddr, ppEAddr); }// xp_os_semaphore_signal(); return(rc);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -