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

📄 skystar2.c

📁 linux环境下的dvb驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * skystar2.c - driver for the Technisat SkyStar2 PCI DVB card *              based on the FlexCopII by B2C2,Inc. * * Copyright (C) 2003  Vadim Catana, skystar@moldova.cc * * FIX: DISEQC Tone Burst in flexcop_diseqc_ioctl() * FIX: FULL soft DiSEqC for skystar2 (FlexCopII rev 130) VP310 equipped  *     Vincenzo Di Massa, hawk.it at tiscalinet.it * 	 * Converted to Linux coding style * Misc reorganization, polishing, restyling *     Roberto Ragusa, r.ragusa at libero.it *        * Added hardware filtering support, *     Niklas Peinecke, peinecke at gdv.uni-hannover.de * * 	 * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation; either version 2.1 * 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 Lesser 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. */#include <linux/module.h>#include <linux/delay.h>#include <linux/pci.h>#include <linux/init.h>#include <asm/io.h>#include "dvb_i2c.h"#include "dvb_frontend.h"#include <linux/dvb/frontend.h>#include <linux/dvb/dmx.h>#include "dvb_demux.h"#include "dmxdev.h"#include "dvb_filter.h"#include "dvbdev.h"#include "demux.h"#include "dvb_net.h"#include "dvb_functions.h"static int debug = 0;#define dprintk(x...)	do { if (debug>=1) printk(x); } while (0)#define ddprintk(x...)	do { if (debug>=2) printk(x); } while (0)static int enable_hw_filters = 2;#define SIZE_OF_BUF_DMA1	0x3ac00#define SIZE_OF_BUF_DMA2	0x758#define MAX_N_HW_FILTERS	(6+32)#define N_PID_SLOTS		256struct dmaq {	u32 bus_addr;	u32 head;	u32 tail;	u32 buffer_size;	u8 *buffer;};struct adapter {	struct pci_dev *pdev;	u8 card_revision;	u32 b2c2_revision;	u32 pid_filter_max;	u32 mac_filter_max;	u32 irq;	unsigned long io_mem;	unsigned long io_port;	u8 mac_addr[8];	u32 dw_sram_type;	struct dvb_adapter *dvb_adapter;	struct dvb_demux demux;	struct dmxdev dmxdev;	struct dmx_frontend hw_frontend;	struct dmx_frontend mem_frontend;	struct dvb_i2c_bus *i2c_bus;	struct dvb_net dvbnet;	struct semaphore i2c_sem;	struct dmaq dmaq1;	struct dmaq dmaq2;	u32 dma_ctrl;	u32 dma_status;	int capturing;	spinlock_t lock;	int useable_hw_filters;	u16 hw_pids[MAX_N_HW_FILTERS];	u16 pid_list[N_PID_SLOTS];	int pid_rc[N_PID_SLOTS];	// ref counters for the pids	int pid_count;	int whole_bandwidth_count;	u32 mac_filter;};#define write_reg_dw(adapter,reg,value) writel(value, adapter->io_mem + reg)#define read_reg_dw(adapter,reg) readl(adapter->io_mem + reg)static void write_reg_bitfield(struct adapter *adapter, u32 reg, u32 zeromask, u32 orvalue){	u32 tmp;	tmp = read_reg_dw(adapter, reg);	tmp = (tmp & ~zeromask) | orvalue;	write_reg_dw(adapter, reg, tmp);}/* i2c functions */static int i2c_main_write_for_flex2(struct adapter *adapter, u32 command, u8 *buf, int retries){	int i;	u32 value;	write_reg_dw(adapter, 0x100, 0);	write_reg_dw(adapter, 0x100, command);	for (i = 0; i < retries; i++) {		value = read_reg_dw(adapter, 0x100);		if ((value & 0x40000000) == 0) {			if ((value & 0x81000000) == 0x80000000) {				if (buf != 0)					*buf = (value >> 0x10) & 0xff;				return 1;			}		} else {			write_reg_dw(adapter, 0x100, 0);			write_reg_dw(adapter, 0x100, command);		}	}	return 0;}/* device = 0x10000000 for tuner, 0x20000000 for eeprom */static void i2c_main_setup(u32 device, u32 chip_addr, u8 op, u8 addr, u32 value, u32 len, u32 *command){	*command = device | ((len - 1) << 26) | (value << 16) | (addr << 8) | chip_addr;	if (op != 0)		*command = *command | 0x03000000;	else		*command = *command | 0x01000000;}static int flex_i2c_read4(struct adapter *adapter, u32 device, u32 chip_addr, u16 addr, u8 *buf, u8 len){	u32 command;	u32 value;	int result, i;	i2c_main_setup(device, chip_addr, 1, addr, 0, len, &command);	result = i2c_main_write_for_flex2(adapter, command, buf, 100000);	if ((result & 0xff) != 0) {		if (len > 1) {			value = read_reg_dw(adapter, 0x104);			for (i = 1; i < len; i++) {				buf[i] = value & 0xff;				value = value >> 8;			}		}	}	return result;}static int flex_i2c_write4(struct adapter *adapter, u32 device, u32 chip_addr, u32 addr, u8 *buf, u8 len){	u32 command;	u32 value;	int i;	if (len > 1) {		value = 0;		for (i = len; i > 1; i--) {			value = value << 8;			value = value | buf[i - 1];		}		write_reg_dw(adapter, 0x104, value);	}	i2c_main_setup(device, chip_addr, 0, addr, buf[0], len, &command);	return i2c_main_write_for_flex2(adapter, command, 0, 100000);}static void fixchipaddr(u32 device, u32 bus, u32 addr, u32 *ret){	if (device == 0x20000000)		*ret = bus | ((addr >> 8) & 3);	*ret = bus;}static u32 flex_i2c_read(struct adapter *adapter, u32 device, u32 bus, u32 addr, u8 *buf, u32 len){	u32 chipaddr;	u32 bytes_to_transfer;	u8 *start;	ddprintk("%s:\n", __FUNCTION__);	start = buf;	while (len != 0) {		bytes_to_transfer = len;		if (bytes_to_transfer > 4)			bytes_to_transfer = 4;		fixchipaddr(device, bus, addr, &chipaddr);		if (flex_i2c_read4(adapter, device, chipaddr, addr, buf, bytes_to_transfer) == 0)			return buf - start;		buf = buf + bytes_to_transfer;		addr = addr + bytes_to_transfer;		len = len - bytes_to_transfer;	};	return buf - start;}static u32 flex_i2c_write(struct adapter *adapter, u32 device, u32 bus, u32 addr, u8 *buf, u32 len){	u32 chipaddr;	u32 bytes_to_transfer;	u8 *start;	ddprintk("%s:\n", __FUNCTION__);	start = buf;	while (len != 0) {		bytes_to_transfer = len;		if (bytes_to_transfer > 4)			bytes_to_transfer = 4;		fixchipaddr(device, bus, addr, &chipaddr);		if (flex_i2c_write4(adapter, device, chipaddr, addr, buf, bytes_to_transfer) == 0)			return buf - start;		buf = buf + bytes_to_transfer;		addr = addr + bytes_to_transfer;		len = len - bytes_to_transfer;	}	return buf - start;}static int master_xfer(struct dvb_i2c_bus *i2c, const struct i2c_msg *msgs, int num){	struct adapter *tmp = i2c->data;	int i, ret = 0;	if (down_interruptible(&tmp->i2c_sem))		return -ERESTARTSYS;	ddprintk("%s: %d messages to transfer\n", __FUNCTION__, num);	for (i = 0; i < num; i++) {		ddprintk("message %d: flags=0x%x, addr=0x%x, buf=0x%x, len=%d \n", i,			 msgs[i].flags, msgs[i].addr, msgs[i].buf[0], msgs[i].len);		/* allow only the mt312 and stv0299 frontends to access the bus */		if ((msgs[i].addr != 0x0e) && (msgs[i].addr != 0x68) && (msgs[i].addr != 0x61)) {			up(&tmp->i2c_sem);			return -EREMOTEIO;		}	}	// read command	if ((num == 2) && (msgs[0].flags == 0) && (msgs[1].flags == I2C_M_RD) && (msgs[0].buf != NULL) && (msgs[1].buf != NULL)) {		ret = flex_i2c_read(tmp, 0x10000000, msgs[0].addr, msgs[0].buf[0], msgs[1].buf, msgs[1].len);		up(&tmp->i2c_sem);		if (ret != msgs[1].len) {			printk("%s: read error !\n", __FUNCTION__);			for (i = 0; i < 2; i++) {				printk("message %d: flags=0x%x, addr=0x%x, buf=0x%x, len=%d \n", i,				       msgs[i].flags, msgs[i].addr, msgs[i].buf[0], msgs[i].len);			}			return -EREMOTEIO;		}		return num;	}	// write command	for (i = 0; i < num; i++) {		if ((msgs[i].flags != 0) || (msgs[i].buf == NULL) || (msgs[i].len < 2))			return -EINVAL;		ret = flex_i2c_write(tmp, 0x10000000, msgs[i].addr, msgs[i].buf[0], &msgs[i].buf[1], msgs[i].len - 1);		up(&tmp->i2c_sem);		if (ret != msgs[0].len - 1) {			printk("%s: write error %i !\n", __FUNCTION__, ret);			printk("message %d: flags=0x%x, addr=0x%x, buf[0]=0x%x, len=%d \n", i,			       msgs[i].flags, msgs[i].addr, msgs[i].buf[0], msgs[i].len);			return -EREMOTEIO;		}		return num;	}	printk("%s: unknown command format !\n", __FUNCTION__);	return -EINVAL;}/* SRAM (Skystar2 rev2.3 has one "ISSI IS61LV256" chip on board,   but it seems that FlexCopII can work with more than one chip) */static void sram_set_net_dest(struct adapter *adapter, u8 dest){	u32 tmp;	udelay(1000);	tmp = (read_reg_dw(adapter, 0x714) & 0xfffffffc) | (dest & 3);	udelay(1000);	write_reg_dw(adapter, 0x714, tmp);	write_reg_dw(adapter, 0x714, tmp);	udelay(1000);	/*return value is never used? *//*	return tmp; */}static void sram_set_cai_dest(struct adapter *adapter, u8 dest){	u32 tmp;	udelay(1000);	tmp = (read_reg_dw(adapter, 0x714) & 0xfffffff3) | ((dest & 3) << 2);	udelay(1000);	udelay(1000);	write_reg_dw(adapter, 0x714, tmp);	write_reg_dw(adapter, 0x714, tmp);	udelay(1000);	/*return value is never used? *//*	return tmp; */}static void sram_set_cao_dest(struct adapter *adapter, u8 dest){	u32 tmp;	udelay(1000);	tmp = (read_reg_dw(adapter, 0x714) & 0xffffffcf) | ((dest & 3) << 4);	udelay(1000);	udelay(1000);	write_reg_dw(adapter, 0x714, tmp);	write_reg_dw(adapter, 0x714, tmp);	udelay(1000);	/*return value is never used? *//*	return tmp; */}static void sram_set_media_dest(struct adapter *adapter, u8 dest){	u32 tmp;	udelay(1000);	tmp = (read_reg_dw(adapter, 0x714) & 0xffffff3f) | ((dest & 3) << 6);	udelay(1000);	udelay(1000);	write_reg_dw(adapter, 0x714, tmp);	write_reg_dw(adapter, 0x714, tmp);	udelay(1000);	/* return value is never used? *//*	return tmp; */}/* SRAM memory is accessed through a buffer register in the FlexCop   chip (0x700). This register has the following structure:    bits 0-14  : address    bit  15    : read/write flag    bits 16-23 : 8-bit word to write    bits 24-27 : = 4    bits 28-29 : memory bank selector    bit  31    : busy flag*/static void flex_sram_write(struct adapter *adapter, u32 bank, u32 addr, u8 *buf, u32 len){	int i, retries;	u32 command;	for (i = 0; i < len; i++) {		command = bank | addr | 0x04000000 | (*buf << 0x10);		retries = 2;		while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {			mdelay(1);			retries--;		};		if (retries == 0)			printk("%s: SRAM timeout\n", __FUNCTION__);		write_reg_dw(adapter, 0x700, command);		buf++;		addr++;	}}static void flex_sram_read(struct adapter *adapter, u32 bank, u32 addr, u8 *buf, u32 len){	int i, retries;	u32 command, value;	for (i = 0; i < len; i++) {		command = bank | addr | 0x04008000;		retries = 10000;		while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {			mdelay(1);			retries--;		};		if (retries == 0)			printk("%s: SRAM timeout\n", __FUNCTION__);		write_reg_dw(adapter, 0x700, command);		retries = 10000;		while (((read_reg_dw(adapter, 0x700) & 0x80000000) != 0) && (retries > 0)) {			mdelay(1);			retries--;		};		if (retries == 0)			printk("%s: SRAM timeout\n", __FUNCTION__);		value = read_reg_dw(adapter, 0x700) >> 0x10;		*buf = (value & 0xff);		addr++;		buf++;	}}static void sram_write_chunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len){	u32 bank;	bank = 0;	if (adapter->dw_sram_type == 0x20000) {		bank = (addr & 0x18000) << 0x0d;	}	if (adapter->dw_sram_type == 0x00000) {		if ((addr >> 0x0f) == 0)			bank = 0x20000000;		else			bank = 0x10000000;	}	flex_sram_write(adapter, bank, addr & 0x7fff, buf, len);}static void sram_read_chunk(struct adapter *adapter, u32 addr, u8 *buf, u16 len){	u32 bank;	bank = 0;	if (adapter->dw_sram_type == 0x20000) {		bank = (addr & 0x18000) << 0x0d;	}	if (adapter->dw_sram_type == 0x00000) {		if ((addr >> 0x0f) == 0)			bank = 0x20000000;		else			bank = 0x10000000;	}	flex_sram_read(adapter, bank, addr & 0x7fff, buf, len);}static void sram_read(struct adapter *adapter, u32 addr, u8 *buf, u32 len){	u32 length;	while (len != 0) {		length = len;		// check if the address range belongs to the same		// 32K memory chip. If not, the data is read from		// one chip at a time.		if ((addr >> 0x0f) != ((addr + len - 1) >> 0x0f)) {			length = (((addr >> 0x0f) + 1) << 0x0f) - addr;		}		sram_read_chunk(adapter, addr, buf, length);		addr = addr + length;		buf = buf + length;		len = len - length;	}}static void sram_write(struct adapter *adapter, u32 addr, u8 *buf, u32 len){	u32 length;	while (len != 0) {		length = len;		// check if the address range belongs to the same		// 32K memory chip. If not, the data is written to		// one chip at a time.		if ((addr >> 0x0f) != ((addr + len - 1) >> 0x0f)) {			length = (((addr >> 0x0f) + 1) << 0x0f) - addr;		}		sram_write_chunk(adapter, addr, buf, length);		addr = addr + length;		buf = buf + length;		len = len - length;	}}static void sram_set_size(struct adapter *adapter, u32 mask){	write_reg_dw(adapter, 0x71c, (mask | (~0x30000 & read_reg_dw(adapter, 0x71c))));}static void sram_init(struct adapter *adapter){

⌨️ 快捷键说明

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