📄 xp_osi_queue.c
字号:
} pChannel->wLockInuse--; } else if(ppBAddr == pChannel->pLockData[wIndex].ppBAddr) { pChannel->pLockData[wIndex].ppBAddr = ppEAddr; } else { pChannel->pLockData[wIndex].ppEAddr = ppBAddr; } /*------------------------------------------------------------------------+ | If the record being unlocked matches the current read pointer in | hardware, then we have to move the read pointer +------------------------------------------------------------------------*/ if(pChannel->ppLockAddr == ppBAddr) { /*--------------------------------------------------------------------+ | If there are no more lock records, then use the most recent | region processed +--------------------------------------------------------------------*/ if(pChannel->wLockInuse == 0) { update_read_pointer(pGlobal,wChannelId, pChannel->ppProcessAddr); } /*--------------------------------------------------------------------+ | If there is another entry in the list, then use address of the | next entry, otherwise use the address in the beginning of the list +--------------------------------------------------------------------*/ else { if(wIndex < pChannel->wLockInuse) { pChannel->ppLockAddr = pChannel->pLockData[wIndex].ppBAddr; } else { pChannel->ppLockAddr = pChannel->pLockData[0].ppBAddr; } update_read_pointer(pGlobal,wChannelId, pChannel->ppLockAddr); } } /*------------------------------------------------------------------------+ | if we're in an RPI condition, then try to find a new region to get | going again +------------------------------------------------------------------------*/ else if(pChannel->wRpiStatus) { process_read_pointer(pGlobal,wChannelId); } return(0);}/*----------------------------------------------------------------------------+| queue_valid+----------------------------------------------------------------------------*/static short queue_valid(GLOBAL_RESOURCES *pGlobal, SHORT wChannelId){ if(pGlobal->QueueInfo.XpQueueChData[wChannelId].State == XP_QUEUE_STATUS_UNDEFINED) { return(XP_ERROR_QUEUE_UNDEFINED); } return(0);}/*----------------------------------------------------------------------------+| XXXXXXX XXX XXX XXXXXX XXXXXXX XXXXXX XX XX XX XXXX| XX X XX XX X XX X XX X XX XX XXX XX XXXX XX| XX X XXX XX XX X XX XX XXXX XX XX XX XX| XXXX X XX XXXX XXXXX XX XXXX XX XX XX| XX X XXX XX XX X XX XX XX XXX XXXXXX XX| XX X XX XX XX XX X XX XX XX XX XX XX XX XX| XXXXXXX XXX XXX XXXX XXXXXXX XXX XX XX XX XX XX XXXXXXX+----------------------------------------------------------------------------*/void xp_osi_queue_de_init(GLOBAL_RESOURCES *pGlobal){ if(pGlobal->gpPMRoot != NULL) { __pm_alloc_physical_deinit(pGlobal->gpPMRoot); os_free_physical(pGlobal->hRoot); pGlobal->gpPMRoot = NULL; pGlobal->hRoot = NULL; }}/*----------------------------------------------------------------------------+| xp0_queue_init+----------------------------------------------------------------------------*/SHORT xp_osi_queue_init(GLOBAL_RESOURCES *pGlobal){ short i; short rc=0; ULONG ulAddr; UINT32 flag; MEM_HANDLE_T hRoot; UINT uPhyAddr; void *pLogicalAddr; /*------------------------------------------------------------------------+ | Free any space from a previous initialization +------------------------------------------------------------------------*/ if(pGlobal->QueueInfo.uXpQueueInited) { for(i=0; i<XP_CHANNEL_COUNT; i++) { if(pGlobal->QueueInfo.XpQueueChData[i].pLockData) { FREE(pGlobal->QueueInfo.XpQueueChData[i].pLockData); } } } pGlobal->QueueInfo.uXpQueueInited = 1; /*------------------------------------------------------------------------+ | Setup the channels +------------------------------------------------------------------------*/ for(i=0; i<XP_CHANNEL_COUNT; i++) { pGlobal->QueueInfo.XpQueueChData[i].State = XP_QUEUE_STATUS_UNDEFINED; pGlobal->QueueInfo.XpQueueChData[i].ulQueueAddr = 0; pGlobal->QueueInfo.XpQueueChData[i].ulQueueSize = 0; pGlobal->QueueInfo.XpQueueChData[i].wLockAlloc = 0; pGlobal->QueueInfo.XpQueueChData[i].wLockInuse = 0; pGlobal->QueueInfo.XpQueueChData[i].pLockData = NULL; pGlobal->QueueInfo.XpQueueChData[i].hMem = NULL; xp_osi_queue_reset_errors(pGlobal,i); } /*------------------------------------------------------------------------+ | If the address is to be used, then make sure the address is | properly aligned +------------------------------------------------------------------------*///lingh added in 5/29/2002 __os_alloc_physical_heap_walk(); hRoot = os_alloc_physical_justify(pGlobal->uReservedBufSize, 0x400000); __os_alloc_physical_heap_walk(); if(hRoot == NULL ) { return -1; } pGlobal->hRoot = hRoot; uPhyAddr = os_get_physical_address(hRoot); pLogicalAddr = os_get_logical_address(hRoot); ulAddr = uPhyAddr; pGlobal->gpPMRoot = __pm_alloc_physical_init(uPhyAddr, pLogicalAddr, pGlobal->uReservedBufSize,256); __os_alloc_physical_heap_walk(); if(pGlobal->gpPMRoot == NULL) { os_free_physical(hRoot); return -1; } /*------------------------------------------------------------------------+ | We have an aligned address, so save the address onto the freelist, | and setup the hardware base address +------------------------------------------------------------------------*/ pGlobal->QueueInfo.ulXpQueueBAddr = ulAddr & 0xff000000; flag = os_enter_critical_section(); xp_atom_dcr_write(pGlobal->uDeviceIndex,XP_DCR_ADDR_QBASE, pGlobal->QueueInfo.ulXpQueueBAddr); os_leave_critical_section(flag); pGlobal->QueueInfo.ulXpQueueBAddr |= REGION_PLB_BYTE_OFFSET; return(rc);}/*----------------------------------------------------------------------------+| xp0_queue_get_status+----------------------------------------------------------------------------*/SHORT xp_osi_queue_get_status(GLOBAL_RESOURCES *pGlobal, SHORT wChannelId, XP_QUEUE_STATUS *pStatus){ short rc;// xp_os_semaphore_wait(); rc = xp_osi_channel_valid(pGlobal,wChannelId); if(rc == 0) { *pStatus = pGlobal->QueueInfo.XpQueueChData[wChannelId].State; }// xp_os_semaphore_signal(); return(rc);}/*----------------------------------------------------------------------------+| xp0_queue_process_data+-----------------------------------------------------------------------------+|| DESCRIPTION: define a queue for data unloaded on this channel|| PROTOTYPE : short xp0_queue_process_data(| short wChannel_Id,| CHANNEL_UNLOAD_TYPE unload_type,| XP_CHANNEL_NOTIFY_FN notify_fn)|| ARGUMENTS : wChannel_Id - the channel id as returned from the| xp0_channel_allocate().| unload_type - type of data being unloaded|| RETURNS :|| COMMENTS : This function determines the amount of data to process.| The starting address of the data to process is the| address where we last read (read_addr). The ending| address is acquired from hardware.| If the unload type is for tables, then the tables are| determined and the application is notified for each| completed table.|+----------------------------------------------------------------------------*/void xp_osi_queue_process_data(GLOBAL_RESOURCES *pGlobal, SHORT wChannelId, XP_CHANNEL_UNLOAD_TYPE UnloadType, XP_CHANNEL_NOTIFY_FN notify_fn){ short rc; SHORT wSectionFilter; /* 1=filtering enabled, 0=no filtering */ ULONG ulWriteStart; /* hardware write pointer */ UCHAR *ppBQueue=NULL; /* starting address of the queue */ UCHAR *ppEQueue=NULL; /* ending address of the queue */ UCHAR *ppBAddr=NULL; /* start address of the data */ UCHAR *ppEAddr=NULL; /* end address of the data */ UCHAR *plBQueue=NULL; /* starting address of the queue */ UCHAR *plEQueue=NULL; /* ending address of the queue */ UCHAR *plBAddr=NULL; /* start address of the data */ UCHAR *plEAddr=NULL; /* end address of the data */ ULONG ulLength; /* ending address of the data */ XP_CHANNEL_NOTIFY_DATA Info; /* notification data */ QUEUE_PTR pChannel; UINT32 flag; pChannel = &pGlobal->QueueInfo.XpQueueChData[wChannelId];// xp_os_semaphore_wait(); /*------------------------------------------------------------------------+ | Make sure the channel is still allocated +------------------------------------------------------------------------*/ rc = xp_osi_channel_valid(pGlobal,wChannelId); if(rc == 0) { flag = os_enter_critical_section(); rc = xp_atom_dcr_read_register_channel(pGlobal->uDeviceIndex,XP_QSTATD_REG_WSTART, wChannelId, &ulWriteStart); os_leave_critical_section(flag); } if(rc == 0) { /*--------------------------------------------------------------------+ | Get the queue range, and the address range of the data +--------------------------------------------------------------------*/ ppBAddr = pChannel->ppReadAddr; ppEAddr = MAKE_PLB_ADDR(ulWriteStart); ppBQueue = MAKE_PLB_ADDR(pChannel->ulQueueAddr); ppEQueue = ppBQueue + pChannel->ulQueueSize; PDEBUG("ppBAddr = %8.8x\n",ppBAddr); PDEBUG("ppEAddr = %8.8x\n",ppEAddr); PDEBUG("ppBQueue = %8.8x\n",ppBQueue); PDEBUG("ppEQueue = %8.8x \n",ppEQueue); /*--------------------------------------------------------------------+ | make sure the address range is within the bounds of the queue +--------------------------------------------------------------------*/ if((ppBAddr < ppBQueue) || (ppEAddr > ppEQueue)) { PDEBUG("XP_ERROR_QUEUE_ADDRESS1\n"); pChannel->Errors.uwQueueAddress++; rc = XP_ERROR_QUEUE_ADDRESS; } /*--------------------------------------------------------------------+ | Abort if there is no data +--------------------------------------------------------------------*/ else if(ppBAddr == ppEAddr) { PDEBUG("XP_ERROR_QUEUE_ADDRESS2\n"); pChannel->Errors.uwNoData++; rc = XP_ERROR_QUEUE_ADDRESS; } } if(rc == 0) { /*--------------------------------------------------------------------+ | Check if queue is not active, then we'll skip the new record | which must have arrived in the hardware when we changed the state | to DISABLED. +--------------------------------------------------------------------*/ if(pChannel->State != XP_QUEUE_STATUS_ENABLED) { PDEBUG("pChannel->Errors.uwQueueDisabled\n"); pChannel->Errors.uwQueueDisabled++; } else { /*----------------------------------------------------------------+ | Calculate the number of bytes, and adjust the read pointer. | We must also check if a queue wrap occurred. +----------------------------------------------------------------*/ PDEBUG("ppBAddr = %8.8x\n",ppBAddr); PDEBUG("ppEAddr = %8.8x\n",ppEAddr); PDEBUG("ppBQueue = %8.8x\n",ppBQueue); PDEBUG("ppEQueue = %8.8x \n",ppEQueue); if(ppBAddr <= ppEAddr) { PDEBUG("ppBAddr <= ppEAddr\n"); ulLength = ppEAddr - ppBAddr; } else { PDEBUG("2\n"); ulLength = (ppEQueue - ppBAddr) + (ppEAddr - ppBQueue); } PDEBUG("uulLength = %8.8x\n",ulLength); /*----------------------------------------------------------------+ | If the application has requested notification, then process | the data, otherwise the hardware will continue to advance the | writeStart until a read pointer error occurs or the application | sets the notify function. +----------------------------------------------------------------*/ if(notify_fn) { /*------------------------------------------------------------+ | For table unloading, process each table section | The sectionFilter = 0 if the unload type does NOT require | filtering, 1=filtering tables +------------------------------------------------------------*/ if(UnloadType >= XP_CHANNEL_UNLOAD_PSI) { wSectionFilter = (UnloadType % 2); plBQueue = (UCHAR*)os_get_logical_address(pChannel->hMem); plEQueue = plBQueue + pChannel->ulQueueSize; plBAddr = plBQueue+(ULONG)ppBAddr - (ULONG)pChannel->ulQueueAddr; plEAddr = plBQueue+(ULONG)ppEAddr - (ULONG)pChannel->ulQueueAddr; xp_osi_filter_process_table_data(pGlobal,wChannelId, plBAddr, plEAddr, plBQueue, plEQueue, wSectionFilter, notify_fn); } /*------------------------------------------------------------+ | Keep track of the record locked call the application to | notify of data available +------------------------------------------------------------*/ else { Info.pGlobal = pGlobal; Info.wChannelId = wChannelId; Info.ulMatchWord = 0; Info.plData = (UCHAR*)((ULONG)os_get_logical_address(pChannel->hMem) +(ULONG)ppBAddr - (ULONG)pChannel->ulQueueAddr); Info.ulLength = ulLength; xp_osi_queue_lock_data(pGlobal,wChannelId, XP_QUEUE_MODE_LOCK, ppBAddr, ppEAddr); (notify_fn)(&Info); } /*------------------------------------------------------------+ | Update the read pointer after processing the data +------------------------------------------------------------*/ pGlobal->QueueInfo.XpQueueChData[wChannelId].ppReadAddr = ppEAddr; } } }// xp_os_semaphore_signal();}/*----------------------------------------------------------------------------+| xp0_queue_process_interrupt+----------------------------------------------------------------------------*/short xp_osi_queue_process_interrupt(GLOBAL_RESOURCES *pGlobal, SHORT wChannelId, ULONG ulInterrupt){ short rc; QUEUE_PTR pChannel; pChannel = &pGlobal->QueueInfo.XpQueueChData[wChannelId];// xp_os_semaphore_wait(); /*------------------------------------------------------------------------+
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -