diff options
| author | Oliver Endriss <devnull@localhost> | 2003-02-18 13:18:02 +0000 |
|---|---|---|
| committer | Oliver Endriss <devnull@localhost> | 2003-02-18 13:18:02 +0000 |
| commit | 5a12e644ad2ddfb5732cec455600de7f0a108305 (patch) | |
| tree | 7d4a2e9bde73500e3c21d2174829085a0c5c7a49 /linux/drivers/media/dvb/dvb-core | |
| parent | 218b5ed2dd2770dff18c55b0c813ade613293a1d (diff) | |
| download | mediapointer-dvb-s2-5a12e644ad2ddfb5732cec455600de7f0a108305.tar.gz mediapointer-dvb-s2-5a12e644ad2ddfb5732cec455600de7f0a108305.tar.bz2 | |
ring buffer cleanup
Diffstat (limited to 'linux/drivers/media/dvb/dvb-core')
| -rw-r--r-- | linux/drivers/media/dvb/dvb-core/Makefile | 4 | ||||
| -rw-r--r-- | linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.c | 176 | ||||
| -rw-r--r-- | linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.h | 127 |
3 files changed, 305 insertions, 2 deletions
diff --git a/linux/drivers/media/dvb/dvb-core/Makefile b/linux/drivers/media/dvb/dvb-core/Makefile index aac79617c..ec55e17d5 100644 --- a/linux/drivers/media/dvb/dvb-core/Makefile +++ b/linux/drivers/media/dvb/dvb-core/Makefile @@ -2,9 +2,9 @@ # Makefile for the kernel DVB device drivers. # -export-objs := dvb_ksyms.o +export-objs := dvb_ksyms.o dvb_ringbuffer.o dvb-core-objs = dvbdev.o compat.o dmxdev.o dvb_demux.o dvb_filter.o \ - dvb_frontend.o dvb_i2c.o dvb_net.o dvb_ksyms.o + dvb_frontend.o dvb_i2c.o dvb_net.o dvb_ksyms.o dvb_ringbuffer.o obj-$(CONFIG_DVB_CORE) += dvb-core.o diff --git a/linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.c b/linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.c new file mode 100644 index 000000000..58918a466 --- /dev/null +++ b/linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.c @@ -0,0 +1,176 @@ +/* + * + * dvb_ringbuffer.c: ring buffer implementation for the dvb driver + * + * Copyright (C) 2003 Oliver Endriss + * + * based on code originally found in av7110.c: + * Copyright (C) 1999-2002 Ralph Metzler + * & Marcus Metzler for convergence integrated media GmbH + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + * + * + * the project's page is at http://www.linuxtv.org/dvb/ + */ + + + +#define __KERNEL_SYSCALLS__ +#include <linux/kernel.h> +#include <linux/sched.h> +#include <linux/module.h> +#include <asm/uaccess.h> + +#include "dvb_ringbuffer.h" + + + +void dvb_ringbuffer_init(dvb_ringbuffer_t *rbuf, void *data, size_t len) +{ + rbuf->pread=rbuf->pwrite=0; + rbuf->data=data; + rbuf->size=len; + + init_waitqueue_head(&rbuf->queue); + + spin_lock_init(&(rbuf->lock)); + rbuf->lock=SPIN_LOCK_UNLOCKED; +} + + + +int dvb_ringbuffer_empty(dvb_ringbuffer_t *rbuf) +{ + return (rbuf->pread==rbuf->pwrite); +} + + + +ssize_t dvb_ringbuffer_free(dvb_ringbuffer_t *rbuf) +{ + ssize_t free; + + free = rbuf->pread - rbuf->pwrite; + if (free <= 0) + free += rbuf->size; + return free-1; +} + + + +ssize_t dvb_ringbuffer_avail(dvb_ringbuffer_t *rbuf) +{ + ssize_t avail; + + avail = rbuf->pwrite - rbuf->pread; + if (avail < 0) + avail += rbuf->size; + return avail; +} + + + +void dvb_ringbuffer_flush(dvb_ringbuffer_t *rbuf) +{ + rbuf->pread = rbuf->pwrite; +} + + + +void dvb_ringbuffer_flush_spinlock_wakeup(dvb_ringbuffer_t *rbuf) +{ + unsigned long flags; + + spin_lock_irqsave(&rbuf->lock, flags); + dvb_ringbuffer_flush(rbuf); + spin_unlock_irqrestore(&rbuf->lock, flags); + + wake_up(&rbuf->queue); +} + + + +ssize_t dvb_ringbuffer_read(dvb_ringbuffer_t *rbuf, u8 *buf, size_t len, int usermem) +{ + size_t todo = len; + size_t split; + + split = (rbuf->pread + len > rbuf->size) ? rbuf->size - rbuf->pread : 0; + if (split > 0) { + if (!usermem) + memcpy(buf, rbuf->data+rbuf->pread, split); + else + if (copy_to_user(buf, rbuf->data+rbuf->pread, split)) + return -EFAULT; + buf += split; + todo -= split; + rbuf->pread = 0; + } + if (!usermem) + memcpy(buf, rbuf->data+rbuf->pread, todo); + else + if (copy_to_user(buf, rbuf->data+rbuf->pread, todo)) + return -EFAULT; + + rbuf->pread = (rbuf->pread + len) % rbuf->size; + + return len; +} + + + +ssize_t dvb_ringbuffer_write(dvb_ringbuffer_t *rbuf, const u8 *buf, + size_t len, int usermem) +{ + size_t todo = len; + size_t split; + + split = (rbuf->pwrite + len > rbuf->size) ? rbuf->size - rbuf->pwrite : 0; + + if (split > 0) { + if (!usermem) + memcpy(rbuf->data+rbuf->pwrite, buf, split); + else + if (copy_from_user(rbuf->data+rbuf->pwrite, + buf, split)) + return -EFAULT; + buf += split; + todo -= split; + rbuf->pwrite = 0; + } + if (!usermem) + memcpy(rbuf->data+rbuf->pwrite, buf, todo); + else + if (copy_from_user(rbuf->data+rbuf->pwrite, buf, todo)) + return -EFAULT; + + rbuf->pwrite = (rbuf->pwrite + len) % rbuf->size; + + return len; +} + + +EXPORT_SYMBOL_GPL(dvb_ringbuffer_init); +EXPORT_SYMBOL_GPL(dvb_ringbuffer_empty); +EXPORT_SYMBOL_GPL(dvb_ringbuffer_free); +EXPORT_SYMBOL_GPL(dvb_ringbuffer_avail); +EXPORT_SYMBOL_GPL(dvb_ringbuffer_flush); +EXPORT_SYMBOL_GPL(dvb_ringbuffer_flush_spinlock_wakeup); +EXPORT_SYMBOL_GPL(dvb_ringbuffer_read); +EXPORT_SYMBOL_GPL(dvb_ringbuffer_write); diff --git a/linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.h b/linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.h new file mode 100644 index 000000000..19322ee1e --- /dev/null +++ b/linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.h @@ -0,0 +1,127 @@ +/* + * + * dvb_ringbuffer.h: ring buffer implementation for the dvb driver + * + * Copyright (C) 2003 Oliver Endriss + * + * based on code originally found in av7110.c: + * Copyright (C) 1999-2002 Ralph Metzler + * & Marcus Metzler for convergence integrated media GmbH + * + * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * Or, point your browser to http://www.gnu.org/copyleft/gpl.html + * + * + * the project's page is at http://www.linuxtv.org/dvb/ + */ + +#ifndef _DVB_RINGBUFFER_H_ +#define _DVB_RINGBUFFER_H_ + + +typedef struct dvb_ringbuffer_s { + u8 *data; + ssize_t size; + ssize_t pread; + ssize_t pwrite; + + wait_queue_head_t queue; + spinlock_t lock; +} dvb_ringbuffer_t; + + +/* +** Notes: +** ------ +** (1) For performance reasons read and write routines don't check buffer sizes +** and/or number of bytes free/available. This has to be done before these +** routines are called. For example: +** +** *** write <buflen> bytes *** +** free = dvb_ringbuffer_free(rbuf); +** if (free >= buflen) +** count = dvb_ringbuffer_write(rbuf, buffer, buflen, 0); +** else +** ... +** +** *** read min. 1000, max. <bufsize> bytes *** +** avail = dvb_ringbuffer_available(rbuf); +** if (avail >= 1000) +** count = dvb_ringbuffer_read(rbuf, buffer, min(avail, bufsize), 0); +** else +** ... +** +** (2) If there is exactly one reader and one writer, there is no need +** to lock read or write operations. +** Two or more readers must be locked against each other. +** Flushing the buffer counts as a read operation. +** Two or more writers must be locked against each other. +*/ + +/* initialize ring buffer, lock and queue */ +extern void dvb_ringbuffer_init(dvb_ringbuffer_t *rbuf, void *data, size_t len); + +/* test whether buffer is empty */ +extern int dvb_ringbuffer_empty(dvb_ringbuffer_t *rbuf); + +/* return the number of free bytes in the buffer */ +extern ssize_t dvb_ringbuffer_free(dvb_ringbuffer_t *rbuf); + +/* return the number of bytes waiting in the buffer */ +extern ssize_t dvb_ringbuffer_avail(dvb_ringbuffer_t *rbuf); + + +/* read routines & macros */ +/* ---------------------- */ +/* flush buffer */ +extern void dvb_ringbuffer_flush(dvb_ringbuffer_t *rbuf); + +/* flush buffer protected by spinlock and wake-up waiting task(s) */ +extern void dvb_ringbuffer_flush_spinlock_wakeup(dvb_ringbuffer_t *rbuf); + +/* peek at byte <offs> in the buffer */ +#define DVB_RINGBUFFER_PEEK(rbuf,offs) \ + (rbuf)->data[((rbuf)->pread+(offs))%(rbuf)->size] + +/* advance read ptr by <num> bytes */ +#define DVB_RINGBUFFER_SKIP(rbuf,num) \ + (rbuf)->pread=((rbuf)->pread+(num))%(rbuf)->size + +/* +** read <len> bytes from ring buffer into <buf> +** <usermem> specifies whether <buf> resides in user space +** returns number of bytes transferred or -EFAULT +*/ +extern ssize_t dvb_ringbuffer_read(dvb_ringbuffer_t *rbuf, u8 *buf, + size_t len, int usermem); + + +/* write routines & macros */ +/* ----------------------- */ +/* write single byte to ring buffer */ +#define DVB_RINGBUFFER_WRITE_BYTE(rbuf,byte) \ + { (rbuf)->data[(rbuf)->pwrite]=(byte); \ + (rbuf)->pwrite=((rbuf)->pwrite+1)%(rbuf)->size; } +/* +** write <len> bytes to ring buffer +** <usermem> specifies whether <buf> resides in user space +** returns number of bytes transferred or -EFAULT +*/ +extern ssize_t dvb_ringbuffer_write(dvb_ringbuffer_t *rbuf, const u8 *buf, + size_t len, int usermem); + +#endif /* _DVB_RINGBUFFER_H_ */ |
