summaryrefslogtreecommitdiff
path: root/linux/drivers/media/dvb/b2c2
diff options
context:
space:
mode:
authorHolger Waechtler <devnull@localhost>2003-12-04 19:15:49 +0000
committerHolger Waechtler <devnull@localhost>2003-12-04 19:15:49 +0000
commit2b17bc52d2eacffa537f7cbbea626e5a48c2d054 (patch)
tree75934acb9eb31c2f27205621d8cf1ad59fa70610 /linux/drivers/media/dvb/b2c2
parentf3e7c1c071288e92cb53c08ec379ccf9a07a4136 (diff)
downloadmediapointer-dvb-s2-2b17bc52d2eacffa537f7cbbea626e5a48c2d054.tar.gz
mediapointer-dvb-s2-2b17bc52d2eacffa537f7cbbea626e5a48c2d054.tar.bz2
update by Niklas Peinecke, Wolfgang This, Vincenzo Di Massa et al.
Diffstat (limited to 'linux/drivers/media/dvb/b2c2')
-rw-r--r--linux/drivers/media/dvb/b2c2/skystar2.c847
1 files changed, 348 insertions, 499 deletions
diff --git a/linux/drivers/media/dvb/b2c2/skystar2.c b/linux/drivers/media/dvb/b2c2/skystar2.c
index a95b0b422..75ce9140f 100644
--- a/linux/drivers/media/dvb/b2c2/skystar2.c
+++ b/linux/drivers/media/dvb/b2c2/skystar2.c
@@ -4,15 +4,16 @@
*
* Copyright (C) 2003 Vadim Catana, skystar@moldova.cc
*
- * FIX: DiSEqC Tone Burst in flexcop_diseqc_ioctl()
+ * FIX: DISEQC Tone Burst in flexcop_diseqc_ioctl()
+ * FIX: FULL soft DiSEqC for skystar2 (rev 193) VP310 equipped
* Vincenzo Di Massa, hawk.it at tiscalinet.it
*
* IMP: Converted to Linux coding style
* Roberto Ragusa, r.ragusa at libero.it
*
- * FIX: FULL soft DiSEqC for skystar2 (rev 193) VP310 equipped
- * Vincenzo Di Massa, hawk.it at tiscalinet.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
@@ -28,7 +29,6 @@
* 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>
@@ -51,11 +51,16 @@
#include "dvb_functions.h"
static int debug = 0;
-#define dprintk(x...) do { if (debug) printk(x); } while (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=1;
#define SIZE_OF_BUF_DMA1 0x3AC00
#define SIZE_OF_BUF_DMA2 0x758
+#define N_HW_FILTERS (6+32)
+#define N_PID_SLOTS 256
+
struct dmaq {
u32 bus_addr;
@@ -100,7 +105,11 @@ struct adapter {
spinlock_t lock;
- u16 pids[0x27];
+ u16 pids[N_HW_FILTERS];
+ u16 pid_list[N_PID_SLOTS];
+ u8 pid_rc[N_PID_SLOTS]; // ref counters for the pids
+ u16 pid_count;
+ int whole_bandwidth;
u32 mac_filter;
};
@@ -224,7 +233,7 @@ static u32 flex_i2c_read(struct adapter * adapter, u32 device, u32 bus, u32 addr
u32 bytes_to_transfer;
u8 *start;
- dprintk("%s:\n", __FUNCTION__);
+ ddprintk("%s:\n", __FUNCTION__);
start = buf;
@@ -253,7 +262,7 @@ static u32 flex_i2c_write(struct adapter * adapter, u32 device, u32 bus, u32 add
u32 bytes_to_transfer;
u8 *start;
- dprintk("%s:\n", __FUNCTION__);
+ ddprintk("%s:\n", __FUNCTION__);
start = buf;
@@ -284,11 +293,11 @@ static int master_xfer(struct dvb_i2c_bus *i2c, const struct i2c_msg *msgs, int
if (down_interruptible(&tmp->i2c_sem))
return -ERESTARTSYS;
- dprintk("%s: %d messages to transfer\n", __FUNCTION__, num);
+ ddprintk("%s: %d messages to transfer\n", __FUNCTION__, num);
for (i = 0; i < num; i++)
{
- dprintk("message %d: flags=0x%x, addr=0x%x, buf=0x%x, len=%d \n", 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 */
@@ -602,13 +611,13 @@ static void sram_init(struct adapter *adapter)
adapter->dw_sram_type = tmp & 0x30000;
- dprintk("%s: dw_sram_type = %x\n", __FUNCTION__, adapter->dw_sram_type);
+ ddprintk("%s: dw_sram_type = %x\n", __FUNCTION__, adapter->dw_sram_type);
} else {
adapter->dw_sram_type = 0x10000;
- dprintk("%s: dw_sram_type = %x\n", __FUNCTION__, adapter->dw_sram_type);
+ ddprintk("%s: dw_sram_type = %x\n", __FUNCTION__, adapter->dw_sram_type);
}
/* return value is never used? */
@@ -933,83 +942,31 @@ static char eeprom_set_mac_addr(struct adapter *adapter, char type, u8 * mac)
*/
/* PID filter */
-static void filter_enable_stream1_filter(struct adapter *adapter, u32 op)
-{
- dprintk("%s: op=%x\n", __FUNCTION__, op);
-
- if (op == 0) {
- write_reg_op(adapter, 0x208, 2, ~0x00000001, 0);
-
- } else {
-
- write_reg_op(adapter, 0x208, 1, 0, 0x00000001);
- }
-}
-static void filter_enable_stream2_filter(struct adapter *adapter, u32 op)
+/* every flexcop has 6 "lower" hw PID filters */
+/* these are enabled by setting bits 0-5 of 0x208 */
+/* we do not check for id>5 here! */
+static void filter_enable_hw_filter(struct adapter *adapter,u8 id,u8 op)
{
- dprintk("%s: op=%x\n", __FUNCTION__, op);
+ u32 mask=( 0x00000001 << id );
- if (op == 0) {
- write_reg_op(adapter, 0x208, 2, ~0x00000002, 0);
-
- } else {
+ dprintk("%s: id=%d op=%d\n", __FUNCTION__, id, op);
- write_reg_op(adapter, 0x208, 1, 0, 0x00000002);
- }
+ if (op == 0) write_reg_op(adapter, 0x208, 2, ~mask, 0);
+ else write_reg_op(adapter, 0x208, 1, 0, mask);
}
-static void filter_enable_pcr_filter(struct adapter *adapter, u32 op)
+/* this sets the PID that should pass the specified filter */
+static void pid_set_hw_pid(struct adapter * adapter,u8 id,u32 pid)
{
- dprintk("%s: op=%x\n", __FUNCTION__, op);
-
- if (op == 0) {
- write_reg_op(adapter, 0x208, 2, ~0x00000004, 0);
+ u32 adr=0x300+((id&6)<<1);
- } else {
+ dprintk("%s: id=%d addr=%x %c pid=%d\n", __FUNCTION__, id, adr, (id&1)? 'h':'l', pid);
- write_reg_op(adapter, 0x208, 1, 0, 0x00000004);
- }
+ if((id&1)==0) write_reg_op(adapter,adr,3,0xffff8000,pid&0x1fff);
+ else write_reg_op(adapter,adr,3,0x8000ffff,(pid&0x1fff)<<16);
}
-static void filter_enable_pmt_filter(struct adapter *adapter, u32 op)
-{
- dprintk("%s: op=%x\n", __FUNCTION__, op);
-
- if (op == 0) {
- write_reg_op(adapter, 0x208, 2, ~0x00000008, 0);
-
- } else {
-
- write_reg_op(adapter, 0x208, 1, 0, 0x00000008);
- }
-}
-
-static void filter_enable_emm_fFilter(struct adapter *adapter, u32 op)
-{
- dprintk("%s: op=%x\n", __FUNCTION__, op);
-
- if (op == 0) {
- write_reg_op(adapter, 0x208, 2, ~0x00000010, 0);
-
- } else {
-
- write_reg_op(adapter, 0x208, 1, 0, 0x00000010);
- }
-}
-
-static void filter_enable_ecm_filter(struct adapter *adapter, u32 op)
-{
- dprintk("%s: op=%x\n", __FUNCTION__, op);
-
- if (op == 0) {
- write_reg_op(adapter, 0x208, 2, ~0x00000020, 0);
-
- } else {
-
- write_reg_op(adapter, 0x208, 1, 0, 0x00000020);
- }
-}
/*
static void filter_enable_null_filter(struct adapter *adapter, u32 op)
@@ -1051,6 +1008,25 @@ static void ctrl_enable_mac(struct adapter *adapter, u32 op)
}
}
+/* select data filter nr. id for setup */
+static void filter_select_data_filter(struct adapter *adapter,u8 id)
+{
+ write_reg_op(adapter,0x310,3,0xffffffe0,id&0x1f);
+}
+
+/* enable data filter; 0: disable, 1: enable */
+static void filter_enable_data_filter(struct adapter *adapter,u8 op)
+{
+ if(op==0) write_reg_op(adapter,0x314,2,0xffff9fff,0);
+ else write_reg_op(adapter,0x314,3,0xffff9fff,0x00004000);
+}
+
+/* set PID for data filter */
+static void pid_set_data_pid(struct adapter *adapter,u32 pid)
+{
+ write_reg_op(adapter,0x314,3,0xffffe000,pid & 0x1fff);
+}
+
static int ca_set_mac_dst_addr_filter(struct adapter *adapter, u8 * mac)
{
u32 tmp1, tmp2;
@@ -1091,29 +1067,6 @@ static void check_null_filter_enable(struct adapter *adapter)
}
*/
-static void init_pids_info(struct adapter *adapter)
-{
- int i;
-
- for (i = 0; i < 0x27; i++)
- adapter->pids[i] = 0x1FFF;
-}
-
-static int check_pid(struct adapter *adapter, u16 pid)
-{
- u32 i;
-
- if (pid == 0x1FFF)
- return 0;
-
- for (i = 0; i < 0x27; i++) {
- if (adapter->pids[i] == pid || adapter->pids[i] == 0x2000)
- return 1;
- }
-
- return 0;
-}
-
static void pid_set_group_pid(struct adapter * adapter, u32 pid)
{
u32 value;
@@ -1142,120 +1095,7 @@ static void pid_set_group_mask(struct adapter * adapter, u32 pid)
/* return value; */
}
-static void pid_set_stream1_pid(struct adapter * adapter, u32 pid)
-{
- u32 value;
-
- dprintk("%s: pid=%x\n", __FUNCTION__, pid);
-
- value = (pid & 0x3FFF) | (read_reg_dw(adapter, 0x300) & 0xFFFFC000);
-
- write_reg_dw(adapter, 0x300, value);
-
- /* return value is never used? */
-/* return value; */
-}
-
-static void pid_set_stream2_pid(struct adapter * adapter, u32 pid)
-{
- u32 value;
-
- dprintk("%s: pid=%x\n", __FUNCTION__, pid);
-
- value = ((pid & 0x3FFF) << 0x10) | (read_reg_dw(adapter, 0x300) & 0xFFFF);
-
- write_reg_dw(adapter, 0x300, value);
-
- /* return value is never used? */
-/* return value; */
-}
-
-static void pid_set_pcr_pid(struct adapter * adapter, u32 pid)
-{
- u32 value;
-
- dprintk("%s: pid=%x\n", __FUNCTION__, pid);
-
- value = (pid & 0x3FFF) | (read_reg_dw(adapter, 0x304) & 0xFFFFC000);
-
- write_reg_dw(adapter, 0x304, value);
-
- /* return value is never used? */
-/* return value; */
-}
-
-static void pid_set_pmt_pid(struct adapter * adapter, u32 pid)
-{
- u32 value;
-
- dprintk("%s: pid=%x\n", __FUNCTION__, pid);
-
- value = ((pid & 0x3FFF) << 0x10) | (read_reg_dw(adapter, 0x304) & 0x3FFF);
-
- write_reg_dw(adapter, 0x304, value);
-
- /* return value is never used? */
-/* return value; */
-}
-
-static void pid_set_emm_pid(struct adapter * adapter, u32 pid)
-{
- u32 value;
-
- dprintk("%s: pid=%x\n", __FUNCTION__, pid);
-
- value = (pid & 0xFFFF) | (read_reg_dw(adapter, 0x308) & 0xFFFF0000);
-
- write_reg_dw(adapter, 0x308, value);
-
- /* return value is never used? */
-/* return value; */
-}
-
-static void pid_set_ecm_pid(struct adapter * adapter, u32 pid)
-{
- u32 value;
-
- dprintk("%s: pid=%x\n", __FUNCTION__, pid);
-
- value = (pid << 0x10) | (read_reg_dw(adapter, 0x308) & 0xFFFF);
-
- write_reg_dw(adapter, 0x308, value);
-
- /* return value is never used? */
-/* return value; */
-}
-
-static int pid_get_stream1_pid(struct adapter * adapter)
-{
- return read_reg_dw(adapter, 0x300) & 0x00001FFF;
-}
-
-static int pid_get_stream2_pid(struct adapter * adapter)
-{
- return (read_reg_dw(adapter, 0x300) >> 0x10)& 0x00001FFF;
-}
-
-static int pid_get_pcr_pid(struct adapter * adapter)
-{
- return read_reg_dw(adapter, 0x304) & 0x00001FFF;
-}
-
-static int pid_get_pmt_pid(struct adapter * adapter)
-{
- return (read_reg_dw(adapter, 0x304) >> 0x10)& 0x00001FFF;
-}
-
-static int pid_get_emm_pid(struct adapter * adapter)
-{
- return read_reg_dw(adapter, 0x308) & 0x00001FFF;
-}
-
-static int pid_get_ecm_pid(struct adapter * adapter)
-{
- return (read_reg_dw(adapter, 0x308) >> 0x10)& 0x00001FFF;
-}
-
+/*
static int pid_get_group_pid(struct adapter * adapter)
{
return read_reg_dw(adapter, 0x30C) & 0x00001FFF;
@@ -1265,6 +1105,7 @@ static int pid_get_group_mask(struct adapter * adapter)
{
return (read_reg_dw(adapter, 0x30C) >> 0x10)& 0x00001FFF;
}
+*/
/*
static void reset_hardware_pid_filter(struct adapter *adapter)
@@ -1284,10 +1125,29 @@ static void reset_hardware_pid_filter(struct adapter *adapter)
filter_enable_ecm_filter(adapter, 0);
pid_set_emm_pid(adapter, 0x1FFF);
- filter_enable_emm_fFilter(adapter, 0);
+ filter_enable_emm_filter(adapter, 0);
}
*/
+static void init_pids(struct adapter *adapter)
+{
+ int i;
+
+ for (i = 0; i < N_HW_FILTERS; i++)
+ adapter->pids[i] = 0x1FFF;
+ adapter->pid_count=0;
+ adapter->whole_bandwidth = 0;
+
+ pid_set_group_pid(adapter, 0);
+ pid_set_group_mask(adapter, 0x1FE0);
+ pid_set_hw_pid(adapter,0,0x1FFF);
+ pid_set_hw_pid(adapter,1,0x1FFF);
+ pid_set_hw_pid(adapter,2,0x1FFF);
+ pid_set_hw_pid(adapter,3,0x1FFF);
+ pid_set_hw_pid(adapter,4,0x1FFF);
+ pid_set_hw_pid(adapter,5,0x1FFF);
+}
+
static void open_whole_bandwidth(struct adapter *adapter)
{
dprintk("%s:\n", __FUNCTION__);
@@ -1297,175 +1157,167 @@ static void open_whole_bandwidth(struct adapter *adapter)
pid_set_group_mask(adapter, 0);
filter_enable_mask_filter(adapter, 1);
-
}
-static int add_hw_pid(struct adapter *adapter, u32 pid)
+static void close_whole_bandwidth(struct adapter *adapter)
{
- dprintk("%s: pid=%d\n", __FUNCTION__, pid);
-
- if (pid <= 0x1F)
- return 1;
-
- if ((pid_get_group_mask(adapter) == 0) && (pid_get_group_pid(adapter) == 0))
- return 0;
-
- if (pid_get_stream1_pid(adapter) == 0x1FFF) {
- pid_set_stream1_pid(adapter, pid & 0xFFFF);
-
- filter_enable_stream1_filter(adapter, 1);
-
- return 1;
- }
-
- if (pid_get_stream2_pid(adapter) == 0x1FFF) {
- pid_set_stream2_pid(adapter, (pid & 0xFFFF));
-
- filter_enable_stream2_filter(adapter, 1);
-
- return 1;
- }
-
- if (pid_get_pcr_pid(adapter) == 0x1FFF) {
- pid_set_pcr_pid(adapter, (pid & 0xFFFF));
-
- filter_enable_pcr_filter(adapter, 1);
-
- return 1;
- }
-
- if ((pid_get_pmt_pid(adapter) & 0x1FFF) == 0x1FFF) {
- pid_set_pmt_pid(adapter, (pid & 0xFFFF));
-
- filter_enable_pmt_filter(adapter, 1);
-
- return 1;
- }
-
- if ((pid_get_emm_pid(adapter) & 0x1FFF) == 0x1FFF) {
- pid_set_emm_pid(adapter, (pid & 0xFFFF));
-
- filter_enable_emm_fFilter(adapter, 1);
-
- return 1;
- }
+ dprintk("%s:\n", __FUNCTION__);
+
+ pid_set_group_pid(adapter, 0);
- if ((pid_get_ecm_pid(adapter) & 0x1FFF) == 0x1FFF) {
- pid_set_ecm_pid(adapter, (pid & 0xFFFF));
+ pid_set_group_mask(adapter, 0x1fe0);
- filter_enable_ecm_filter(adapter, 1);
+ filter_enable_mask_filter(adapter, 1);
+}
- return 1;
+/* this tries to add the specified PID to be let through the
+ hw filters. return 1 on success.
+ if this cannot be done (all filter in use), returns -1
+ for PID <= 0x1f there is always success reported, since
+ these are let through by the group filters anyway. */
+static int add_hw_pid(struct adapter *adapter, u32 pid)
+{
+ int num,i;
+
+ if(pid<=0x1f) return 1;
+
+ if(adapter->b2c2_revision==0xc0 || adapter->b2c2_revision==0xc3)
+ num=38; // FlexCop IIb & III have 6+32 hw filters
+ else num=6; // FlexCop II has 6 hw filters, every other should have at least 6
+
+ for (i=0; i<num; i++) {
+ if (adapter->pids[i] == 0x1fff) { // find a free pid slot
+ adapter->pids[i]=pid;
+ if(i<6) {
+ pid_set_hw_pid(adapter,i,pid);
+ filter_enable_hw_filter(adapter,i,1);
+ return 1;
+ } else {
+ filter_select_data_filter(adapter,i-6);
+ pid_set_data_pid(adapter,pid);
+ filter_enable_data_filter(adapter,1);
+ return 1;
+ }
+ }
}
-
return -1;
}
+/* returns -1 if the pid was not present in the filters */
static int remove_hw_pid(struct adapter *adapter, u32 pid)
{
- dprintk("%s: pid=%d\n", __FUNCTION__, pid);
-
- if (pid <= 0x1F)
- return 1;
-
- if (pid_get_stream1_pid(adapter) == pid) {
- pid_set_stream1_pid(adapter, 0x1FFF);
-
- return 1;
- }
-
- if (pid_get_stream2_pid(adapter) == pid) {
- pid_set_stream2_pid(adapter, 0x1FFF);
-
- filter_enable_stream2_filter(adapter, 0);
-
- return 1;
- }
-
- if (pid_get_pcr_pid(adapter) == pid) {
- pid_set_pcr_pid(adapter, 0x1FFF);
-
- filter_enable_pcr_filter(adapter, 0);
-
- return 1;
- }
-
- if (pid_get_pmt_pid(adapter) == pid) {
- pid_set_pmt_pid(adapter, 0x1FFF);
-
- filter_enable_pmt_filter(adapter, 0);
-
- return 1;
- }
-
- if (pid_get_emm_pid(adapter) == pid) {
- pid_set_emm_pid(adapter, 0x1FFF);
-
- filter_enable_emm_fFilter(adapter, 0);
-
- return 1;
- }
-
- if (pid_get_ecm_pid(adapter) == pid) {
- pid_set_ecm_pid(adapter, 0x1FFF);
-
- filter_enable_ecm_filter(adapter, 0);
-
- return 1;
+ int num,i;
+
+ if(pid<=0x1f) return 1;
+
+ if(adapter->b2c2_revision==0xc0 || adapter->b2c2_revision==0xc3)
+ num=38; // FlexCop IIb & III have 6+32 hw filters
+ else num=6; // FlexCop II has 6 hw filters, every other should have at least 6
+
+ for(i=0; i<num; i++) {
+ if (adapter->pids[i] == pid) { // find the pid slot
+ adapter->pids[i]=0x1fff;
+ if(i<6) {
+ pid_set_hw_pid(adapter,i,pid);
+ filter_enable_hw_filter(adapter,i,0);
+ return 1;
+ } else {
+ filter_select_data_filter(adapter,i-6);
+ pid_set_data_pid(adapter,pid);
+ filter_enable_data_filter(adapter,0);
+ return 1;
+ }
+ }
}
-
return -1;
}
-static int add_pid(struct adapter *adapter, u32 pid)
+/* Adds a PID to the filters.
+ If there are no more hw filters available, open the whole
+ ts stream to pass by.
+ Adding a pid more than once has no effect.
+ If pid==0x2000, open whole ts stream also.
+ Returns 1 on success, -1 on error */
+static int add_pid(struct adapter *adapter,u32 pid)
{
int i;
-
+
dprintk("%s: pid=%d\n", __FUNCTION__, pid);
-
- if (pid > 0x1FFE && pid != 0x2000)
- return -1;
-
- if (check_pid(adapter, pid) == 1)
+
+ if(pid==0x2000) {
+ if (adapter->whole_bandwidth == 0)
+ open_whole_bandwidth(adapter);
+ ++adapter->whole_bandwidth;
return 1;
-
- for (i = 0; i < 0x27; i++) {
- if (adapter->pids[i] == 0x1FFF) // find free pid filter
- {
- adapter->pids[i] = pid;
-
- if (pid == 0x2000 || add_hw_pid(adapter, pid) < 0)
- open_whole_bandwidth(adapter);
-
+ }
+
+ if (pid > 0x1ffe) return -1;
+
+ // check if the pid is already present
+ for(i=0; i<adapter->pid_count; i++)
+ if(adapter->pid_list[i]==pid) {
+ adapter->pid_rc[i]++; // increment ref counter
return 1;
}
+
+ if(adapter->pid_count==N_PID_SLOTS) return -1; // no more pids can be added
+ adapter->pid_list[adapter->pid_count]=pid; // register pid
+ adapter->pid_rc[adapter->pid_count]=1;
+ adapter->pid_count++;
+
+ // setup a filter for the pid
+ // if there are no filters left, let the whole ts pass
+ if (add_hw_pid(adapter,pid)==-1) {
+ if (adapter->whole_bandwidth == 0)
+ open_whole_bandwidth(adapter);
+ adapter->whole_bandwidth++;
}
-
- return -1;
+
+ return 1;
}
+/* Removes a PID from the filters. */
static int remove_pid(struct adapter *adapter, u32 pid)
{
- u32 i;
-
- dprintk("%s: pid=%d\n", __FUNCTION__, pid);
-
- if (pid > 0x1FFE)
- return -1;
-
- for (i = 0; i < 0x27; i++) {
- if (adapter->pids[i] == pid) {
- adapter->pids[i] = 0x1FFF;
-
- remove_hw_pid(adapter, pid);
+ int i,j;
+
+ if (pid==0x2000) {
+ if (adapter->whole_bandwidth <= 0) return -1; // cannot remove a pid that was not added ;)
+ adapter->whole_bandwidth--;
+ if (adapter->whole_bandwidth == 0)
+ close_whole_bandwidth(adapter);
+ return 1;
+ }
+
+ if (pid > 0x1ffe && pid != 0x2000) return -1;
+
+ // check if the pid is present
+ for (i=0; i<adapter->pid_count; i++) {
+ if(adapter->pid_list[i]==pid) {
+ adapter->pid_rc[i]--;
+ if(adapter->pid_rc[i]<=0) {
+ // remove from the list
+ adapter->pid_count--;
+ for(j=i; j<adapter->pid_count; j++) {
+ adapter->pid_list[j]=adapter->pid_list[j+1];
+ adapter->pid_rc[j]=adapter->pid_rc[j+1];
+ }
+ // close filter and take care to reverse the effect of open_whole_bandwidth
+ if (remove_hw_pid(adapter,pid)==-1) {
+ if (adapter->whole_bandwidth > 0)
+ --adapter->whole_bandwidth;
+ if (adapter->whole_bandwidth == 0)
+ close_whole_bandwidth(adapter);
+ }
+ }
return 1;
}
}
-
return -1;
}
+
/* dma & irq */
static void ctrl_enable_smc(struct adapter *adapter, u32 op)
{
@@ -1745,7 +1597,12 @@ static void open_stream(struct adapter *adapter, u32 pid)
filter_enable_mask_filter(adapter, 1);
- add_pid(adapter, pid);
+ if(enable_hw_filters==1) add_pid(adapter, pid);
+ else {
+ if (adapter->whole_bandwidth == 0)
+ open_whole_bandwidth(adapter);
+ adapter->whole_bandwidth++;
+ }
dprintk("%s: adapter->dma_status=%x\n", __FUNCTION__, adapter->dma_status);
@@ -1795,7 +1652,15 @@ static void close_stream(struct adapter *adapter, u32 pid)
dma_start_stop0x2102(adapter, dma_mask, 0);
}
}
- remove_pid(adapter, pid);
+ if (enable_hw_filters==1)
+ remove_pid(adapter, pid);
+ else {
+ if (adapter->whole_bandwidth > 0) {
+ adapter->whole_bandwidth--;
+ if (adapter->whole_bandwidth == 0)
+ close_whole_bandwidth(adapter);
+ }
+ }
}
static void interrupt_service_dma1(struct adapter *adapter)
@@ -1827,9 +1692,9 @@ static void interrupt_service_dma1(struct adapter *adapter)
n_num_new_bytes_transferred = (adapter->dmaq1.buffer_size - adapter->dmaq1.tail) + n_cur_dma_counter;
}
- dprintk("%s: n_cur_dma_counter = %d\n" , __FUNCTION__, n_cur_dma_counter);
- dprintk("%s: dmaq1.tail = %d\n" , __FUNCTION__, adapter->dmaq1.tail);
- dprintk("%s: bytes_transferred = %d\n" , __FUNCTION__, n_num_new_bytes_transferred);
+ ddprintk("%s: n_cur_dma_counter = %d\n" , __FUNCTION__, n_cur_dma_counter);
+ ddprintk("%s: dmaq1.tail = %d\n" , __FUNCTION__, adapter->dmaq1.tail);
+ ddprintk("%s: bytes_transferred = %d\n" , __FUNCTION__, n_num_new_bytes_transferred);
if (n_num_new_bytes_transferred < dw_default_packet_size)
return;
@@ -1871,7 +1736,7 @@ static irqreturn_t isr(int irq, void *dev_id, struct pt_regs *regs)
u32 value;
- dprintk("%s:\n", __FUNCTION__);
+ ddprintk("%s:\n", __FUNCTION__);
spin_lock_irq(&tmp->lock);
@@ -1915,7 +1780,7 @@ static void init_dma_queue(struct adapter *adapter)
adapter->dma_status = adapter->dma_status | 0x10000000;
- dprintk("%s: allocated dma buffer at 0x%p, length=%d\n", __FUNCTION__, adapter->dmaq1.buffer, SIZE_OF_BUF_DMA1);
+ ddprintk("%s: allocated dma buffer at 0x%p, length=%d\n", __FUNCTION__, adapter->dmaq1.buffer, SIZE_OF_BUF_DMA1);
} else {
@@ -1941,7 +1806,7 @@ static void init_dma_queue(struct adapter *adapter)
adapter->dma_status = adapter->dma_status | 0x20000000;
- dprintk("%s: allocated dma buffer at 0x%p, length=%d\n", __FUNCTION__, adapter->dmaq2.buffer, (int) SIZE_OF_BUF_DMA2);
+ ddprintk("%s: allocated dma buffer at 0x%p, length=%d\n", __FUNCTION__, adapter->dmaq2.buffer, (int) SIZE_OF_BUF_DMA2);
} else {
@@ -2080,16 +1945,7 @@ static int driver_initialize(struct pci_dev * pdev)
write_reg_dw(adapter, 0x210, 0xB2FF);
write_reg_dw(adapter, 0x208, 0x40);
- init_pids_info(adapter);
-
- pid_set_group_pid(adapter, 0);
- pid_set_group_mask(adapter, 0x1FE0);
- pid_set_stream1_pid(adapter, 0x1FFF);
- pid_set_stream2_pid(adapter, 0x1FFF);
- pid_set_pmt_pid(adapter, 0x1FFF);
- pid_set_pcr_pid(adapter, 0x1FFF);
- pid_set_ecm_pid(adapter, 0x1FFF);
- pid_set_emm_pid(adapter, 0x1FFF);
+ init_pids(adapter);
init_dma_queue(adapter);
@@ -2101,25 +1957,25 @@ static int driver_initialize(struct pci_dev * pdev)
adapter->b2c2_revision = (read_reg_dw(adapter, 0x204) >> 0x18);
- switch(adapter->b2c2_revision) {
- case 0x82:
- printk("%s: FlexCopII(rev.130) chip found\n", __FILE__);
- break;
- case 0xC3:
- printk("%s: FlexCopIIB(rev.195) chip found\n", __FILE__);
- break;
- case 0xC0:
- printk("%s: FlexCopIII(rev.192) chip found\n", __FILE__);
- break;
- default:
- printk("%s: The revision of the FlexCop chip on your card is %d\n", __FILE__, adapter->b2c2_revision);
- printk("%s: This driver works only with FlexCopII(rev.130), FlexCopIIB(rev.195) and FlexCopIII(rev. 192).\n", __FILE__);
- free_adapter_object(adapter);
- pci_set_drvdata(pdev, NULL);
- release_region(pci_resource_start(pdev,1), pci_resource_len(pdev,1));
- release_mem_region(pci_resource_start(pdev,0), pci_resource_len(pdev,0));
- return -ENODEV;
- }
+ switch(adapter->b2c2_revision) {
+ case 0x82:
+ printk("%s: FlexCopII(rev.130) chip found\n", __FILE__);
+ break;
+ case 0xC3:
+ printk("%s: FlexCopIIB(rev.195) chip found\n", __FILE__);
+ break;
+ case 0xC0:
+ printk("%s: FlexCopIII(rev.192) chip found\n", __FILE__);
+ break;
+ default:
+ printk("%s: The revision of the FlexCop chip on your card is %d\n", __FILE__, adapter->b2c2_revision);
+ printk("%s: This driver works only with FlexCopII(rev.130), FlexCopIIB(rev.195) and FlexCopIII(rev. 192).\n", __FILE__);
+ free_adapter_object(adapter);
+ pci_set_drvdata(pdev, NULL);
+ release_region(pci_resource_start(pdev,1), pci_resource_len(pdev,1));
+ release_mem_region(pci_resource_start(pdev,0), pci_resource_len(pdev,0));
+ return -ENODEV;
+ }
tmp = read_reg_dw(adapter, 0x204);
@@ -2265,147 +2121,138 @@ static void set_tuner_polarity(struct adapter *adapter, u8 polarity)
write_reg_dw(adapter, 0x204, var);
}
-static void diseqc_send_bit (struct adapter *adapter, int data)
+static int flexcop_diseqc_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg)
{
- set_tuner_tone(adapter, 1);
- udelay(data ? 500 : 1000);
- set_tuner_tone(adapter, 0);
- udelay(data ? 1000 : 500);
-}
+ struct adapter *adapter = fe->before_after_data;
+ struct dvb_frontend_info info;
+
+ switch (cmd) {
+
+ case FE_DISEQC_SEND_BURST:
+ {
+ u8 count;
+ fe_sec_mini_cmd_t b = (fe_sec_mini_cmd_t) arg;
+ dprintk("%s: FE_SEND_BURST ", __FUNCTION__);
+ switch ( b )
+ {
+ case SEC_MINI_A:
+ {
+ dprintk("SEC_MINI_A\n");
+ set_tuner_tone(adapter, 1); // This lines are needed
+ udelay(500*25); // to do a down-step
+ set_tuner_tone(adapter, 0);
+ udelay(500*25);
+ break;
+ }
+ case SEC_MINI_B:
+ {
+ dprintk("SEC_MINI_B\n");
+ set_tuner_tone(adapter, 0);
+ udelay(1000*15);
+ for (count=0;count<9; count++)
+ {
+ set_tuner_tone(adapter, 1);
+ udelay(500);
+ set_tuner_tone(adapter, 0);
+ udelay(1000);
+ }
+ udelay(1000*15);
+ break;
+ }
+ default:
+ break;
+ };
+ return 0;
+ }
+
-static void diseqc_send_byte (struct adapter *adapter, int data)
-{
- int i, par=1, d;
+ case FE_SLEEP:
+ {
+ dprintk("%s: FE_SLEEP\n", __FUNCTION__);
- for (i=7; i>=0; i--) {
- d = (data>>i)&1;
- par ^= d;
- diseqc_send_bit(adapter, d);
- }
+ set_tuner_polarity(adapter, 0);
- diseqc_send_bit(adapter, par);
-}
+ // return -EOPNOTSUPP, to make DVB core also send "FE_SLEEP" command to frontend.
+ return -EOPNOTSUPP;
+ }
+ case FE_SET_VOLTAGE:
+ {
+ dprintk("%s: FE_SET_VOLTAGE\n", __FUNCTION__);
-static int send_diseqc_msg (struct adapter *adapter, int len, u8 *msg, unsigned long burst)
-{
- int i;
+ switch ((fe_sec_voltage_t) arg)
+ {
+ case SEC_VOLTAGE_13:
- set_tuner_tone(adapter, 0);
- mdelay(16);
+ dprintk("%s: SEC_VOLTAGE_13, %x\n", __FUNCTION__, SEC_VOLTAGE_13);
- for (i=0; i<len; i++)
- diseqc_send_byte(adapter, msg[i]);
+ set_tuner_polarity(adapter, 1);
- mdelay(16);
+ return 0;
- if (burst!=-1) {
- if (burst)
- diseqc_send_byte(adapter, 0xff);
- else {
- set_tuner_tone(adapter, 1);
- udelay(12500);
- set_tuner_tone(adapter, 0);
- }
- dvb_delay(20);
- }
+ case SEC_VOLTAGE_18:
- return 0;
-}
+ dprintk("%s: SEC_VOLTAGE_18, %x\n", __FUNCTION__, SEC_VOLTAGE_18);
+ set_tuner_polarity(adapter, 2);
-int soft_diseqc (struct adapter *adapter, unsigned int cmd, void *arg)
-{
- switch (cmd) {
- case FE_SET_TONE:
- switch ((fe_sec_tone_mode_t) arg) {
- case SEC_TONE_ON:
- set_tuner_tone(adapter, 1);
- break;
- case SEC_TONE_OFF:
- set_tuner_tone(adapter, 0);
- break;
- default:
- return -EINVAL;
- };
- break;
-
- case FE_DISEQC_SEND_MASTER_CMD:
- {
- struct dvb_diseqc_master_cmd *cmd = arg;
-
- send_diseqc_msg (adapter, cmd->msg_len, cmd->msg, 0);
- break;
- }
+ return 0;
- case FE_DISEQC_SEND_BURST:
- send_diseqc_msg (adapter, 0, NULL, (unsigned long)arg);
- break;
+ default:
- default:
- return -EOPNOTSUPP;
- };
+ return -EINVAL;
+ };
- return 0;
-}
+ }
-static int flexcop_diseqc_ioctl(struct dvb_frontend *fe, unsigned int cmd, void *arg)
-{
- struct adapter *adapter = fe->before_after_data;
+ case FE_SET_TONE:
+ {
+ dprintk("%s: FE_SET_TONE\n", __FUNCTION__);
- struct dvb_frontend_info info;
-
- fe->ioctl(fe, FE_GET_INFO, &info);
+ fe->ioctl(fe, FE_GET_INFO, &info);
- // we must use different DiSEqC hw
-
- if ( strcmp(info.name, "Zarlink MT312") == 0){
- //VP310 using mt312 driver for tuning only: diseqc not wired
- //use FCII instead
- if (!soft_diseqc(adapter,cmd,arg))
- return 0;
- }
-
- switch (cmd) {
- case FE_SLEEP:
- {
- dprintk("%s: FE_SLEEP\n", __FUNCTION__);
+ if ( strcmp(info.name, "Zarlink MT312") == 0)
+ {
+ dprintk("%s: FE_SET_TONE for %s frontend\n", __FUNCTION__, info.name);
- set_tuner_polarity(adapter, 0);
+ switch ((fe_sec_tone_mode_t) arg)
+ {
+ case SEC_TONE_ON:
- // return -EOPNOTSUPP, to make DVB core also send "FE_SLEEP" command to frontend.
- return -EOPNOTSUPP;
- }
+ dprintk("%s: SEC_TONE_ON, %x\n", __FUNCTION__, SEC_TONE_ON);
- case FE_SET_VOLTAGE:
- {
- dprintk("%s: FE_SET_VOLTAGE\n", __FUNCTION__);
+ set_tuner_tone(adapter, 1);
- switch ((fe_sec_voltage_t) arg)
- {
- case SEC_VOLTAGE_13:
+ return 0;
- dprintk("%s: SEC_VOLTAGE_13, %x\n", __FUNCTION__, SEC_VOLTAGE_13);
+ case SEC_TONE_OFF:
- set_tuner_polarity(adapter, 1);
+ dprintk("%s: SEC_TONE_OFF, %x\n", __FUNCTION__, SEC_TONE_OFF);
- return 0;
+ set_tuner_tone(adapter, 0);
- case SEC_VOLTAGE_18:
+ return 0;
- dprintk("%s: SEC_VOLTAGE_18, %x\n", __FUNCTION__, SEC_VOLTAGE_18);
+ default:
- set_tuner_polarity(adapter, 2);
+ return -EINVAL;
+ };
- return 0;
+ };
+
+ if ( strcmp(info.name, "STV0299/TSA5059/SL1935 based") == 0)
+ {
+ dprintk("%s: FE_SET_TONE for %s frontend\n", __FUNCTION__, info.name);
- default:
+ /* allow the frontend driver to handle this command*/
+ return -EOPNOTSUPP;
+ };
- return -EINVAL;
- };
- }
+ printk("%s: FE_SET_TONE unknown frontend : %s\n", __FUNCTION__, info.name);
+ return -EINVAL;
+ }
default:
@@ -2456,8 +2303,8 @@ static int skystar2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
dvbdemux = &adapter->demux;
dvbdemux->priv = (void *) adapter;
- dvbdemux->filternum = 256;
- dvbdemux->feednum = 256;
+ dvbdemux->filternum = N_PID_SLOTS;
+ dvbdemux->feednum = N_PID_SLOTS;
dvbdemux->start_feed = dvb_start_feed;
dvbdemux->stop_feed = dvb_stop_feed;
dvbdemux->write_to_decoder = 0;
@@ -2551,7 +2398,9 @@ module_init(skystar2_init);
module_exit(skystar2_cleanup);
MODULE_PARM(debug,"i");
-MODULE_PARM_DESC(debug, "enable verbose debug messages");
+MODULE_PARM_DESC(debug, "enable verbose debug messages: supported values: 1 and 2");
+MODULE_PARM(enable_hw_filters,"i");
+MODULE_PARM_DESC(enable_hw_filters, "enable hardware filters, if disabled the whole ts is passed through");
MODULE_DESCRIPTION("Technisat SkyStar2 DVB PCI Driver");
MODULE_LICENSE("GPL");