Mailing List archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[linux-dvb] new. perfect fidbirq()



HI All

Today I was watching the breaking news on a different 
computer with budget card... From packet loss and artefacts 
I couldn't follow what's going on, so I said "enough is enough".

It was all because of the improper coding logic
in fidbirq(). Even the recently modified fidbirq() 
by Marian couldn't cope with heavy loaded PCI latency.

So I remembered a discussion with Roberto Deza about
fidbirq() that was almost forgotten...

I took the paper and have rewritten fidbirq() 
from scrach, having in mind triggering on both edges,
recovery from lost interrupt and the trust in 7146 dma 
pointer given the proper pointer arithmetic.

The result is absolutely astonishing: ZERO PACKET LOSS.
(patch and complete the fidbirq attached)

I recommend you all to try this new fidbirq(), and
also to apply it to the dvb-kernel.

Best regards, Emard
static
void fidbirq (unsigned long data)
{
	struct budget_s *budget = (struct budget_s*) data;
	u8 *mem=(u8 *)(budget->grabbing);
//	int field=0x80 & saa7146_read(budget->dev, PSR);
	u16 oldblk = budget->ttbp;
	u16 newblk = saa7146_read(budget->dev, PCI_VDP3)/188; /* PCI_VDP3 = 0..TS_BUFLEN-1 */
	u8 *olddma = mem + oldblk*188;
	u8 *newdma = mem + newblk*188; /* rounded to last complete packet */

	DEB_EE(("budget: %p\n",budget));
	
	/* Zero-Packet-Loss fidbirq by EMARD */

	budget->ttbp = newblk;
	
	/* exit immediately when the card is not set for feeding
	** or when values are out of expected boundaries
	*/
	if(budget->feeding == 0 ||
		oldblk >= TS_BUFLEN/188 || newblk >= TS_BUFLEN/188)
		return;

	if(oldblk < newblk) /* no wraparound - dump in one chunk */
		if(*olddma == 0x47)
			dvb_dmx_swfilter_packets(&budget->demux, olddma,
				newblk-oldblk);
	
	if(oldblk > newblk) /* wraparound - dump in two chunks */
	{
		/* dump from olddma to end of dma window */
		if(*olddma == 0x47)
			dvb_dmx_swfilter_packets(&budget->demux, olddma,
				TS_BUFLEN/188 - oldblk);
		/* dump from begin of dma window to newdma */
		if(*mem == 0x47)
			dvb_dmx_swfilter_packets(&budget->demux, mem,
				newblk);
	}			
}
diff -pur orig/dvb-kernel/linux/drivers/media/dvb/ttpci-budget/budget-core.c dvb-kernel/linux/drivers/media/dvb/ttpci-budget/budget-core.c
--- orig/dvb-kernel/linux/drivers/media/dvb/ttpci-budget/budget-core.c	Thu Jan 23 20:00:03 2003
+++ dvb-kernel/linux/drivers/media/dvb/ttpci-budget/budget-core.c	Sun Feb  2 00:21:30 2003
@@ -110,27 +110,41 @@ void fidbirq (unsigned long data)
 {
 	struct budget_s *budget = (struct budget_s*) data;
 	u8 *mem=(u8 *)(budget->grabbing);
-	int num=512;
-	int field=0x80 & saa7146_read(budget->dev, PSR);
+//	int field=0x80 & saa7146_read(budget->dev, PSR);
+	u16 oldblk = budget->ttbp;
+	u16 newblk = saa7146_read(budget->dev, PCI_VDP3)/188; /* PCI_VDP3 = 0..TS_BUFLEN-1 */
+	u8 *olddma = mem + oldblk*188;
+	u8 *newdma = mem + newblk*188; /* rounded to last complete packet */
 
 	DEB_EE(("budget: %p\n",budget));
+	
+	/* Zero-Packet-Loss fidbirq by EMARD */
 
-	if (field) {
-		if (field==budget->tsf)
-			num=1024;
-		else
-			mem+=TS_BUFLEN/2;
-	} else {
-		if (field==budget->tsf) {
-			if (budget->feeding && mem[TS_BUFLEN/2]==0x47)
-				dvb_dmx_swfilter_packets(&budget->demux, 
-				    mem+TS_BUFLEN/2, 512 );
-		}
-	}
+	budget->ttbp = newblk;
+	
+	/* exit immediately when the card is not set for feeding
+	** or when values are out of expected boundaries
+	*/
+	if(budget->feeding == 0 ||
+		oldblk >= TS_BUFLEN/188 || newblk >= TS_BUFLEN/188)
+		return;
 
-	budget->tsf=field;
-	if (budget->feeding && mem[0]==0x47)
-		dvb_dmx_swfilter_packets(&budget->demux, mem, num);
+	if(oldblk < newblk) /* no wraparound - dump in one chunk */
+		if(*olddma == 0x47)
+			dvb_dmx_swfilter_packets(&budget->demux, olddma,
+				newblk-oldblk);
+	
+	if(oldblk > newblk) /* wraparound - dump in two chunks */
+	{
+		/* dump from olddma to end of dma window */
+		if(*olddma == 0x47)
+			dvb_dmx_swfilter_packets(&budget->demux, olddma,
+				TS_BUFLEN/188 - oldblk);
+		/* dump from begin of dma window to newdma */
+		if(*mem == 0x47)
+			dvb_dmx_swfilter_packets(&budget->demux, mem,
+				newblk);
+	}			
 }
 
 inline static void 
diff -pur orig/dvb-kernel/linux/drivers/media/dvb/ttpci-budget/budget.h dvb-kernel/linux/drivers/media/dvb/ttpci-budget/budget.h
--- orig/dvb-kernel/linux/drivers/media/dvb/ttpci-budget/budget.h	Thu Jan 23 20:00:03 2003
+++ dvb-kernel/linux/drivers/media/dvb/ttpci-budget/budget.h	Sun Feb  2 00:22:39 2003
@@ -47,7 +47,7 @@ struct budget_s {
         struct semaphore        pid_mutex;
 
         int tsf;
-        u32 ttbp;
+        u16 ttbp;
         int feeding;
 
         int registered;

Home | Main Index | Thread Index