All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] DVB: firedtv: port to new firewire driver stack
@ 2009-11-08 21:27 Stefan Richter
  2009-11-08 21:28 ` [PATCH 1/4] firedtv: move remote control workqueue handling into rc source file Stefan Richter
                   ` (4 more replies)
  0 siblings, 5 replies; 8+ messages in thread
From: Stefan Richter @ 2009-11-08 21:27 UTC (permalink / raw)
  To: linux-media; +Cc: linux1394-devel, linux-kernel

The following patch series adapts the firedtv driver for
FireWire-attached DVB boxes and cards to the newer firewire-core kernel
API.  The driver will continue to work with the older ieee1394 kernel
API as well.  Which of the two IEEE 1394 stacks will be used depends on
which one was configured at build time.  If both were built, firedtv
transparently uses the stack which is bound to the FireWire controller.

This patch series depends on changes to firewire-core which were merged
into Linux 2.6.31.

There is some non-essential functionality yet to implement:
  - Finish FCP support in firewire-core so that more than one AV/C
    device can be used on the same FireWire bus at the same time.
  - Enhance firedtv to use firewire-core's channel and bandwidth
    allocation function for proper cooperation with non-FireDTV AV/C
    devices on the same bus.

Following as reply:
[PATCH 1/4] firedtv: move remote control workqueue handling into rc source file
[PATCH 2/4] firedtv: reform lock transaction backend call
[PATCH 3/4] firedtv: add missing include, rename a constant
[PATCH 4/4] firedtv: port to new firewire core

 drivers/media/dvb/firewire/Kconfig        |    7
 drivers/media/dvb/firewire/Makefile       |    1
 drivers/media/dvb/firewire/firedtv-1394.c |   37 +-
 drivers/media/dvb/firewire/firedtv-avc.c  |   50 +-
 drivers/media/dvb/firewire/firedtv-dvb.c  |   15
 drivers/media/dvb/firewire/firedtv-fw.c   |  385 ++++++++++++++++++++++
 drivers/media/dvb/firewire/firedtv-rc.c   |    2
 drivers/media/dvb/firewire/firedtv.h      |   17
 8 files changed, 471 insertions(+), 43 deletions(-)
-- 
Stefan Richter
-=====-==--= =-== -=---
http://arcgraph.de/sr/


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/4] firedtv: move remote control workqueue handling into rc source file
  2009-11-08 21:27 [PATCH 0/4] DVB: firedtv: port to new firewire driver stack Stefan Richter
@ 2009-11-08 21:28 ` Stefan Richter
  2009-11-08 21:29 ` [PATCH 2/4] firedtv: reform lock transaction backend call Stefan Richter
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Stefan Richter @ 2009-11-08 21:28 UTC (permalink / raw)
  To: linux-media; +Cc: linux1394-devel, linux-kernel

Preparation for the port of firedtv to the firewire-core kernel API:
Canceling of the remote control workqueue job is factored into
firedtv-rc.c.  Plus trivial whitespace change.

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
---
 drivers/media/dvb/firewire/firedtv-1394.c |    5 +++--
 drivers/media/dvb/firewire/firedtv-rc.c   |    2 ++
 2 files changed, 5 insertions(+), 2 deletions(-)

Index: linux-2.6.31.4/drivers/media/dvb/firewire/firedtv-1394.c
===================================================================
--- linux-2.6.31.4.orig/drivers/media/dvb/firewire/firedtv-1394.c
+++ linux-2.6.31.4/drivers/media/dvb/firewire/firedtv-1394.c
@@ -212,6 +212,7 @@ static int node_probe(struct device *dev
 		goto fail;
 
 	avc_register_remote_control(fdtv);
+
 	return 0;
 fail:
 	spin_lock_irq(&node_list_lock);
@@ -220,6 +221,7 @@ fail:
 	fdtv_unregister_rc(fdtv);
 fail_free:
 	kfree(fdtv);
+
 	return err;
 }
 
@@ -233,10 +235,9 @@ static int node_remove(struct device *de
 	list_del(&fdtv->list);
 	spin_unlock_irq(&node_list_lock);
 
-	cancel_work_sync(&fdtv->remote_ctrl_work);
 	fdtv_unregister_rc(fdtv);
-
 	kfree(fdtv);
+
 	return 0;
 }
 
Index: linux-2.6.31.4/drivers/media/dvb/firewire/firedtv-rc.c
===================================================================
--- linux-2.6.31.4.orig/drivers/media/dvb/firewire/firedtv-rc.c
+++ linux-2.6.31.4/drivers/media/dvb/firewire/firedtv-rc.c
@@ -14,6 +14,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/types.h>
+#include <linux/workqueue.h>
 
 #include "firedtv.h"
 
@@ -163,6 +164,7 @@ fail:
 
 void fdtv_unregister_rc(struct firedtv *fdtv)
 {
+	cancel_work_sync(&fdtv->remote_ctrl_work);
 	kfree(fdtv->remote_ctrl_dev->keycode);
 	input_unregister_device(fdtv->remote_ctrl_dev);
 }

-- 
Stefan Richter
-=====-==--= =-== -=---
http://arcgraph.de/sr/


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 2/4] firedtv: reform lock transaction backend call
  2009-11-08 21:27 [PATCH 0/4] DVB: firedtv: port to new firewire driver stack Stefan Richter
  2009-11-08 21:28 ` [PATCH 1/4] firedtv: move remote control workqueue handling into rc source file Stefan Richter
@ 2009-11-08 21:29 ` Stefan Richter
  2009-11-08 21:29 ` [PATCH 3/4] firedtv: add missing include, rename a constant Stefan Richter
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 8+ messages in thread
From: Stefan Richter @ 2009-11-08 21:29 UTC (permalink / raw)
  To: linux-media; +Cc: linux1394-devel, linux-kernel

Preparation for the port of firedtv to the firewire-core kernel API:
The fdtv->backend->lock() hook and thus the CMP code is slightly changed
to better fit with the new API.

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
---
 drivers/media/dvb/firewire/firedtv-1394.c |   11 ++++-
 drivers/media/dvb/firewire/firedtv-avc.c  |   50 ++++++++++++----------
 drivers/media/dvb/firewire/firedtv.h      |    2 
 3 files changed, 37 insertions(+), 26 deletions(-)

Index: linux-2.6.31.4/drivers/media/dvb/firewire/firedtv-1394.c
===================================================================
--- linux-2.6.31.4.orig/drivers/media/dvb/firewire/firedtv-1394.c
+++ linux-2.6.31.4/drivers/media/dvb/firewire/firedtv-1394.c
@@ -87,10 +87,15 @@ static inline struct node_entry *node_of
 	return container_of(fdtv->device, struct unit_directory, device)->ne;
 }
 
-static int node_lock(struct firedtv *fdtv, u64 addr, void *data, __be32 arg)
+static int node_lock(struct firedtv *fdtv, u64 addr, __be32 data[])
 {
-	return hpsb_node_lock(node_of(fdtv), addr, EXTCODE_COMPARE_SWAP, data,
-			      (__force quadlet_t)arg);
+	int ret;
+
+	ret = hpsb_node_lock(node_of(fdtv), addr, EXTCODE_COMPARE_SWAP,
+		(__force quadlet_t *)&data[1], (__force quadlet_t)data[0]);
+	data[0] = data[1];
+
+	return ret;
 }
 
 static int node_read(struct firedtv *fdtv, u64 addr, void *data, size_t len)
Index: linux-2.6.31.4/drivers/media/dvb/firewire/firedtv-avc.c
===================================================================
--- linux-2.6.31.4.orig/drivers/media/dvb/firewire/firedtv-avc.c
+++ linux-2.6.31.4/drivers/media/dvb/firewire/firedtv-avc.c
@@ -1255,14 +1255,14 @@ static int cmp_read(struct firedtv *fdtv
 	return ret;
 }
 
-static int cmp_lock(struct firedtv *fdtv, void *data, u64 addr, __be32 arg)
+static int cmp_lock(struct firedtv *fdtv, u64 addr, __be32 data[])
 {
 	int ret;
 
 	if (mutex_lock_interruptible(&fdtv->avc_mutex))
 		return -EINTR;
 
-	ret = fdtv->backend->lock(fdtv, addr, data, arg);
+	ret = fdtv->backend->lock(fdtv, addr, data);
 	if (ret < 0)
 		dev_err(fdtv->device, "CMP: lock I/O error\n");
 
@@ -1292,25 +1292,25 @@ static inline void set_opcr(__be32 *opcr
 
 int cmp_establish_pp_connection(struct firedtv *fdtv, int plug, int channel)
 {
-	__be32 old_opcr, opcr;
+	__be32 old_opcr, opcr[2];
 	u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2);
 	int attempts = 0;
 	int ret;
 
-	ret = cmp_read(fdtv, &opcr, opcr_address, 4);
+	ret = cmp_read(fdtv, opcr, opcr_address, 4);
 	if (ret < 0)
 		return ret;
 
 repeat:
-	if (!get_opcr_online(opcr)) {
+	if (!get_opcr_online(*opcr)) {
 		dev_err(fdtv->device, "CMP: output offline\n");
 		return -EBUSY;
 	}
 
-	old_opcr = opcr;
+	old_opcr = *opcr;
 
-	if (get_opcr_p2p_connections(opcr)) {
-		if (get_opcr_channel(opcr) != channel) {
+	if (get_opcr_p2p_connections(*opcr)) {
+		if (get_opcr_channel(*opcr) != channel) {
 			dev_err(fdtv->device, "CMP: cannot change channel\n");
 			return -EBUSY;
 		}
@@ -1318,11 +1318,11 @@ repeat:
 
 		/* We don't allocate isochronous resources. */
 	} else {
-		set_opcr_channel(&opcr, channel);
-		set_opcr_data_rate(&opcr, 2); /* S400 */
+		set_opcr_channel(opcr, channel);
+		set_opcr_data_rate(opcr, 2); /* S400 */
 
 		/* FIXME: this is for the worst case - optimize */
-		set_opcr_overhead_id(&opcr, 0);
+		set_opcr_overhead_id(opcr, 0);
 
 		/*
 		 * FIXME: allocate isochronous channel and bandwidth at IRM
@@ -1330,13 +1330,16 @@ repeat:
 		 */
 	}
 
-	set_opcr_p2p_connections(&opcr, get_opcr_p2p_connections(opcr) + 1);
+	set_opcr_p2p_connections(opcr, get_opcr_p2p_connections(*opcr) + 1);
 
-	ret = cmp_lock(fdtv, &opcr, opcr_address, old_opcr);
+	opcr[1] = *opcr;
+	opcr[0] = old_opcr;
+
+	ret = cmp_lock(fdtv, opcr_address, opcr);
 	if (ret < 0)
 		return ret;
 
-	if (old_opcr != opcr) {
+	if (old_opcr != *opcr) {
 		/*
 		 * FIXME: if old_opcr.P2P_Connections > 0,
 		 * deallocate isochronous channel and bandwidth at IRM
@@ -1354,27 +1357,30 @@ repeat:
 
 void cmp_break_pp_connection(struct firedtv *fdtv, int plug, int channel)
 {
-	__be32 old_opcr, opcr;
+	__be32 old_opcr, opcr[2];
 	u64 opcr_address = CMP_OUTPUT_PLUG_CONTROL_REG_0 + (plug << 2);
 	int attempts = 0;
 
-	if (cmp_read(fdtv, &opcr, opcr_address, 4) < 0)
+	if (cmp_read(fdtv, opcr, opcr_address, 4) < 0)
 		return;
 
 repeat:
-	if (!get_opcr_online(opcr) || !get_opcr_p2p_connections(opcr) ||
-	    get_opcr_channel(opcr) != channel) {
+	if (!get_opcr_online(*opcr) || !get_opcr_p2p_connections(*opcr) ||
+	    get_opcr_channel(*opcr) != channel) {
 		dev_err(fdtv->device, "CMP: no connection to break\n");
 		return;
 	}
 
-	old_opcr = opcr;
-	set_opcr_p2p_connections(&opcr, get_opcr_p2p_connections(opcr) - 1);
+	old_opcr = *opcr;
+	set_opcr_p2p_connections(opcr, get_opcr_p2p_connections(*opcr) - 1);
+
+	opcr[1] = *opcr;
+	opcr[0] = old_opcr;
 
-	if (cmp_lock(fdtv, &opcr, opcr_address, old_opcr) < 0)
+	if (cmp_lock(fdtv, opcr_address, opcr) < 0)
 		return;
 
-	if (old_opcr != opcr) {
+	if (old_opcr != *opcr) {
 		/*
 		 * FIXME: if old_opcr.P2P_Connections == 1, i.e. we were last
 		 * owner, deallocate isochronous channel and bandwidth at IRM
Index: linux-2.6.31.4/drivers/media/dvb/firewire/firedtv.h
===================================================================
--- linux-2.6.31.4.orig/drivers/media/dvb/firewire/firedtv.h
+++ linux-2.6.31.4/drivers/media/dvb/firewire/firedtv.h
@@ -72,7 +72,7 @@ struct input_dev;
 struct firedtv;
 
 struct firedtv_backend {
-	int (*lock)(struct firedtv *fdtv, u64 addr, void *data, __be32 arg);
+	int (*lock)(struct firedtv *fdtv, u64 addr, __be32 data[]);
 	int (*read)(struct firedtv *fdtv, u64 addr, void *data, size_t len);
 	int (*write)(struct firedtv *fdtv, u64 addr, void *data, size_t len);
 	int (*start_iso)(struct firedtv *fdtv);

-- 
Stefan Richter
-=====-==--= =-== -=---
http://arcgraph.de/sr/


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 3/4] firedtv: add missing include, rename a constant
  2009-11-08 21:27 [PATCH 0/4] DVB: firedtv: port to new firewire driver stack Stefan Richter
  2009-11-08 21:28 ` [PATCH 1/4] firedtv: move remote control workqueue handling into rc source file Stefan Richter
  2009-11-08 21:29 ` [PATCH 2/4] firedtv: reform lock transaction backend call Stefan Richter
@ 2009-11-08 21:29 ` Stefan Richter
  2009-11-08 21:30 ` [PATCH 4/4] firedtv: port to new firewire core Stefan Richter
  2009-11-12  1:44 ` [PATCH 0/4] DVB: firedtv: port to new firewire driver stack Stefan Richter
  4 siblings, 0 replies; 8+ messages in thread
