[linux-dvb] Dish Network Legacy Switch Code in Kernel 2.6.10 / 2.6.11

homer simpson homer_simpson_loves_u at hotmail.com
Sun Mar 13 22:14:25 CET 2005

The Legacy switch code doesn't work in the latest kernel very well (It 
worked once in 12 times or so on my Athlon XP system). Using an idea of 
NoOneImportants I hacked it to generate serial data on 8ms + or - 1 ms 
boundaries which makes it very reliable. Can you guys role this into the 
kernel or do I have to bug the kernel guys?

The way it works is to make sure that the bits are sent out at 8ms 
boundaries, and if it misses (because of a non-maskable interrupt) then it 
starts over. The code will not exit until it has sent the command with the 
correct timing. In reality the timing can be as much as two milliseconds off 
in either direction per bit because the target uart doesn't grab until 4ms + 
(bit number +1) * 8 ms after the start bit.

This works perfectly on my Athlon XP 2000MHz. I'd like to hear from people 
who have P4 systems because I'm not sure jiffies is the same on every 
platform. On mine a jiffie is a millisecond, is it that way on all systems?

This is from stv0299.c

static int stv0299_send_legacy_dish_cmd(struct dvb_frontend* fe, u32 cmd)

	long unsigned int target_jiffies;
	int i;                             // Bit counter
	int status=2;                      // Keep sending until it works
	const unsigned int bit_length = 8; // milliseconds
	u32 cmd_copy;
	u8 last = 1;
	unsigned int millisec;

//	printk("Entering Send Legacy Command\n");
	dprintk("%s switch command: 0x%04x\n",__FUNCTION__, cmd);

	while (status)
//		printk("Starting bit banging sequence.\n");
		i = 9; // 8 data bits + start bit
		status = 1;
		cmd_copy = cmd;
		cmd_copy = cmd_copy << 1; // Put in the start bit

		msleep(32); //Send the reset bits, aka set 18 volts and wait four bits.
		target_jiffies = msecs_to_jiffies(bit_length) + jiffies;

	        while ((status == 1) && i > 0)
//			printk(".");
			if ((cmd_copy & 0x01) != last) {
					    last ? SEC_VOLTAGE_13 :
				last = last ? 0: 1;

			cmd_copy = cmd_copy >> 1;
		        millisec = jiffies_to_msecs(target_jiffies - jiffies);
			if (jiffies > target_jiffies + 1) status = 2; // If its off by more than 
1ms, start over
			target_jiffies += msecs_to_jiffies(bit_length);
		if (status == 1) status = 0;
//		printk(".\n");
		if (status == 2) printk("Bit bang failed, starting over.\n");
	return 0;

More information about the linux-dvb mailing list