summaryrefslogtreecommitdiff
path: root/linux/drivers
diff options
context:
space:
mode:
authorOliver Endriss <devnull@localhost>2003-02-18 13:18:02 +0000
committerOliver Endriss <devnull@localhost>2003-02-18 13:18:02 +0000
commit5a12e644ad2ddfb5732cec455600de7f0a108305 (patch)
tree7d4a2e9bde73500e3c21d2174829085a0c5c7a49 /linux/drivers
parent218b5ed2dd2770dff18c55b0c813ade613293a1d (diff)
downloadmediapointer-dvb-s2-5a12e644ad2ddfb5732cec455600de7f0a108305.tar.gz
mediapointer-dvb-s2-5a12e644ad2ddfb5732cec455600de7f0a108305.tar.bz2
ring buffer cleanup
Diffstat (limited to 'linux/drivers')
-rw-r--r--linux/drivers/media/dvb/dvb-core/Makefile4
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.c176
-rw-r--r--linux/drivers/media/dvb/dvb-core/dvb_ringbuffer.h127
-rw-r--r--linux/drivers/media/dvb/ttpci/av7110.c442
-rw-r--r--linux/drivers/media/dvb/ttpci/av7110.h22
5 files changed, 437 insertions, 334 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_ */
diff --git a/linux/drivers/media/dvb/ttpci/av7110.c b/linux/drivers/media/dvb/ttpci/av7110.c
index be2e84297..5bf6a7e26 100644
--- a/linux/drivers/media/dvb/ttpci/av7110.c
+++ b/linux/drivers/media/dvb/ttpci/av7110.c
@@ -541,150 +541,6 @@ AV_Stop(av7110_t *av7110, int av)
}
}
-/****************************************************************************
- * Buffer handling
- ****************************************************************************/
-
-static inline void
-ring_buffer_flush(ring_buffer_t *rbuf)
-{
- spin_lock_irq(&rbuf->lock);
- rbuf->pwrite=rbuf->pread;
- spin_unlock_irq(&rbuf->lock);
- wake_up(&rbuf->queue);
-}
-
-static inline void
-ring_buffer_init(ring_buffer_t *rbuf, u8 *data, int 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;
- sema_init(&(rbuf->sema), 1);
-}
-
-static inline
-int ring_buffer_empty(ring_buffer_t *rbuf)
-{
- return (rbuf->pread==rbuf->pwrite);
-}
-
-static inline
-int ring_buffer_free(ring_buffer_t *rbuf)
-{
- int free;
-
- free=rbuf->pread - rbuf->pwrite;
- if (free<=0)
- free+=rbuf->size;
- return free;
-}
-
-static inline
-int ring_buffer_avail(ring_buffer_t *rbuf)
-{
- int avail;
-
- avail=rbuf->pwrite - rbuf->pread;
- if (avail<0)
- avail+=rbuf->size;
- return avail;
-}
-
-#if 0
-static void
-ring_buffer_block(ring_buffer_t *rbuf, unsigned long count)
-{
- if (ring_buffer_free(rbuf)>=count)
- return;
- while (!wait_event_interruptible(rbuf->queue,
- (ring_buffer_free(rbuf)>=count)));
-}
-#endif
-
-static long
-ring_buffer_write(ring_buffer_t *rbuf,
- const char *buf, unsigned long count,
- int nonblock, int usermem)
-{
- unsigned long todo = count;
- int free, split;
-
- while (todo > 0) {
- if (ring_buffer_free(rbuf)<=2048) {
- if (nonblock)
- return count-todo;
- if (wait_event_interruptible(rbuf->queue,
- (ring_buffer_free(rbuf)>2048)))
- return count-todo;
- }
- DEB_S(("pread=%08x, pwrite=%08x\n",rbuf->pread, rbuf->pwrite));
- //mdelay(2);
- free = rbuf->pread - rbuf->pwrite;
- split=rbuf->size;
- if (free<=0) {
- free+=rbuf->size;
- split-=rbuf->pwrite;
- }
- if (free > todo)
- free = todo;
-
- if (split < free) {
- 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;
- free -= split;
- rbuf->pwrite = 0;
- }
- if (!usermem)
- memcpy(rbuf->data+rbuf->pwrite, buf, free);
- else
- if (copy_from_user(rbuf->data+rbuf->pwrite, buf, free))
- return -EFAULT;
- rbuf->pwrite = (rbuf->pwrite + free)%rbuf->size;
- todo -= free;
- buf += free;
- }
-
- return count-todo;
-}
-
-#if 0
-static void
-ring_buffer_put(ring_buffer_t *db, u8 *buf, int len)
-{
- int split, fsize;
-
- fsize=db->pread - db->pwrite;
- if (fsize <= 0) {
- fsize+=db->size;
- split=db->size-db->pwrite;
- } else
- split=0;
- if (len>=fsize) {
- DEB_S(("buffer overflow, len:%d, size:%d\n",len,size));
- return;
- }
- if (split>=len)
- split=0;
- if (split) {
- memcpy(db->data + db->pwrite, buf, split);
- len-=split;
- db->pwrite=0;
- }
- memcpy(db->data + db->pwrite, split + buf, len);
- db->pwrite=(db->pwrite+len)%db->size;
-}
-#endif
-
/**
* Hack! we save the last av7110 ptr. This should be ok, since
* you rarely will use more then one IR control.
@@ -845,28 +701,16 @@ print_time(char *s)
}
static void
-ci_get_data(ring_buffer_t *cibuf, u8 *data, int len)
+ci_get_data(dvb_ringbuffer_t *cibuf, u8 *data, int len)
{
- int free, split=0, pread=cibuf->pread;
-
- free=pread-cibuf->pwrite;
- if (free<=0)
- free+=cibuf->size;
- if (free<=len+2)
+ if (dvb_ringbuffer_free(cibuf) < len+2)
return;
- cibuf->data[cibuf->pwrite]=(len>>8);
- cibuf->data[(cibuf->pwrite+1)%cibuf->size]=(len&0xff);
- cibuf->pwrite=(cibuf->pwrite+2)%cibuf->size;
-
- if (pread<=cibuf->pwrite)
- split=cibuf->size-cibuf->pwrite;
- if (split && split<len) {
- memcpy(cibuf->data + cibuf->pwrite, data, split);
- memcpy(cibuf->data, data+split, len-split);
- } else
- memcpy(cibuf->data + cibuf->pwrite, data, len);
- cibuf->pwrite=(cibuf->pwrite+len)%cibuf->size;
-
+
+ DVB_RINGBUFFER_WRITE_BYTE(cibuf,len>>8);
+ DVB_RINGBUFFER_WRITE_BYTE(cibuf,len&0xff);
+
+ dvb_ringbuffer_write(cibuf,data,len,0);
+
wake_up_interruptible(&cibuf->queue);
}
@@ -1000,59 +844,44 @@ void debiirq (unsigned long data)
}
static int
-pes_play(void *dest, ring_buffer_t *buf, int dlen)
+pes_play(void *dest, dvb_ringbuffer_t *buf, int dlen)
{
- int len, split=0;
+ int len;
u32 sync;
u16 blen;
- DEB_EE(("ring_buffer_t: %p\n",buf));
+ DEB_EE(("dvb_ring_buffer_t: %p\n",buf));
if (!dlen) {
wake_up(&buf->queue);
return -1;
}
while (1) {
- if ((len=ring_buffer_avail(buf)) < 6)
+ if ((len=dvb_ringbuffer_avail(buf)) < 6)
return -1;
- sync=(buf->data[buf->pread])<<24;
- sync|=(buf->data[(buf->pread+1)%buf->size]<<16);
- sync|=(buf->data[(buf->pread+2)%buf->size]<<8);
- sync|=buf->data[(buf->pread+3)%buf->size];
+ sync= DVB_RINGBUFFER_PEEK(buf,0)<<24;
+ sync|=DVB_RINGBUFFER_PEEK(buf,1)<<16;
+ sync|=DVB_RINGBUFFER_PEEK(buf,2)<<8;
+ sync|=DVB_RINGBUFFER_PEEK(buf,3);
if (((sync&~0x1f)==0x000001e0) ||
((sync&~0x1f)==0x000001c0) ||
(sync==0x000001bd))
break;
printk("resync\n");
- buf->pread=(buf->pread+1)%buf->size;
+ DVB_RINGBUFFER_SKIP(buf,1);
}
- blen=(buf->data[(buf->pread+4)%buf->size]<<8);
- blen|=buf->data[(buf->pread+5)%buf->size];
+ blen= DVB_RINGBUFFER_PEEK(buf,4)<<8;
+ blen|=DVB_RINGBUFFER_PEEK(buf,5);
blen+=6;
- if (len<blen || blen > dlen) {
- printk("buffer empty\n");
+ if (len<blen || blen>dlen) {
+ printk("buffer empty - avail %d blen %u dlen %d\n",len,blen,dlen);
wake_up(&buf->queue);
return -1;
}
-/* if (blen>2048) {
- buf->pread=(buf->pread+blen)%buf->size;
- printk("packet too large\n");
- return -1;
- }
-*/
- len=blen;
- if (buf->pread + len > buf->size)
- split=buf->size-buf->pread;
- if (split>0) {
- memcpy(dest, buf->data+buf->pread, split);
- buf->pread=0;
- len-=split;
- }
- memcpy(split + dest,
- buf->data + buf->pread, len);
- buf->pread = (buf->pread +len)%buf->size;
-
+
+ (void)dvb_ringbuffer_read(buf,dest,(size_t)blen,0);
+
DEB_S(("pread=%08x, pwrite=%08x\n",buf->pread, buf->pwrite));
wake_up(&buf->queue);
return blen;
@@ -1098,38 +927,28 @@ void gpioirq (unsigned long data)
case DATA_CI_PUT:
{
- int avail, split=0, pwrite;
- ring_buffer_t *cibuf=&av7110->ci_wbuffer;
+ int avail;
+ dvb_ringbuffer_t *cibuf=&av7110->ci_wbuffer;
- pwrite=cibuf->pwrite;
- avail=pwrite-cibuf->pread;
- if (avail<0)
- avail+=cibuf->size;
+ avail=dvb_ringbuffer_avail(cibuf);
if (avail<=2) {
iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
break;
}
- len=(cibuf->data[cibuf->pread]<<8);
- len|=cibuf->data[(cibuf->pread+1)%cibuf->size];
+ len= DVB_RINGBUFFER_PEEK(cibuf,0)<<8;
+ len|=DVB_RINGBUFFER_PEEK(cibuf,1);
if (avail<len+2) {
iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, 0, 2);
iwdebi(av7110, DEBINOSWAP, TX_LEN, 0, 2);
iwdebi(av7110, DEBINOSWAP, TX_BUFF, 0, 2);
break;
}
- cibuf->pread=(cibuf->pread+2)%cibuf->size;
-
- if (pwrite<cibuf->pread)
- split=cibuf->size-cibuf->pread;
- if (split && split<len) {
- int todo=len-split;
- memcpy(av7110->debi_virt, cibuf->data+cibuf->pread, split);
- memcpy(av7110->debi_virt+split, cibuf->data, todo);
- } else
- memcpy(av7110->debi_virt, cibuf->data+cibuf->pread, len);
- cibuf->pread=(cibuf->pread+len)%cibuf->size;
+ DVB_RINGBUFFER_SKIP(cibuf,2);
+
+ dvb_ringbuffer_read(cibuf,av7110->debi_virt,len,0);
+
wake_up(&cibuf->queue);
iwdebi(av7110, DEBINOSWAP, TX_LEN, len, 2);
iwdebi(av7110, DEBINOSWAP, IRQ_STATE_EXT, len, 2);
@@ -2411,6 +2230,29 @@ get_video_format(av7110_t *av7110, u8 *buf, int count)
}
}
+static inline long
+aux_ring_buffer_write(dvb_ringbuffer_t *rbuf, const char *buf, unsigned long count)
+{
+ unsigned long todo = count;
+ int free;
+
+ while (todo > 0) {
+ if (dvb_ringbuffer_free(rbuf)<2048) {
+ if (wait_event_interruptible(rbuf->queue,
+ (dvb_ringbuffer_free(rbuf)>=2048)))
+ return count-todo;
+ }
+ free = dvb_ringbuffer_free(rbuf);
+ if (free > todo)
+ free = todo;
+ (void)dvb_ringbuffer_write(rbuf,buf,free,0);
+ todo -= free;
+ buf += free;
+ }
+
+ return count-todo;
+}
+
static void
play_video_cb(u8 *buf, int count, void *priv)
{
@@ -2419,9 +2261,9 @@ play_video_cb(u8 *buf, int count, void *priv)
if ((buf[3]&0xe0)==0xe0) {
get_video_format(av7110, buf, count);
- ring_buffer_write(&av7110->avout, buf, count, 0, 0);
+ aux_ring_buffer_write(&av7110->avout, buf, count);
} else
- ring_buffer_write(&av7110->aout, buf, count, 0, 0);
+ aux_ring_buffer_write(&av7110->aout, buf, count);
}
static void
@@ -2430,10 +2272,10 @@ play_audio_cb(u8 *buf, int count, void *priv)
av7110_t *av7110=(av7110_t *) priv;
DEB_EE(("av7110: %p\n",av7110));
- ring_buffer_write(&av7110->aout, buf, count, 0, 0);
+ aux_ring_buffer_write(&av7110->aout, buf, count);
}
-#define FREE_COND (ring_buffer_free(&av7110->avout)>=20*1024 && ring_buffer_free(&av7110->aout)>=20*1024)
+#define FREE_COND (dvb_ringbuffer_free(&av7110->avout)>=20*1024 && dvb_ringbuffer_free(&av7110->aout)>=20*1024)
static ssize_t
dvb_play(av7110_t *av7110, const u8 *buf,
@@ -2483,15 +2325,15 @@ dvb_aplay(av7110_t *av7110, const u8 *buf,
if (!av7110->kbuf[type])
return -ENOBUFS;
- if (nonblock && ring_buffer_free(&av7110->aout)<20*1024)
+ if (nonblock && dvb_ringbuffer_free(&av7110->aout)<20*1024)
return -EWOULDBLOCK;
while (todo>0) {
- if (ring_buffer_free(&av7110->aout)<20*1024) {
+ if (dvb_ringbuffer_free(&av7110->aout)<20*1024) {
if (nonblock)
return count-todo;
if (wait_event_interruptible(av7110->aout.queue,
- (ring_buffer_free(&av7110->aout)>=
+ (dvb_ringbuffer_free(&av7110->aout)>=
20*1024)))
return count-todo;
}
@@ -2804,7 +2646,7 @@ unsigned int dvb_audio_poll(struct file *file, poll_table *wait)
if (av7110->playing) {
poll_wait(file, &av7110->aout.queue, wait);
- if (ring_buffer_free(&av7110->aout)>20*1024)
+ if (dvb_ringbuffer_free(&av7110->aout)>20*1024)
mask |= (POLLOUT | POLLWRNORM);
} else /* if not playing: may play if asked for */
mask = (POLLOUT | POLLWRNORM);
@@ -3045,8 +2887,8 @@ av7110_start_feed(struct dvb_demux_feed *feed)
if (feed->pes_type < 2 &&
!(demux->pids[0] & 0x8000) &&
!(demux->pids[1] & 0x8000)) {
- ring_buffer_flush(&av7110->avout);
- ring_buffer_flush(&av7110->aout);
+ dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
+ dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
AV_StartPlay(av7110,RP_AV);
demux->playing = 1;
}
@@ -3194,20 +3036,20 @@ int av7110_diseqc_ioctl (struct dvb_frontend *fe, unsigned int cmd, void *arg)
* CI link layer file ops (FIXME: move this to separate module later)
******************************************************************************/
-int ci_ll_init(ring_buffer_t *cirbuf, ring_buffer_t *ciwbuf, int size)
+int ci_ll_init(dvb_ringbuffer_t *cirbuf, dvb_ringbuffer_t *ciwbuf, int size)
{
- ring_buffer_init(cirbuf, vmalloc(size), size);
- ring_buffer_init(ciwbuf, vmalloc(size), size);
+ dvb_ringbuffer_init(cirbuf, vmalloc(size), size);
+ dvb_ringbuffer_init(ciwbuf, vmalloc(size), size);
return 0;
}
-void ci_ll_flush(ring_buffer_t *cirbuf, ring_buffer_t *ciwbuf)
+void ci_ll_flush(dvb_ringbuffer_t *cirbuf, dvb_ringbuffer_t *ciwbuf)
{
- ring_buffer_flush(cirbuf);
- ring_buffer_flush(ciwbuf);
+ dvb_ringbuffer_flush_spinlock_wakeup(cirbuf);
+ dvb_ringbuffer_flush_spinlock_wakeup(ciwbuf);
}
-void ci_ll_release(ring_buffer_t *cirbuf, ring_buffer_t *ciwbuf)
+void ci_ll_release(dvb_ringbuffer_t *cirbuf, dvb_ringbuffer_t *ciwbuf)
{
vfree(cirbuf->data);
cirbuf->data=0;
@@ -3216,109 +3058,79 @@ void ci_ll_release(ring_buffer_t *cirbuf, ring_buffer_t *ciwbuf)
}
-int ci_ll_reset(ring_buffer_t *cibuf, struct file *file,
+int ci_ll_reset(dvb_ringbuffer_t *cibuf, struct file *file,
int slots, ca_slot_info_t *slot)
{
int i;
+ int len=0;
+ u8 msg[8]={0x00,0x06,0,0x00,0xff,0x02,0x00,0x00};
- if (ring_buffer_free(cibuf)<=8)
- return -EBUSY;
+ for (i=0; i<2; i++) {
+ if (slots & (1<<i))
+ len+=8;
+ }
+
+ if (dvb_ringbuffer_free(cibuf) < len)
+ return -EBUSY;
for (i=0; i<2; i++) {
- if (slots&(1<<i)) {
- cibuf->data[cibuf->pwrite]=0x00;
- cibuf->data[(cibuf->pwrite+1)%cibuf->size]=0x06;
- cibuf->data[(cibuf->pwrite+2)%cibuf->size]=i;
- cibuf->data[(cibuf->pwrite+3)%cibuf->size]=0x00;
- cibuf->data[(cibuf->pwrite+4)%cibuf->size]=0xff;
- cibuf->data[(cibuf->pwrite+5)%cibuf->size]=0x02;
- cibuf->data[(cibuf->pwrite+6)%cibuf->size]=0x00;
- cibuf->data[(cibuf->pwrite+7)%cibuf->size]=0x00;
- cibuf->pwrite=(cibuf->pwrite+8)%cibuf->size;
- slot[i].flags=0;
- }
+ if (slots & (1<<i)) {
+ msg[2]=i;
+ dvb_ringbuffer_write(cibuf,msg,8,0);
+ slot[i].flags=0;
+ }
}
return 0;
}
static ssize_t
-ci_ll_write(ring_buffer_t *cibuf, struct file *file, const char *buf, size_t count, loff_t *ppos)
+ci_ll_write(dvb_ringbuffer_t *cibuf, struct file *file, const char *buf, size_t count, loff_t *ppos)
{
- int free, split;
- int32_t pread;
+ int free;
int non_blocking=file->f_flags&O_NONBLOCK;
-
+
if (count>2048)
return -EINVAL;
- pread=cibuf->pread;
- free=pread-cibuf->pwrite;
- if (free<=0)
- free+=cibuf->size;
- if (count+2>=free) {
+ free=dvb_ringbuffer_free(cibuf);
+ if (count+2>free) {
if (non_blocking)
return -EWOULDBLOCK;
if (wait_event_interruptible(cibuf->queue,
- (ring_buffer_free(cibuf)>count+2)))
+ (dvb_ringbuffer_free(cibuf)>=count+2)))
return 0;
}
- cibuf->data[cibuf->pwrite]=(count>>8);
- cibuf->data[(cibuf->pwrite+1)%cibuf->size]=(count&0xff);
- cibuf->pwrite=(cibuf->pwrite+2)%cibuf->size;
- if (pread>cibuf->pwrite)
- split=0;
- else
- split=cibuf->size-cibuf->pwrite;
- if (split && split<count) {
- if (copy_from_user(cibuf->data + cibuf->pwrite, buf, split))
- return -EFAULT;
- if (copy_from_user(cibuf->data, buf+split, count-split))
- return -EFAULT;
- } else
- if (copy_from_user(cibuf->data + cibuf->pwrite, buf, count))
- return -EFAULT;
- cibuf->pwrite=(cibuf->pwrite+count)%cibuf->size;
- return count;
+ DVB_RINGBUFFER_WRITE_BYTE(cibuf,count>>8);
+ DVB_RINGBUFFER_WRITE_BYTE(cibuf,count&0xff);
+
+ return dvb_ringbuffer_write(cibuf,buf,count,1);
}
static ssize_t
-ci_ll_read(ring_buffer_t *cibuf, struct file *file, char *buf, size_t count, loff_t *ppos)
+ci_ll_read(dvb_ringbuffer_t *cibuf, struct file *file, char *buf, size_t count, loff_t *ppos)
{
- int split=0, avail, pwrite;
- int non_blocking=file->f_flags&O_NONBLOCK;
-
+ int avail;
+ int non_blocking=file->f_flags&O_NONBLOCK;
+ ssize_t len;
+
if (!cibuf->data || !count)
return 0;
- if (non_blocking && (ring_buffer_empty(cibuf)))
+ if (non_blocking && (dvb_ringbuffer_empty(cibuf)))
return -EWOULDBLOCK;
- if (wait_event_interruptible(cibuf->queue,
- !ring_buffer_empty(cibuf)))
+ if (wait_event_interruptible(cibuf->queue,
+ !dvb_ringbuffer_empty(cibuf)))
return 0;
- pwrite=cibuf->pwrite;
- avail=pwrite - cibuf->pread;
- if (avail<0)
- avail+=cibuf->size;
+ avail=dvb_ringbuffer_avail(cibuf);
if (avail<4)
- return 0;
- count=(cibuf->data[cibuf->pread]<<8);
- count|=cibuf->data[(cibuf->pread+1)%cibuf->size];
- if (avail<count+2)
- return -EINVAL;
- cibuf->pread=(cibuf->pread+2)%cibuf->size;
-
- if (pwrite<cibuf->pread)
- split=cibuf->size-cibuf->pread;
- if (split && split<count) {
- if (copy_to_user(buf, cibuf->data+cibuf->pread, split))
- return -EFAULT;
- if (copy_to_user(buf+split, cibuf->data, count-split))
- return -EFAULT;
- } else
- if (copy_to_user(buf, cibuf->data+cibuf->pread, count))
- return -EFAULT;
- cibuf->pread=(cibuf->pread + count)%cibuf->size;
- return count;
+ return 0;
+ len= DVB_RINGBUFFER_PEEK(cibuf,0)<<8;
+ len|=DVB_RINGBUFFER_PEEK(cibuf,1);
+ if (avail<len+2 || count<len)
+ return -EINVAL;
+ DVB_RINGBUFFER_SKIP(cibuf,2);
+
+ return dvb_ringbuffer_read(cibuf,buf,len,1);
}
static int
@@ -3343,17 +3155,17 @@ unsigned int dvb_ca_poll (struct file *file, poll_table *wait)
av7110_t *av7110 = (av7110_t *) dvbdev->priv;
unsigned int mask = 0;
- ring_buffer_t *rbuf = &av7110->ci_rbuffer;
- ring_buffer_t *wbuf = &av7110->ci_wbuffer;
+ dvb_ringbuffer_t *rbuf = &av7110->ci_rbuffer;
+ dvb_ringbuffer_t *wbuf = &av7110->ci_wbuffer;
DEB_EE(("av7110: %p\n",av7110));
poll_wait (file, &rbuf->queue, wait);
- if (!ring_buffer_empty(rbuf))
+ if (!dvb_ringbuffer_empty(rbuf))
mask |= POLLIN;
- if (ring_buffer_avail(wbuf)>1024)
+ if (dvb_ringbuffer_avail(wbuf)>1024)
mask |= POLLOUT;
return mask;
@@ -3674,7 +3486,7 @@ dvb_video_ioctl(struct inode *inode, struct file *file,
{
struct video_still_picture *pic=
(struct video_still_picture *) parg;
- ring_buffer_flush(&av7110->avout);
+ dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
play_iframe(av7110, pic->iFrame, pic->size,
file->f_flags&O_NONBLOCK);
break;
@@ -3712,7 +3524,7 @@ dvb_video_ioctl(struct inode *inode, struct file *file,
break;
case VIDEO_CLEAR_BUFFER:
- ring_buffer_flush(&av7110->avout);
+ dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
av7110_ipack_reset(&av7110->ipack[1]);
if (av7110->playing==RP_AV) {
@@ -3837,7 +3649,7 @@ dvb_audio_ioctl(struct inode *inode, struct file *file,
break;
case AUDIO_CLEAR_BUFFER:
- ring_buffer_flush(&av7110->aout);
+ dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
av7110_ipack_reset(&av7110->ipack[0]);
if (av7110->playing==RP_AV)
outcom(av7110, COMTYPE_REC_PLAY,
@@ -3873,8 +3685,8 @@ static int dvb_video_open(struct inode *inode, struct file *file)
if ((err=dvb_generic_open(inode, file))<0)
return err;
- ring_buffer_flush(&av7110->aout);
- ring_buffer_flush(&av7110->avout);
+ dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
+ dvb_ringbuffer_flush_spinlock_wakeup(&av7110->avout);
av7110->video_blank=1;
av7110->audiostate.AV_sync_state=1;
av7110->videostate.stream_source=VIDEO_SOURCE_DEMUX;
@@ -3902,7 +3714,7 @@ static int dvb_audio_open(struct inode *inode, struct file *file)
if (err<0)
return err;
- ring_buffer_flush(&av7110->aout);
+ dvb_ringbuffer_flush_spinlock_wakeup(&av7110->aout);
av7110->audiostate.stream_source=AUDIO_SOURCE_DEMUX;
return 0;
}
@@ -4280,8 +4092,8 @@ int av7110_attach (struct saa7146_dev* dev, struct saa7146_pci_extension_data *p
goto err;
}
- ring_buffer_init(&av7110->avout, av7110->iobuf, AVOUTLEN);
- ring_buffer_init(&av7110->aout, av7110->iobuf+AVOUTLEN, AOUTLEN);
+ dvb_ringbuffer_init(&av7110->avout, av7110->iobuf, AVOUTLEN);
+ dvb_ringbuffer_init(&av7110->aout, av7110->iobuf+AVOUTLEN, AOUTLEN);
/* init BMP buffer */
av7110->bmpbuf=av7110->iobuf+AVOUTLEN+AOUTLEN;
diff --git a/linux/drivers/media/dvb/ttpci/av7110.h b/linux/drivers/media/dvb/ttpci/av7110.h
index d1eabe3ab..901cc305b 100644
--- a/linux/drivers/media/dvb/ttpci/av7110.h
+++ b/linux/drivers/media/dvb/ttpci/av7110.h
@@ -38,6 +38,7 @@
#include "dmxdev.h"
#include "dvb_filter.h"
#include "dvb_net.h"
+#include "dvb_ringbuffer.h"
typedef enum BOOTSTATES
{
@@ -313,19 +314,6 @@ typedef enum {
#define CI_MSG_CA_PMT 0xe0
#define CI_MSG_ERROR 0xf0
-typedef struct ring_buffer_s {
- u8 *data;
- int size;
- int pread;
- int pwrite;
-
- WAIT_QUEUE queue;
- spinlock_t lock;
- struct semaphore sema;
-
- int error;
-} ring_buffer_t;
-
#define PROG_STREAM_MAP 0xBC
#define PRIVATE_STREAM1 0xBD
@@ -482,9 +470,9 @@ typedef struct av7110_s {
/* buffers */
void *iobuf; /* memory for all buffers */
- ring_buffer_t avout; /* buffer for video or A/V mux */
+ dvb_ringbuffer_t avout; /* buffer for video or A/V mux */
#define AVOUTLEN (128*1024)
- ring_buffer_t aout; /* buffer for audio */
+ dvb_ringbuffer_t aout; /* buffer for audio */
#define AOUTLEN (64*1024)
void *bmpbuf;
#define BMPLEN (8*32768+1024)
@@ -585,8 +573,8 @@ typedef struct av7110_s {
u16 pids[DMX_PES_OTHER];
- ring_buffer_t ci_rbuffer;
- ring_buffer_t ci_wbuffer;
+ dvb_ringbuffer_t ci_rbuffer;
+ dvb_ringbuffer_t ci_wbuffer;
struct dvb_adapter *dvb_adapter;