📄 pcan_fifo.c
字号:
//****************************************************************************// Copyright (C) 2001,2002,2003 PEAK System-Technik GmbH//// linux@peak-system.com// www.peak-system.com//// This program is free software; you can redistribute it and/or modify// it under the terms of the GNU General Public License as published by// the Free Software Foundation; either version 2 of the License, or// (at your option) any later version.//// This program is distributed in the hope that it will be useful,// but WITHOUT ANY WARRANTY; without even the implied warranty of// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the// GNU General Public License for more details.//// You should have received a copy of the GNU General Public License// along with this program; if not, write to the Free Software// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.//// Maintainer(s): Klaus Hitschler (klaus.hitschler@gmx.de)//****************************************************************************//****************************************************************************//// pcan_fifo.c - manages the ringbuffers for read and write data//// $Log: pcan_fifo.c,v $// Revision 1.12 2003/03/02 10:58:07 klaus// merged USB thread into main path//// Revision 1.11 2003/03/02 10:58:07 klaus// merged USB thread into main path//// Revision 1.10.2.7 2003/02/09 13:18:09 klaus// modifications to support linux 2.2.19 kernels//// Revision 1.10.2.6 2003/02/09 13:18:09 klaus// modifications to support linux 2.2.19 kernels//// Revision 1.10.2.5 2003/01/29 20:34:20 klaus// release_20030129_a and release_20030129_u released//// Revision 1.10.2.4 2003/01/29 20:34:20 klaus// release_20030129_a and release_20030129_u released//// Revision 1.10.2.3 2003/01/28 23:28:26 klaus// reorderd pcan_usb.c and pcan_usb_kernel.c, tidied up//// Revision 1.10.2.2 2003/01/08 22:21:48 klaus// fixed version 1.3 problem, write has still a deadlock////****************************************************************************//****************************************************************************// INCLUDES#include <src/pcan_common.h> #include <linux/types.h>#include <linux/errno.h> // error codes#ifdef LINUX_22#include <asm/system.h> // cli(), save_flags(), restore_flags()#endif#include <linux/spinlock.h> // <asm/spinlock.h>, where are the diffs?#include <src/pcan_fifo.h> //****************************************************************************// DEFINES//****************************************************************************// GLOBALS//****************************************************************************// LOCALS//****************************************************************************// CODE int pcan_fifo_reset(register FIFO_MANAGER *anchor){ spin_lock_irqsave(&anchor->lock, anchor->flags); anchor->dwTotal = 0; anchor->nStored = 0; anchor->r = anchor->w = anchor->bufferBegin; // nothing to read anchor->bPutClaimed = 0; anchor->bGetClaimed = 0; spin_unlock_irqrestore(&anchor->lock, anchor->flags); // DPRINTK(KERN_DEBUG "%s: pcan_fifo_reset() %d %p %p %d\n", DEVICE_NAME, anchor->nStored, anchor->r, anchor->w, anchor->bGetClaimed); return 0;}int pcan_fifo_init(register FIFO_MANAGER *anchor, void *bufferBegin, void *bufferEnd, int nCount, u16 wCopySize){ anchor->wCopySize = wCopySize; anchor->wStepSize = (bufferBegin == bufferEnd) ? 0 : ((bufferEnd - bufferBegin) / (nCount - 1)); anchor->nCount = nCount; anchor->bufferBegin = bufferBegin; anchor->bufferEnd = bufferEnd; anchor->flags = 0; // check for fatal program errors if ((anchor->wStepSize < anchor->wCopySize) || (anchor->bufferBegin > anchor->bufferEnd) || (nCount <= 1)) return -EINVAL; spin_lock_init(&anchor->lock); return pcan_fifo_reset(anchor);}//----------------------------------------------------------------------------// the functiony claim and ..put or ..get are always a timingly narrow related// pair. Never there should be a .._claim_.. without a .._put or .._get! int pcan_fifo_claim_for_put(register FIFO_MANAGER *anchor, void **pvPutData){ int err = 0; if (anchor->bPutClaimed) err = EAGAIN; else { spin_lock_irqsave(&anchor->lock, anchor->flags); if (anchor->nStored < anchor->nCount) { anchor->bPutClaimed = 1; *pvPutData = anchor->w; } else { spin_unlock_irqrestore(&anchor->lock, anchor->flags); *pvPutData = NULL; err = -ENOSPC; } } return err;}int pcan_fifo_put(register FIFO_MANAGER *anchor){ // DPRINTK(KERN_DEBUG "%s: pcan_fifo_put() %d %p %p %d\n", DEVICE_NAME, anchor->nStored, anchor->r, anchor->w, anchor->bPutClaimed); if (!anchor->bPutClaimed) return -EDEADLOCK; anchor->nStored++; anchor->dwTotal++; if (anchor->w < anchor->bufferEnd) anchor->w += anchor->wStepSize; // increment to next else anchor->w = anchor->bufferBegin; // start from begin anchor->bPutClaimed = 0; spin_unlock_irqrestore(&anchor->lock, anchor->flags); return 0;}int pcan_fifo_put_reject(register FIFO_MANAGER *anchor){ // DPRINTK(KERN_DEBUG "%s: pcan_fifo_put_reject() %d %p %p %d\n", DEVICE_NAME, anchor->nStored, anchor->r, anchor->w, anchor->bPutClaimed); if (!anchor->bPutClaimed) return -EDEADLOCK; anchor->bPutClaimed = 0; spin_unlock_irqrestore(&anchor->lock, anchor->flags); return 0;}//----------------------------------------------------------------------------// the functiony claim and ..put or ..get are always a timingly narrow related// pair. There should never be a .._claim_.. without a .._put or .._get! int pcan_fifo_claim_for_get(register FIFO_MANAGER *anchor, void **pvGetData){ int err = 0; if (anchor->bGetClaimed) err = EAGAIN; else { spin_lock_irqsave(&anchor->lock, anchor->flags); if (anchor->nStored > 0) { anchor->bGetClaimed = 1; *pvGetData = anchor->r; } else { spin_unlock_irqrestore(&anchor->lock, anchor->flags); *pvGetData = NULL; err = -ENODATA; } } return err;}int pcan_fifo_get(register FIFO_MANAGER *anchor){ // DPRINTK(KERN_DEBUG "%s: pcan_fifo_get() %d %p %p %d\n", DEVICE_NAME, anchor->nStored, anchor->r, anchor->w, anchor->bGetClaimed); if (!anchor->bGetClaimed) return -EDEADLOCK; anchor->nStored--; if (anchor->r < anchor->bufferEnd) anchor->r += anchor->wStepSize; // increment to next else anchor->r = anchor->bufferBegin; // start from begin anchor->bGetClaimed = 0; spin_unlock_irqrestore(&anchor->lock, anchor->flags); return 0;}int pcan_fifo_get_reject(register FIFO_MANAGER *anchor){ // DPRINTK(KERN_DEBUG "%s: pcan_fifo_get_reject() %d %p %p %d\n", DEVICE_NAME, anchor->nStored, anchor->r, anchor->w, anchor->bGetClaimed); if (!anchor->bGetClaimed) return -EDEADLOCK; anchor->bGetClaimed = 0; spin_unlock_irqrestore(&anchor->lock, anchor->flags); return 0;}//----------------------------------------------------------------------------// returns the current count of elements in fifoint pcan_fifo_status(FIFO_MANAGER *anchor){ return anchor->nStored;}//----------------------------------------------------------------------------// returns 0 if the fifo is fullint pcan_fifo_near_full(FIFO_MANAGER *anchor){ return (anchor->nStored < (anchor->nCount - 1));} //----------------------------------------------------------------------------// returns 0 if the fifo is emptyint pcan_fifo_empty(FIFO_MANAGER *anchor){ return anchor->nStored;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -