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 | |
parent | 218b5ed2dd2770dff18c55b0c813ade613293a1d (diff) | |
download | mediapointer-dvb-s2-5a12e644ad2ddfb5732cec455600de7f0a108305.tar.gz mediapointer-dvb-s2-5a12e644ad2ddfb5732cec455600de7f0a108305.tar.bz2 |
ring buffer cleanup
Diffstat (limited to 'linux')
-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 | ||||
-rw-r--r-- | linux/drivers/media/dvb/ttpci/av7110.c | 442 | ||||
-rw-r--r-- | linux/drivers/media/dvb/ttpci/av7110.h | 22 |
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; |