From: Stefan Richter @ 2009-11-08 21:29 UTC (permalink / raw)
  To: linux-media; +Cc: linux1394-devel, linux-kernel

Add #include <dvb_demux.h> for dvb_dmx_swfilter_packets().  This was
already indirectly included via firedtv.h, but don't rely on it.

The 4 bytes which were referred to as FIREWIRE_HEADER_SIZE are actually
the source packet header from IEC 61883-4 (MPEG2-TS data transmission
over 1394), not e.g. the IEEE 1394 isochronous packet header.  So choose
a more precise name.

Also, express the payload size as a preprocessor constant too.

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
---
 drivers/media/dvb/firewire/firedtv-1394.c |   15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

Index: linux-2.6.31.4/drivers/media/dvb/firewire/firedtv-1394.c
===================================================================
--- linux-2.6.31.4.orig/drivers/media/dvb/firewire/firedtv-1394.c
+++ linux-2.6.31.4/drivers/media/dvb/firewire/firedtv-1394.c
@@ -26,13 +26,16 @@
 #include <iso.h>
 #include <nodemgr.h>
 
+#include <dvb_demux.h>
+
 #include "firedtv.h"
 
 static LIST_HEAD(node_list);
 static DEFINE_SPINLOCK(node_list_lock);
 
-#define FIREWIRE_HEADER_SIZE	4
-#define CIP_HEADER_SIZE		8
+#define CIP_HEADER_SIZE			8
+#define MPEG2_TS_HEADER_SIZE		4
+#define MPEG2_TS_SOURCE_PACKET_SIZE	(4 + 188)
 
 static void rawiso_activity_cb(struct hpsb_iso *iso)
 {
@@ -62,20 +65,20 @@ static void rawiso_activity_cb(struct hp
 		buf = dma_region_i(&iso->data_buf, unsigned char,
 			iso->infos[packet].offset + CIP_HEADER_SIZE);
 		count = (iso->infos[packet].len - CIP_HEADER_SIZE) /
-			(188 + FIREWIRE_HEADER_SIZE);
+			MPEG2_TS_SOURCE_PACKET_SIZE;
 
 		/* ignore empty packet */
 		if (iso->infos[packet].len <= CIP_HEADER_SIZE)
 			continue;
 
 		while (count--) {
-			if (buf[FIREWIRE_HEADER_SIZE] == 0x47)
+			if (buf[MPEG2_TS_HEADER_SIZE] == 0x47)
 				dvb_dmx_swfilter_packets(&fdtv->demux,
-						&buf[FIREWIRE_HEADER_SIZE], 1);
+						&buf[MPEG2_TS_HEADER_SIZE], 1);
 			else
 				dev_err(fdtv->device,
 					"skipping invalid packet\n");
-			buf += 188 + FIREWIRE_HEADER_SIZE;
+			buf += MPEG2_TS_SOURCE_PACKET_SIZE;
 		}
 	}
 out:

-- 
Stefan Richter
-=====-==--= =-== -=---
http://arcgraph.de/sr/


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 4/4] firedtv: port to new firewire core
  2009-11-08 21:27 [PATCH 0/4] DVB: firedtv: port to new firewire driver stack Stefan Richter
                   ` (2 preceding siblings ...)
  2009-11-08 21:29 ` [PATCH 3/4] firedtv: add missing include, rename a constant Stefan Richter
@ 2009-11-08 21:30 ` Stefan Richter
  2009-11-12  1:44 ` [PATCH 0/4] DVB: firedtv: port to new firewire driver stack Stefan Richter
  4 siblings, 0 replies; 8+ messages in thread
From: Stefan Richter @ 2009-11-08 21:30 UTC (permalink / raw)
  To: linux-media; +Cc: linux1394-devel, linux-kernel

The firedtv DVB driver will now work not only on top of the old ieee1394
driver stack but also on the new firewire driver stack.

Alongside to the firedtv-1394.c backend for driver binding and I/O, the
firedtv-fw.c backend is added.  Depending on which of the two 1394
stacks is configured, one or the other or both backends will be built
into the firedtv driver.

This has been tested with a DVB-T and a DVB-C box on x86-64 and x86-32
together with a few different controllers (Agere FW323, a NEC chip, TI
TSB82AA2, TSB43AB22/A, VIA VT6306).

Signed-off-by: Stefan Richter <stefanr@s5r6.in-berlin.de>
---
 drivers/media/dvb/firewire/Kconfig        |    7 +
 drivers/media/dvb/firewire/Makefile       |    1 +
 drivers/media/dvb/firewire/firedtv-1394.c |    6 
 drivers/media/dvb/firewire/firedtv-dvb.c  |   15 +
 drivers/media/dvb/firewire/firedtv-fw.c   |  385 ++++++++++++++++++++++
 drivers/media/dvb/firewire/firedtv.h      |   15 +
 6 files changed, 420 insertions(+), 9 deletions(-)

Index: linux-2.6.31.4/drivers/media/dvb/firewire/Kconfig
===================================================================
--- linux-2.6.31.4.orig/drivers/media/dvb/firewire/Kconfig
+++ linux-2.6.31.4/drivers/media/dvb/firewire/Kconfig
@@ -1,6 +1,6 @@
 config DVB_FIREDTV
 	tristate "FireDTV and FloppyDTV"
-	depends on DVB_CORE && IEEE1394
+	depends on DVB_CORE && (FIREWIRE || IEEE1394)
 	help
 	  Support for DVB receivers from Digital Everywhere
 	  which are connected via IEEE 1394 (FireWire).
@@ -13,8 +13,11 @@ config DVB_FIREDTV
 
 if DVB_FIREDTV
 
+config DVB_FIREDTV_FIREWIRE
+	def_bool FIREWIRE = y || (FIREWIRE = m && DVB_FIREDTV = m)
+
 config DVB_FIREDTV_IEEE1394
-	def_bool IEEE1394
+	def_bool IEEE1394 = y || (IEEE1394 = m && DVB_FIREDTV = m)
 
 config DVB_FIREDTV_INPUT
 	def_bool INPUT = y || (INPUT = m && DVB_FIREDTV = m)
Index: linux-2.6.31.4/drivers/media/dvb/firewire/Makefile
===================================================================
--- linux-2.6.31.4.orig/drivers/media/dvb/firewire/Makefile
+++ linux-2.6.31.4/drivers/media/dvb/firewire/Makefile
@@ -1,6 +1,7 @@
 obj-$(CONFIG_DVB_FIREDTV) += firedtv.o
 
 firedtv-y := firedtv-avc.o firedtv-ci.o firedtv-dvb.o firedtv-fe.o
+firedtv-$(CONFIG_DVB_FIREDTV_FIREWIRE) += firedtv-fw.o
 firedtv-$(CONFIG_DVB_FIREDTV_IEEE1394) += firedtv-1394.o
 firedtv-$(CONFIG_DVB_FIREDTV_INPUT)    += firedtv-rc.o
 
Index: linux-2.6.31.4/drivers/media/dvb/firewire/firedtv-1394.c
===================================================================
--- linux-2.6.31.4.orig/drivers/media/dvb/firewire/firedtv-1394.c
+++ linux-2.6.31.4/drivers/media/dvb/firewire/firedtv-1394.c
@@ -1,5 +1,5 @@
 /*
- * FireDTV driver (formerly known as FireSAT)
+ * FireDTV driver -- ieee1394 I/O backend
  *
  * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
  * Copyright (C) 2007-2008 Ben Backx <ben@bbackx.com>
@@ -261,6 +261,7 @@ static int node_update(struct unit_direc
 
 static struct hpsb_protocol_driver fdtv_driver = {
 	.name		= "firedtv",
+	.id_table	= fdtv_id_table,
 	.update		= node_update,
 	.driver         = {
 		.probe  = node_probe,
@@ -273,12 +274,11 @@ static struct hpsb_highlevel fdtv_highle
 	.fcp_request	= fcp_request,
 };
 
-int __init fdtv_1394_init(struct ieee1394_device_id id_table[])
+int __init fdtv_1394_init(void)
 {
 	int ret;
 
 	hpsb_register_highlevel(&fdtv_highlevel);
-	fdtv_driver.id_table = id_table;
 	ret = hpsb_register_protocol(&fdtv_driver);
 	if (ret) {
 		printk(KERN_ERR "firedtv: failed to register protocol\n");
Index: linux-2.6.31.4/drivers/media/dvb/firewire/firedtv-dvb.c
===================================================================
--- linux-2.6.31.4.orig/drivers/media/dvb/firewire/firedtv-dvb.c
+++ linux-2.6.31.4/drivers/media/dvb/firewire/firedtv-dvb.c
@@ -297,7 +297,7 @@ struct firedtv *fdtv_alloc(struct device
 #define AVC_UNIT_SPEC_ID_ENTRY	0x00a02d
 #define AVC_SW_VERSION_ENTRY	0x010001
 
-static struct ieee1394_device_id fdtv_id_table[] = {
+const struct ieee1394_device_id fdtv_id_table[] = {
 	{
 		/* FloppyDTV S/CI and FloppyDTV S2 */
 		.match_flags	= MATCH_FLAGS,
@@ -346,12 +346,23 @@ MODULE_DEVICE_TABLE(ieee1394, fdtv_id_ta
 
 static int __init fdtv_init(void)
 {
-	return fdtv_1394_init(fdtv_id_table);
+	int ret;
+
+	ret = fdtv_fw_init();
+	if (ret < 0)
+		return ret;
+
+	ret = fdtv_1394_init();
+	if (ret < 0)
+		fdtv_fw_exit();
+
+	return ret;
 }
 
 static void __exit fdtv_exit(void)
 {
 	fdtv_1394_exit();
+	fdtv_fw_exit();
 }
 
 module_init(fdtv_init);
Index: linux-2.6.31.4/drivers/media/dvb/firewire/firedtv-fw.c
===================================================================
--- /dev/null
+++ linux-2.6.31.4/drivers/media/dvb/firewire/firedtv-fw.c
@@ -0,0 +1,385 @@
+/*
+ * FireDTV driver -- firewire I/O backend
+ */
+
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/firewire.h>
+#include <linux/firewire-constants.h>
+#include <linux/highmem.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include <asm/page.h>
+
+#include <dvb_demux.h>
+
+#include "firedtv.h"
+
+static LIST_HEAD(node_list);
+static DEFINE_SPINLOCK(node_list_lock);
+
+static inline struct fw_device *device_of(struct firedtv *fdtv)
+{
+	return fw_device(fdtv->device->parent);
+}
+
+static int node_req(struct firedtv *fdtv, u64 addr, void *data, size_t len,
+		    int tcode)
+{
+	struct fw_device *device = device_of(fdtv);
+	int rcode, generation = device->generation;
+
+	smp_rmb(); /* node_id vs. generation */
+
+	rcode = fw_run_transaction(device->card, tcode, device->node_id,
+			generation, device->max_speed, addr, data, len);
+
+	return rcode != RCODE_COMPLETE ? -EIO : 0;
+}
+
+static int node_lock(struct firedtv *fdtv, u64 addr, __be32 data[])
+{
+	return node_req(fdtv, addr, data, 8, TCODE_LOCK_COMPARE_SWAP);
+}
+
+static int node_read(struct firedtv *fdtv, u64 addr, void *data, size_t len)
+{
+	return node_req(fdtv, addr, data, len, len == 4 ?
+			TCODE_READ_QUADLET_REQUEST : TCODE_READ_BLOCK_REQUEST);
+}
+
+static int node_write(struct firedtv *fdtv, u64 addr, void *data, size_t len)
+{
+	return node_req(fdtv, addr, data, len, TCODE_WRITE_BLOCK_REQUEST);
+}
+
+#define ISO_HEADER_SIZE			4
+#define CIP_HEADER_SIZE			8
+#define MPEG2_TS_HEADER_SIZE		4
+#define MPEG2_TS_SOURCE_PACKET_SIZE	(4 + 188)
+
+#define MAX_PACKET_SIZE		1024  /* 776, rounded up to 2^n */
+#define PACKETS_PER_PAGE	(PAGE_SIZE / MAX_PACKET_SIZE)
+#define N_PACKETS		64    /* buffer size */
+#define N_PAGES			DIV_ROUND_UP(N_PACKETS, PACKETS_PER_PAGE)
+#define IRQ_INTERVAL		16
+
+struct firedtv_receive_context {
+	struct fw_iso_context *context;
+	struct fw_iso_buffer buffer;
+	int interrupt_packet;
+	int current_packet;
+	char *packets[N_PACKETS];
+};
+
+static int queue_iso(struct firedtv_receive_context *ctx, int index)
+{
+	struct fw_iso_packet p;
+	int err;
+
+	p.payload_length = MAX_PACKET_SIZE;
+	p.interrupt = !(ctx->interrupt_packet & (IRQ_INTERVAL - 1));
+	p.skip = 0;
+	p.header_length = ISO_HEADER_SIZE;
+
+	err = fw_iso_context_queue(ctx->context, &p, &ctx->buffer,
+				   index * MAX_PACKET_SIZE);
+	if (!err)
+		ctx->interrupt_packet++;
+
+	return err;
+}
+
+static void handle_iso(struct fw_iso_context *context, u32 cycle,
+		       size_t header_length, void *header, void *data)
+{
+	struct firedtv *fdtv = data;
+	struct firedtv_receive_context *ctx = fdtv->backend_data;
+	__be32 *h, *h_end;
+	int i = ctx->current_packet, length, err;
+	char *p, *p_end;
+
+	for (h = header, h_end = h + header_length / 4; h < h_end; h++) {
+		length = be32_to_cpup(h) >> 16;
+		if (unlikely(length > MAX_PACKET_SIZE)) {
+			dev_err(fdtv->device, "length = %d\n", length);
+			length = MAX_PACKET_SIZE;
+		}
+
+		p = ctx->packets[i];
+		p_end = p + length;
+
+		for (p += CIP_HEADER_SIZE + MPEG2_TS_HEADER_SIZE; p < p_end;
+		     p += MPEG2_TS_SOURCE_PACKET_SIZE)
+			dvb_dmx_swfilter_packets(&fdtv->demux, p, 1);
+
+		err = queue_iso(ctx, i);
+		if (unlikely(err))
+			dev_err(fdtv->device, "requeue failed\n");
+
+		i = (i + 1) & (N_PACKETS - 1);
+	}
+	ctx->current_packet = i;
+}
+
+static int start_iso(struct firedtv *fdtv)
+{
+	struct firedtv_receive_context *ctx;
+	struct fw_device *device = device_of(fdtv);
+	char *p;
+	int i, j, k, err;
+
+	ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
+	if (!ctx)
+		return -ENOMEM;
+
+	ctx->context = fw_iso_context_create(device->card,
+			FW_ISO_CONTEXT_RECEIVE, fdtv->isochannel,
+			device->max_speed, ISO_HEADER_SIZE, handle_iso, fdtv);
+	if (IS_ERR(ctx->context)) {
+		err = PTR_ERR(ctx->context);
+		goto fail_free;
+	}
+
+	err = fw_iso_buffer_init(&ctx->buffer, device->card,
+				 N_PAGES, DMA_FROM_DEVICE);
+	if (err)
+		goto fail_context_destroy;
+
+	ctx->interrupt_packet = 1;
+	ctx->current_packet = 0;
+
+	for (i = 0, k = 0; k < N_PAGES; k++) {
+		p = kmap(ctx->buffer.pages[k]);
+		for (j = 0; j < PACKETS_PER_PAGE && i < N_PACKETS; j++, i++)
+			ctx->packets[i] = p + j * MAX_PACKET_SIZE;
+	}
+
+	for (i = 0; i < N_PACKETS; i++) {
+		err = queue_iso(ctx, i);
+		if (err)
+			goto fail;
+	}
+
+	err = fw_iso_context_start(ctx->context, -1, 0,
+				   FW_ISO_CONTEXT_MATCH_ALL_TAGS);
+	if (err)
+		goto fail;
+
+	fdtv->backend_data = ctx;
+
+	return 0;
+fail:
+	fw_iso_buffer_destroy(&ctx->buffer, device->card);
+fail_context_destroy:
+	fw_iso_context_destroy(ctx->context);
+fail_free:
+	kfree(ctx);
+
+	return err;
+}
+
+static void stop_iso(struct firedtv *fdtv)
+{
+	struct firedtv_receive_context *ctx = fdtv->backend_data;
+
+	fw_iso_context_stop(ctx->context);
+	fw_iso_buffer_destroy(&ctx->buffer, device_of(fdtv)->card);
+	fw_iso_context_destroy(ctx->context);
+	kfree(ctx);
+}
+
+static const struct firedtv_backend backend = {
+	.lock		= node_lock,
+	.read		= node_read,
+	.write		= node_write,
+	.start_iso	= start_iso,
+	.stop_iso	= stop_iso,
+};
+
+static void handle_fcp(struct fw_card *card, struct fw_request *request,
+		       int tcode, int destination, int source, int generation,
+		       int speed, unsigned long long offset,
+		       void *payload, size_t length, void *callback_data)
+{
+	struct firedtv *f, *fdtv = NULL;
+	struct fw_device *device;
+	unsigned long flags;
+	int su;
+
+	if ((tcode != TCODE_WRITE_QUADLET_REQUEST &&
+	     tcode != TCODE_WRITE_BLOCK_REQUEST) ||
+	    offset != CSR_REGISTER_BASE + CSR_FCP_RESPONSE ||
+	    length == 0 ||
+	    (((u8 *)payload)[0] & 0xf0) != 0) {
+		fw_send_response(card, request, RCODE_TYPE_ERROR);
+		return;
+	}
+
+	su = ((u8 *)payload)[1] & 0x7;
+
+	spin_lock_irqsave(&node_list_lock, flags);
+	list_for_each_entry(f, &node_list, list) {
+		device = device_of(f);
+		if (device->generation != generation)
+			continue;
+
+		smp_rmb(); /* node_id vs. generation */
+
+		if (device->card == card &&
+		    device->node_id == source &&
+		    (f->subunit == su || (f->subunit == 0 && su == 0x7))) {
+			fdtv = f;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&node_list_lock, flags);
+
+	if (fdtv) {
+		avc_recv(fdtv, payload, length);
+		fw_send_response(card, request, RCODE_COMPLETE);
+	}
+}
+
+static struct fw_address_handler fcp_handler = {
+	.length           = CSR_FCP_END - CSR_FCP_RESPONSE,
+	.address_callback = handle_fcp,
+};
+
+static const struct fw_address_region fcp_region = {
+	.start	= CSR_REGISTER_BASE + CSR_FCP_RESPONSE,
+	.end	= CSR_REGISTER_BASE + CSR_FCP_END,
+};
+
+/* Adjust the template string if models with longer names appear. */
+#define MAX_MODEL_NAME_LEN ((int)DIV_ROUND_UP(sizeof("FireDTV ????"), 4))
+
+static size_t model_name(u32 *directory, __be32 *buffer)
+{
+	struct fw_csr_iterator ci;
+	int i, length, key, value, last_key = 0;
+	u32 *block = NULL;
+
+	fw_csr_iterator_init(&ci, directory);
+	while (fw_csr_iterator_next(&ci, &key, &value)) {
+		if (last_key == CSR_MODEL &&
+		    key == (CSR_DESCRIPTOR | CSR_LEAF))
+			block = ci.p - 1 + value;
+		last_key = key;
+	}
+
+	if (block == NULL)
+		return 0;
+
+	length = min((int)(block[0] >> 16) - 2, MAX_MODEL_NAME_LEN);
+	if (length <= 0)
+		return 0;
+
+	/* fast-forward to text string */
+	block += 3;
+
+	for (i = 0; i < length; i++)
+		buffer[i] = cpu_to_be32(block[i]);
+
+	return length * 4;
+}
+
+static int node_probe(struct device *dev)
+{
+	struct firedtv *fdtv;
+	__be32 name[MAX_MODEL_NAME_LEN];
+	int name_len, err;
+
+	name_len = model_name(fw_unit(dev)->directory, name);
+
+	fdtv = fdtv_alloc(dev, &backend, (char *)name, name_len);
+	if (!fdtv)
+		return -ENOMEM;
+
+	err = fdtv_register_rc(fdtv, dev);
+	if (err)
+		goto fail_free;
+
+	spin_lock_irq(&node_list_lock);
+	list_add_tail(&fdtv->list, &node_list);
+	spin_unlock_irq(&node_list_lock);
+
+	err = avc_identify_subunit(fdtv);
+	if (err)
+		goto fail;
+
+	err = fdtv_dvb_register(fdtv);
+	if (err)
+		goto fail;
+
+	avc_register_remote_control(fdtv);
+
+	return 0;
+fail:
+	spin_lock_irq(&node_list_lock);
+	list_del(&fdtv->list);
+	spin_unlock_irq(&node_list_lock);
+	fdtv_unregister_rc(fdtv);
+fail_free:
+	kfree(fdtv);
+
+	return err;
+}
+
+static int node_remove(struct device *dev)
+{
+	struct firedtv *fdtv = dev_get_drvdata(dev);
+
+	fdtv_dvb_unregister(fdtv);
+
+	spin_lock_irq(&node_list_lock);
+	list_del(&fdtv->list);
+	spin_unlock_irq(&node_list_lock);
+
+	fdtv_unregister_rc(fdtv);
+
+	kfree(fdtv);
+	return 0;
+}
+
+static void node_update(struct fw_unit *unit)
+{
+	struct firedtv *fdtv = dev_get_drvdata(&unit->device);
+
+	if (fdtv->isochannel >= 0)
+		cmp_establish_pp_connection(fdtv, fdtv->subunit,
+					    fdtv->isochannel);
+}
+
+static struct fw_driver fdtv_driver = {
+	.driver   = {
+		.owner  = THIS_MODULE,
+		.name   = "firedtv",
+		.bus    = &fw_bus_type,
+		.probe  = node_probe,
+		.remove = node_remove,
+	},
+	.update   = node_update,
+	.id_table = fdtv_id_table,
+};
+
+int __init fdtv_fw_init(void)
+{
+	int ret;
+
+	ret = fw_core_add_address_handler(&fcp_handler, &fcp_region);
+	if (ret < 0)
+		return ret;
+
+	return driver_register(&fdtv_driver.driver);
+}
+
+void fdtv_fw_exit(void)
+{
+	driver_unregister(&fdtv_driver.driver);
+	fw_core_remove_address_handler(&fcp_handler);
+}
Index: linux-2.6.31.4/drivers/media/dvb/firewire/firedtv.h
===================================================================
--- linux-2.6.31.4.orig/drivers/media/dvb/firewire/firedtv.h
+++ linux-2.6.31.4/drivers/media/dvb/firewire/firedtv.h
@@ -16,6 +16,7 @@
 #include <linux/dvb/dmx.h>
 #include <linux/dvb/frontend.h>
 #include <linux/list.h>
+#include <linux/mod_devicetable.h>
 #include <linux/mutex.h>
 #include <linux/spinlock_types.h>
 #include <linux/types.h>
@@ -119,10 +120,10 @@ struct firedtv {
 
 /* firedtv-1394.c */
 #ifdef CONFIG_DVB_FIREDTV_IEEE1394
-int fdtv_1394_init(struct ieee1394_device_id id_table[]);
+int fdtv_1394_init(void);
 void fdtv_1394_exit(void);
 #else
-static inline int fdtv_1394_init(struct ieee1394_device_id it[]) { return 0; }
+static inline int fdtv_1394_init(void) { return 0; }
 static inline void fdtv_1394_exit(void) {}
 #endif
 
@@ -163,10 +164,20 @@ struct firedtv *fdtv_alloc(struct device
 			   const struct firedtv_backend *backend,
 			   const char *name, size_t name_len);
 extern const char *fdtv_model_names[];
+extern const struct ieee1394_device_id fdtv_id_table[];
 
 /* firedtv-fe.c */
 void fdtv_frontend_init(struct firedtv *fdtv);
 
+/* firedtv-fw.c */
+#ifdef CONFIG_DVB_FIREDTV_FIREWIRE
+int fdtv_fw_init(void);
+void fdtv_fw_exit(void);
+#else
+static inline int fdtv_fw_init(void) { return 0; }
+static inline void fdtv_fw_exit(void) {}
+#endif
+
 /* firedtv-rc.c */
 #ifdef CONFIG_DVB_FIREDTV_INPUT
 int fdtv_register_rc(struct firedtv *fdtv, struct device *dev);

-- 
Stefan Richter
-=====-==--= =-== -=---
http://arcgraph.de/sr/


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 0/4] DVB: firedtv: port to new firewire driver stack
  2009-11-08 21:27 [PATCH 0/4] DVB: firedtv: port to new firewire driver stack Stefan Richter
                   ` (3 preceding siblings ...)
  2009-11-08 21:30 ` [PATCH 4/4] firedtv: port to new firewire core Stefan Richter
@ 2009-11-12  1:44 ` Stefan Richter
  2009-11-14  7:54   ` Benny Amorsen
  4 siblings, 1 reply; 8+ messages in thread
From: Stefan Richter @ 2009-11-12  1:44 UTC (permalink / raw)
  To: linux-media; +Cc: linux1394-devel, linux-kernel

Stefan Richter wrote:
> [PATCH 1/4] firedtv: move remote control workqueue handling into rc source file
> [PATCH 2/4] firedtv: reform lock transaction backend call
> [PATCH 3/4] firedtv: add missing include, rename a constant
> [PATCH 4/4] firedtv: port to new firewire core
> 
>  drivers/media/dvb/firewire/Kconfig        |    7
>  drivers/media/dvb/firewire/Makefile       |    1
>  drivers/media/dvb/firewire/firedtv-1394.c |   37 +-
>  drivers/media/dvb/firewire/firedtv-avc.c  |   50 +-
>  drivers/media/dvb/firewire/firedtv-dvb.c  |   15
>  drivers/media/dvb/firewire/firedtv-fw.c   |  385 ++++++++++++++++++++++
>  drivers/media/dvb/firewire/firedtv-rc.c   |    2
>  drivers/media/dvb/firewire/firedtv.h      |   17
>  8 files changed, 471 insertions(+), 43 deletions(-)

These patches are now also available in the v2.6.31 based "firedtv"
branch at

    git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6.git firedtv

This branch is also merged into linux1394-2.6.git for-next and thereby
linux-next.git.
-- 
Stefan Richter
-=====-==--= =-== -==--
http://arcgraph.de/sr/


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 0/4] DVB: firedtv: port to new firewire driver stack
  2009-11-12  1:44 ` [PATCH 0/4] DVB: firedtv: port to new firewire driver stack Stefan Richter
@ 2009-11-14  7:54   ` Benny Amorsen
  2009-11-14 17:24     ` Goga777
  0 siblings, 1 reply; 8+ messages in thread
From: Benny Amorsen @ 2009-11-14  7:54 UTC (permalink / raw)
  To: Stefan Richter; +Cc: linux-media, linux1394-devel, linux-kernel

Stefan Richter <stefanr@s5r6.in-berlin.de> writes:

> These patches are now also available in the v2.6.31 based "firedtv"
> branch at
>
>     git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6.git firedtv
>
> This branch is also merged into linux1394-2.6.git for-next and thereby
> linux-next.git.

It works beautifully! Tested on a FireDTV C/CI.


/Benny


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 0/4] DVB: firedtv: port to new firewire driver stack
  2009-11-14  7:54   ` Benny Amorsen
@ 2009-11-14 17:24     ` Goga777
  0 siblings, 0 replies; 8+ messages in thread
From: Goga777 @ 2009-11-14 17:24 UTC (permalink / raw)
  To: Benny Amorsen, linux-media

> > These patches are now also available in the v2.6.31 based "firedtv"
> > branch at
> >
> >     git://git.kernel.org/pub/scm/linux/kernel/git/ieee1394/linux1394-2.6.git firedtv
> >
> > This branch is also merged into linux1394-2.6.git for-next and thereby
> > linux-next.git.
> 
> It works beautifully! Tested on a FireDTV C/CI.


what about of dvb-s2 support for FireDTV  and FloppyDTV ?  does it exist and work well ?

Goga

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2009-11-14 17:18 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-11-08 21:27 [PATCH 0/4] DVB: firedtv: port to new firewire driver stack Stefan Richter
2009-11-08 21:28 ` [PATCH 1/4] firedtv: move remote control workqueue handling into rc source file Stefan Richter
2009-11-08 21:29 ` [PATCH 2/4] firedtv: reform lock transaction backend call Stefan Richter
2009-11-08 21:29 ` [PATCH 3/4] firedtv: add missing include, rename a constant Stefan Richter
2009-11-08 21:30 ` [PATCH 4/4] firedtv: port to new firewire core Stefan Richter
2009-11-12  1:44 ` [PATCH 0/4] DVB: firedtv: port to new firewire driver stack Stefan Richter
2009-11-14  7:54   ` Benny Amorsen
2009-11-14 17:24     ` Goga777

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.