Hi Niklas,

your patch looks fine to me, and IMHO should be added to cvs.

I'll attach a patch against cvs with a few changes:
- I corrected a wrong adapter variable name
- I added a few lines for enable_hw_filters=0
- I removed my name from the file, because I don't think I contributed much.

Many thanks for your nice work :-)
And of course many thanks to Vladim for his great work.


Wolfgang

--- dvb-kernel/linux/drivers/media/dvb/b2c2/skystar2.c.orig     2003-12-04 
17:53:17.000000000 +0000
+++ dvb-kernel/linux/drivers/media/dvb/b2c2/skystar2.c  2003-12-04 17:55:39.000000000 
+0000
@@ -4,15 +4,16 @@
  *
  * Copyright (C) 2003  Vadim Catana, [EMAIL PROTECTED]
  *
- * 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 @@
 
        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 @@
        u32 bytes_to_transfer;
        u8 *start;
 
-       dprintk("%s:\n", __FUNCTION__);
+       ddprintk("%s:\n", __FUNCTION__);
 
        start = buf;
 
@@ -253,7 +262,7 @@
        u32 bytes_to_transfer;
        u8 *start;
 
-       dprintk("%s:\n", __FUNCTION__);
+       ddprintk("%s:\n", __FUNCTION__);
 
        start = buf;
 
@@ -284,11 +293,11 @@
        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 @@
 
                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 @@
 */
 
 /* 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 @@
        }
 }
 
+/* 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 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 @@
 /*     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 @@
 {
        return (read_reg_dw(adapter, 0x30C) >> 0x10)& 0x00001FFF;
 }
+*/
 
 /*
 static void reset_hardware_pid_filter(struct adapter *adapter)
@@ -1284,10 +1125,29 @@
        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 @@
        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 @@
 
        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 @@
                        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 @@
                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 @@
 
        u32 value;
 
-       dprintk("%s:\n", __FUNCTION__);
+       ddprintk("%s:\n", __FUNCTION__);
 
        spin_lock_irq(&tmp->lock);
 
@@ -1915,7 +1780,7 @@
 
                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 @@
 
                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 @@
        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 @@
 
        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 @@
        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;
+           }
+       
 
+           case FE_SLEEP:
+           {
+               dprintk("%s: FE_SLEEP\n", __FUNCTION__);
 
-static void diseqc_send_byte (struct adapter *adapter, int data)
-{
-       int i, par=1, d;
+               set_tuner_polarity(adapter, 0);
 
-       for (i=7; i>=0; i--) {
-               d = (data>>i)&1;
-               par ^= d;
-               diseqc_send_bit(adapter, d);
-       }
+               // return -EOPNOTSUPP, to make DVB core also send "FE_SLEEP" command 
to frontend.
+               return -EOPNOTSUPP;
+           }
 
-       diseqc_send_bit(adapter, par);
-}
+           case FE_SET_VOLTAGE:
+           {
+               dprintk("%s: FE_SET_VOLTAGE\n", __FUNCTION__);
 
+               switch ((fe_sec_voltage_t) arg)
+               {
+                       case SEC_VOLTAGE_13:
 
-static int send_diseqc_msg (struct adapter *adapter, int len, u8 *msg, unsigned long 
burst)
-{
-       int i;
+                               dprintk("%s: SEC_VOLTAGE_13, %x\n", __FUNCTION__, 
SEC_VOLTAGE_13);
 
-       set_tuner_tone(adapter, 0);
-       mdelay(16);
+                               set_tuner_polarity(adapter, 1);
 
-       for (i=0; i<len; i++)
-               diseqc_send_byte(adapter, msg[i]);
+                               return 0;
 
-       mdelay(16);
+                       case SEC_VOLTAGE_18:
 
-       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);
-       }
+                               dprintk("%s: SEC_VOLTAGE_18, %x\n", __FUNCTION__, 
SEC_VOLTAGE_18);
 
-       return 0;
-}
+                               set_tuner_polarity(adapter, 2);
 
+                               return 0;
 
-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;
-               }
-
-               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 @@
        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_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");

Reply via email to