⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 em8300_fifo.c

📁 linux TV 源码
💻 C
字号:
/*	Copyright (C) 2000 Henrik Johansson <henrikjo@post.utfors.se>	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.*/#define __NO_VERSION__#include <linux/module.h>#include <linux/delay.h>#include <linux/init.h>#include <linux/errno.h>#include <linux/fs.h>#include <linux/kernel.h>#include <linux/major.h>#include <linux/slab.h>#include <linux/vmalloc.h>#include <linux/mm.h>#include <linux/pci.h>#include <linux/signal.h>#include <linux/string.h>#include <linux/time.h>#include <asm/io.h>#include <asm/pgtable.h>#include <asm/page.h>#include <linux/sched.h>#include <asm/segment.h>#include <linux/version.h>#include <asm/uaccess.h>#include <linux/i2c-algo-bit.h>#include "em8300_reg.h"#include <linux/em8300.h>#include "em8300_fifo.h"int em8300_fifo_init(struct em8300_s *em, struct fifo_s *f, int start, int wrptr, int rdptr, int pcisize, int slotsize, int fifotype){	int i;	unsigned phys;	f->em = em;	f->preprocess_ratio = 1;	f->preprocess_cb = NULL;	f->preprocess_maxbufsize = -1;		f->type = fifotype;		f->writeptr = (unsigned *)ucregister_ptr(wrptr);	f->readptr = (unsigned *)ucregister_ptr(rdptr);	switch (f->type) {	case FIFOTYPE_AUDIO:		f->slotptrsize = 3;		f->slots.a = (struct audio_fifoslot_s *) ucregister_ptr(start);		f->nslots = read_ucregister(pcisize) / 3;		break;	case FIFOTYPE_VIDEO:		f->slotptrsize = 4;		f->slots.v = (struct video_fifoslot_s *) ucregister_ptr(start);		f->nslots = read_ucregister(pcisize) / 4;		break;	}		f->slotsize = slotsize;	f->start = ucregister(start) - 0x1000;	f->threshold = f->nslots / 2;	f->waiting=0;	f->bytes = 0;	if (f->fifobuffer) {		kfree(f->fifobuffer);	}		f->fifobuffer = kmalloc(f->nslots * f->slotsize, GFP_KERNEL);	if (f->fifobuffer == NULL) {		return -ENOMEM;	}#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,0)	init_waitqueue(&f->wait);#else	init_waitqueue_head(&f->wait);#endif			for (i=0; i < f->nslots; i++) {		phys = virt_to_phys(f->fifobuffer + i*f->slotsize);		switch (f->type) {		case FIFOTYPE_AUDIO:				f->slots.a[i].physaddress_hi = phys >> 16;			f->slots.a[i].physaddress_lo = phys & 0xffff;			f->slots.a[i].slotsize = f->slotsize;			break;		case FIFOTYPE_VIDEO:			f->slots.v[i].flags = 0;			f->slots.v[i].physaddress_hi = phys >> 16;			f->slots.v[i].physaddress_lo = phys & 0xffff;			f->slots.v[i].slotsize = f->slotsize;		}	}	f->valid = 1;		return 0;}void em8300_fifo_free(struct fifo_s *f){	if (f) {		if(f->valid && f->fifobuffer) {			kfree(f->fifobuffer);		}		kfree(f);	}}struct fifo_s *em8300_fifo_alloc(){	struct fifo_s *f = kmalloc(sizeof(struct fifo_s), GFP_KERNEL);	if (f) {		memset(f, 0, sizeof(struct fifo_s));	}	return f;}int em8300_fifo_check(struct fifo_s *fifo){	int freeslots;		if (!fifo || !fifo->valid) {		return -1;	}		freeslots = ((*fifo->readptr - *fifo->writeptr) / 4 + fifo->nslots - 1) % fifo->nslots;	if ((freeslots > fifo->threshold) && fifo->waiting) {		fifo->waiting=0;		wake_up_interruptible(&fifo->wait);	}	return 0;}int em8300_fifo_sync(struct fifo_s *fifo){	while (*fifo->writeptr != *fifo->readptr) {		fifo->waiting=1;			interruptible_sleep_on(&fifo->wait);		fifo->waiting=0;		if (signal_pending(current)) {			printk(KERN_ERR "em8300.o: FIFO sync interrupted\n");					return -EINTR;		}	}	return 0;}int em8300_fifo_write(struct fifo_s *fifo, int n, const char *userbuffer,			  int flags){	int freeslots,writeindex,i,bytes_transferred=0,copysize;	if (!fifo || !fifo->valid) {		return -1;	}		freeslots = ((*fifo->readptr - *fifo->writeptr) / fifo->slotptrsize + fifo->nslots - 1) % fifo->nslots;	writeindex = (*fifo->writeptr - fifo->start) / fifo->slotptrsize;	for (i=0; i < freeslots && n; i++) {		copysize = n < fifo->slotsize / fifo->preprocess_ratio ? n : fifo->slotsize / fifo->preprocess_ratio;		if ((fifo->preprocess_maxbufsize > 0) && (copysize > fifo->preprocess_maxbufsize)) {			copysize = fifo->preprocess_maxbufsize;		}		switch (fifo->type) {		case FIFOTYPE_AUDIO:			fifo->slots.a[writeindex].slotsize = copysize*fifo->preprocess_ratio;			break;		case FIFOTYPE_VIDEO:			fifo->slots.v[writeindex].flags = flags;			fifo->slots.v[writeindex].slotsize = copysize*fifo->preprocess_ratio;			break;		}			if (fifo->preprocess_cb) {			fifo->preprocess_cb(fifo->em, fifo->fifobuffer + writeindex*fifo->slotsize, userbuffer, copysize);		} else {			copy_from_user(fifo->fifobuffer + writeindex*fifo->slotsize, userbuffer, copysize);		}			writeindex++;		writeindex %= fifo->nslots;		n -= copysize;		userbuffer += copysize;		bytes_transferred += copysize;		fifo->bytes += copysize;	}	*fifo->writeptr = fifo->start + writeindex*fifo->slotptrsize;	return bytes_transferred;}int em8300_fifo_writeblocking(struct fifo_s *fifo, int n, const char *userbuffer, int flags){	int total_bytes_written=0,copy_size;	if(!fifo->valid) {		return -EPERM;	}		while (n) {		copy_size = em8300_fifo_write(fifo, n, userbuffer, flags);		if (!copy_size) {			fifo->waiting=1;			interruptible_sleep_on(&fifo->wait);		}			if (signal_pending(current)) {			if (total_bytes_written) {				return total_bytes_written;			} else {				return -EINTR;			}		}		if (copy_size < 0) {			return -EIO;		}			n -= copy_size;		userbuffer += copy_size;		total_bytes_written += copy_size;	}	return total_bytes_written;}int em8300_fifo_freeslots(struct fifo_s *fifo){	return ((*fifo->readptr - *fifo->writeptr) / fifo->slotptrsize + fifo->nslots - 1) % fifo->nslots;}void em8300_fifo_statusmsg(struct fifo_s *fifo, char *str){	int freeslots = em8300_fifo_freeslots(fifo);	sprintf(str,"Free slots: %d/%d", freeslots, fifo->nslots);}int em8300_fifo_calcbuffered(struct fifo_s *fifo){	int readindex,writeindex,i,n;	writeindex = (*fifo->writeptr - fifo->start) / fifo->slotptrsize;		readindex = (*fifo->readptr - fifo->start) / fifo->slotptrsize;	n=0;	i=readindex;	while (i != writeindex) {		switch (fifo->type) {		case FIFOTYPE_AUDIO:			n += fifo->slots.a[i].slotsize;			break;		case FIFOTYPE_VIDEO:			n += fifo->slots.v[i].slotsize;			break;		}		i++;		i &= fifo->nslots-1;	}	return n;}int em8300_fifo_isempty(struct fifo_s *fifo){	return !(*fifo->writeptr - *fifo->readptr);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -