aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/dvb/firewire/firedtv-1394.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/media/dvb/firewire/firedtv-1394.c')
-rw-r--r--drivers/media/dvb/firewire/firedtv-1394.c332
1 files changed, 163 insertions, 169 deletions
diff --git a/drivers/media/dvb/firewire/firedtv-1394.c b/drivers/media/dvb/firewire/firedtv-1394.c
index 953618246e8e..4e207658c5d9 100644
--- a/drivers/media/dvb/firewire/firedtv-1394.c
+++ b/drivers/media/dvb/firewire/firedtv-1394.c
@@ -15,162 +15,181 @@
15#include <linux/errno.h> 15#include <linux/errno.h>
16#include <linux/kernel.h> 16#include <linux/kernel.h>
17#include <linux/list.h> 17#include <linux/list.h>
18#include <linux/module.h>
19#include <linux/mutex.h>
20#include <linux/slab.h>
21#include <linux/spinlock.h> 18#include <linux/spinlock.h>
22#include <linux/string.h>
23#include <linux/types.h> 19#include <linux/types.h>
24 20
25#include <dmxdev.h> 21#include <dma.h>
26#include <dvb_demux.h>
27#include <dvb_frontend.h>
28#include <dvbdev.h>
29
30#include <csr1212.h> 22#include <csr1212.h>
31#include <highlevel.h> 23#include <highlevel.h>
32#include <hosts.h> 24#include <hosts.h>
33#include <ieee1394_hotplug.h> 25#include <ieee1394.h>
26#include <iso.h>
34#include <nodemgr.h> 27#include <nodemgr.h>
35 28
36#include "avc.h"
37#include "cmp.h"
38#include "firedtv.h" 29#include "firedtv.h"
39#include "firedtv-ci.h"
40#include "firedtv-rc.h"
41
42#define MATCH_FLAGS IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID | \
43 IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION
44#define DIGITAL_EVERYWHERE_OUI 0x001287
45
46static struct ieee1394_device_id fdtv_id_table[] = {
47
48 {
49 /* FloppyDTV S/CI and FloppyDTV S2 */
50 .match_flags = MATCH_FLAGS,
51 .vendor_id = DIGITAL_EVERYWHERE_OUI,
52 .model_id = 0x000024,
53 .specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
54 .version = AVC_SW_VERSION_ENTRY,
55 },{
56 /* FloppyDTV T/CI */
57 .match_flags = MATCH_FLAGS,
58 .vendor_id = DIGITAL_EVERYWHERE_OUI,
59 .model_id = 0x000025,
60 .specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
61 .version = AVC_SW_VERSION_ENTRY,
62 },{
63 /* FloppyDTV C/CI */
64 .match_flags = MATCH_FLAGS,
65 .vendor_id = DIGITAL_EVERYWHERE_OUI,
66 .model_id = 0x000026,
67 .specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
68 .version = AVC_SW_VERSION_ENTRY,
69 },{
70 /* FireDTV S/CI and FloppyDTV S2 */
71 .match_flags = MATCH_FLAGS,
72 .vendor_id = DIGITAL_EVERYWHERE_OUI,
73 .model_id = 0x000034,
74 .specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
75 .version = AVC_SW_VERSION_ENTRY,
76 },{
77 /* FireDTV T/CI */
78 .match_flags = MATCH_FLAGS,
79 .vendor_id = DIGITAL_EVERYWHERE_OUI,
80 .model_id = 0x000035,
81 .specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
82 .version = AVC_SW_VERSION_ENTRY,
83 },{
84 /* FireDTV C/CI */
85 .match_flags = MATCH_FLAGS,
86 .vendor_id = DIGITAL_EVERYWHERE_OUI,
87 .model_id = 0x000036,
88 .specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
89 .version = AVC_SW_VERSION_ENTRY,
90 }, { }
91};
92 30
93MODULE_DEVICE_TABLE(ieee1394, fdtv_id_table); 31static LIST_HEAD(node_list);
32static DEFINE_SPINLOCK(node_list_lock);
94 33
95/* list of all firedtv devices */ 34#define FIREWIRE_HEADER_SIZE 4
96LIST_HEAD(fdtv_list); 35#define CIP_HEADER_SIZE 8
97DEFINE_SPINLOCK(fdtv_list_lock);
98 36
99static void fcp_request(struct hpsb_host *host, 37static void rawiso_activity_cb(struct hpsb_iso *iso)
100 int nodeid,
101 int direction,
102 int cts,
103 u8 *data,
104 size_t length)
105{ 38{
106 struct firedtv *fdtv = NULL; 39 struct firedtv *f, *fdtv = NULL;
107 struct firedtv *fdtv_entry; 40 unsigned int i, num, packet;
41 unsigned char *buf;
108 unsigned long flags; 42 unsigned long flags;
43 int count;
44
45 spin_lock_irqsave(&node_list_lock, flags);
46 list_for_each_entry(f, &node_list, list)
47 if (f->backend_data == iso) {
48 fdtv = f;
49 break;
50 }
51 spin_unlock_irqrestore(&node_list_lock, flags);
52
53 packet = iso->first_packet;
54 num = hpsb_iso_n_ready(iso);
55
56 if (!fdtv) {
57 dev_err(fdtv->device, "received at unknown iso channel\n");
58 goto out;
59 }
109 60
110 if (length > 0 && ((data[0] & 0xf0) >> 4) == 0) { 61 for (i = 0; i < num; i++, packet = (packet + 1) % iso->buf_packets) {
111 62 buf = dma_region_i(&iso->data_buf, unsigned char,
112 spin_lock_irqsave(&fdtv_list_lock, flags); 63 iso->infos[packet].offset + CIP_HEADER_SIZE);
113 list_for_each_entry(fdtv_entry,&fdtv_list,list) { 64 count = (iso->infos[packet].len - CIP_HEADER_SIZE) /
114 if (fdtv_entry->ud->ne->host == host && 65 (188 + FIREWIRE_HEADER_SIZE);
115 fdtv_entry->ud->ne->nodeid == nodeid && 66
116 (fdtv_entry->subunit == (data[1]&0x7) || 67 /* ignore empty packet */
117 (fdtv_entry->subunit == 0 && 68 if (iso->infos[packet].len <= CIP_HEADER_SIZE)
118 (data[1]&0x7) == 0x7))) { 69 continue;
119 fdtv=fdtv_entry; 70
120 break; 71 while (count--) {
121 } 72 if (buf[FIREWIRE_HEADER_SIZE] == 0x47)
73 dvb_dmx_swfilter_packets(&fdtv->demux,
74 &buf[FIREWIRE_HEADER_SIZE], 1);
75 else
76 dev_err(fdtv->device,
77 "skipping invalid packet\n");
78 buf += 188 + FIREWIRE_HEADER_SIZE;
122 } 79 }
123 spin_unlock_irqrestore(&fdtv_list_lock, flags); 80 }
81out:
82 hpsb_iso_recv_release_packets(iso, num);
83}
84
85static inline struct node_entry *node_of(struct firedtv *fdtv)
86{
87 return container_of(fdtv->device, struct unit_directory, device)->ne;
88}
89
90static int node_lock(struct firedtv *fdtv, u64 addr, void *data, __be32 arg)
91{
92 return hpsb_node_lock(node_of(fdtv), addr, EXTCODE_COMPARE_SWAP, data,
93 (__force quadlet_t)arg);
94}
95
96static int node_read(struct firedtv *fdtv, u64 addr, void *data, size_t len)
97{
98 return hpsb_node_read(node_of(fdtv), addr, data, len);
99}
100
101static int node_write(struct firedtv *fdtv, u64 addr, void *data, size_t len)
102{
103 return hpsb_node_write(node_of(fdtv), addr, data, len);
104}
105
106#define FDTV_ISO_BUFFER_PACKETS 256
107#define FDTV_ISO_BUFFER_SIZE (FDTV_ISO_BUFFER_PACKETS * 200)
108
109static int start_iso(struct firedtv *fdtv)
110{
111 struct hpsb_iso *iso_handle;
112 int ret;
113
114 iso_handle = hpsb_iso_recv_init(node_of(fdtv)->host,
115 FDTV_ISO_BUFFER_SIZE, FDTV_ISO_BUFFER_PACKETS,
116 fdtv->isochannel, HPSB_ISO_DMA_DEFAULT,
117 -1, /* stat.config.irq_interval */
118 rawiso_activity_cb);
119 if (iso_handle == NULL) {
120 dev_err(fdtv->device, "cannot initialize iso receive\n");
121 return -ENOMEM;
122 }
123 fdtv->backend_data = iso_handle;
124
125 ret = hpsb_iso_recv_start(iso_handle, -1, -1, 0);
126 if (ret != 0) {
127 dev_err(fdtv->device, "cannot start iso receive\n");
128 hpsb_iso_shutdown(iso_handle);
129 fdtv->backend_data = NULL;
130 }
131 return ret;
132}
133
134static void stop_iso(struct firedtv *fdtv)
135{
136 struct hpsb_iso *iso_handle = fdtv->backend_data;
124 137
125 if (fdtv) 138 if (iso_handle != NULL) {
126 avc_recv(fdtv, data, length); 139 hpsb_iso_stop(iso_handle);
140 hpsb_iso_shutdown(iso_handle);
127 } 141 }
142 fdtv->backend_data = NULL;
128} 143}
129 144
130const char *fdtv_model_names[] = { 145static const struct firedtv_backend fdtv_1394_backend = {
131 [FIREDTV_UNKNOWN] = "unknown type", 146 .lock = node_lock,
132 [FIREDTV_DVB_S] = "FireDTV S/CI", 147 .read = node_read,
133 [FIREDTV_DVB_C] = "FireDTV C/CI", 148 .write = node_write,
134 [FIREDTV_DVB_T] = "FireDTV T/CI", 149 .start_iso = start_iso,
135 [FIREDTV_DVB_S2] = "FireDTV S2 ", 150 .stop_iso = stop_iso,
136}; 151};
137 152
138static int fdtv_probe(struct device *dev) 153static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
154 int cts, u8 *data, size_t length)
139{ 155{
140 struct unit_directory *ud = 156 struct firedtv *f, *fdtv = NULL;
141 container_of(dev, struct unit_directory, device);
142 struct firedtv *fdtv;
143 unsigned long flags; 157 unsigned long flags;
144 int kv_len; 158 int su;
145 void *kv_str;
146 int i;
147 int err = -ENOMEM;
148 159
149 fdtv = kzalloc(sizeof(*fdtv), GFP_KERNEL); 160 if (length == 0 || (data[0] & 0xf0) != 0)
150 if (!fdtv) 161 return;
151 return -ENOMEM;
152 162
153 dev->driver_data = fdtv; 163 su = data[1] & 0x7;
154 fdtv->ud = ud; 164
155 fdtv->subunit = 0; 165 spin_lock_irqsave(&node_list_lock, flags);
156 fdtv->isochannel = -1; 166 list_for_each_entry(f, &node_list, list)
157 fdtv->tone = 0xff; 167 if (node_of(f)->host == host &&
158 fdtv->voltage = 0xff; 168 node_of(f)->nodeid == nodeid &&
169 (f->subunit == su || (f->subunit == 0 && su == 0x7))) {
170 fdtv = f;
171 break;
172 }
173 spin_unlock_irqrestore(&node_list_lock, flags);
159 174
160 mutex_init(&fdtv->avc_mutex); 175 if (fdtv)
161 init_waitqueue_head(&fdtv->avc_wait); 176 avc_recv(fdtv, data, length);
162 fdtv->avc_reply_received = true; 177}
163 mutex_init(&fdtv->demux_mutex); 178
164 INIT_WORK(&fdtv->remote_ctrl_work, avc_remote_ctrl_work); 179static int node_probe(struct device *dev)
180{
181 struct unit_directory *ud =
182 container_of(dev, struct unit_directory, device);
183 struct firedtv *fdtv;
184 int kv_len, err;
185 void *kv_str;
165 186
166 /* Reading device model from ROM */
167 kv_len = (ud->model_name_kv->value.leaf.len - 2) * sizeof(quadlet_t); 187 kv_len = (ud->model_name_kv->value.leaf.len - 2) * sizeof(quadlet_t);
168 kv_str = CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(ud->model_name_kv); 188 kv_str = CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(ud->model_name_kv);
169 for (i = ARRAY_SIZE(fdtv_model_names); --i;) 189
170 if (strlen(fdtv_model_names[i]) <= kv_len && 190 fdtv = fdtv_alloc(dev, &fdtv_1394_backend, kv_str, kv_len);
171 strncmp(kv_str, fdtv_model_names[i], kv_len) == 0) 191 if (!fdtv)
172 break; 192 return -ENOMEM;
173 fdtv->type = i;
174 193
175 /* 194 /*
176 * Work around a bug in udev's path_id script: Use the fw-host's dev 195 * Work around a bug in udev's path_id script: Use the fw-host's dev
@@ -180,50 +199,39 @@ static int fdtv_probe(struct device *dev)
180 if (err) 199 if (err)
181 goto fail_free; 200 goto fail_free;
182 201
183 INIT_LIST_HEAD(&fdtv->list); 202 spin_lock_irq(&node_list_lock);
184 spin_lock_irqsave(&fdtv_list_lock, flags); 203 list_add_tail(&fdtv->list, &node_list);
185 list_add_tail(&fdtv->list, &fdtv_list); 204 spin_unlock_irq(&node_list_lock);
186 spin_unlock_irqrestore(&fdtv_list_lock, flags);
187 205
188 err = avc_identify_subunit(fdtv); 206 err = avc_identify_subunit(fdtv);
189 if (err) 207 if (err)
190 goto fail; 208 goto fail;
191 209
192 err = fdtv_dvbdev_init(fdtv, dev); 210 err = fdtv_dvb_register(fdtv);
193 if (err) 211 if (err)
194 goto fail; 212 goto fail;
195 213
196 avc_register_remote_control(fdtv); 214 avc_register_remote_control(fdtv);
197 return 0; 215 return 0;
198
199fail: 216fail:
200 spin_lock_irqsave(&fdtv_list_lock, flags); 217 spin_lock_irq(&node_list_lock);
201 list_del(&fdtv->list); 218 list_del(&fdtv->list);
202 spin_unlock_irqrestore(&fdtv_list_lock, flags); 219 spin_unlock_irq(&node_list_lock);
203 fdtv_unregister_rc(fdtv); 220 fdtv_unregister_rc(fdtv);
204fail_free: 221fail_free:
205 kfree(fdtv); 222 kfree(fdtv);
206 return err; 223 return err;
207} 224}
208 225
209static int fdtv_remove(struct device *dev) 226static int node_remove(struct device *dev)
210{ 227{
211 struct firedtv *fdtv = dev->driver_data; 228 struct firedtv *fdtv = dev->driver_data;
212 unsigned long flags;
213 229
214 fdtv_ca_release(fdtv); 230 fdtv_dvb_unregister(fdtv);
215 dvb_unregister_frontend(&fdtv->fe); 231
216 dvb_net_release(&fdtv->dvbnet); 232 spin_lock_irq(&node_list_lock);
217 fdtv->demux.dmx.close(&fdtv->demux.dmx);
218 fdtv->demux.dmx.remove_frontend(&fdtv->demux.dmx,
219 &fdtv->frontend);
220 dvb_dmxdev_release(&fdtv->dmxdev);
221 dvb_dmx_release(&fdtv->demux);
222 dvb_unregister_adapter(&fdtv->adapter);
223
224 spin_lock_irqsave(&fdtv_list_lock, flags);
225 list_del(&fdtv->list); 233 list_del(&fdtv->list);
226 spin_unlock_irqrestore(&fdtv_list_lock, flags); 234 spin_unlock_irq(&node_list_lock);
227 235
228 cancel_work_sync(&fdtv->remote_ctrl_work); 236 cancel_work_sync(&fdtv->remote_ctrl_work);
229 fdtv_unregister_rc(fdtv); 237 fdtv_unregister_rc(fdtv);
@@ -232,7 +240,7 @@ static int fdtv_remove(struct device *dev)
232 return 0; 240 return 0;
233} 241}
234 242
235static int fdtv_update(struct unit_directory *ud) 243static int node_update(struct unit_directory *ud)
236{ 244{
237 struct firedtv *fdtv = ud->device.driver_data; 245 struct firedtv *fdtv = ud->device.driver_data;
238 246
@@ -243,17 +251,11 @@ static int fdtv_update(struct unit_directory *ud)
243} 251}
244 252
245static struct hpsb_protocol_driver fdtv_driver = { 253static struct hpsb_protocol_driver fdtv_driver = {
246
247 .name = "firedtv", 254 .name = "firedtv",
248 .id_table = fdtv_id_table, 255 .update = node_update,
249 .update = fdtv_update,
250
251 .driver = { 256 .driver = {
252 //.name and .bus are filled in for us in more recent linux versions 257 .probe = node_probe,
253 //.name = "FireDTV", 258 .remove = node_remove,
254 //.bus = &ieee1394_bus_type,
255 .probe = fdtv_probe,
256 .remove = fdtv_remove,
257 }, 259 },
258}; 260};
259 261
@@ -262,11 +264,12 @@ static struct hpsb_highlevel fdtv_highlevel = {
262 .fcp_request = fcp_request, 264 .fcp_request = fcp_request,
263}; 265};
264 266
265static int __init fdtv_init(void) 267int __init fdtv_1394_init(struct ieee1394_device_id id_table[])
266{ 268{
267 int ret; 269 int ret;
268 270
269 hpsb_register_highlevel(&fdtv_highlevel); 271 hpsb_register_highlevel(&fdtv_highlevel);
272 fdtv_driver.id_table = id_table;
270 ret = hpsb_register_protocol(&fdtv_driver); 273 ret = hpsb_register_protocol(&fdtv_driver);
271 if (ret) { 274 if (ret) {
272 printk(KERN_ERR "firedtv: failed to register protocol\n"); 275 printk(KERN_ERR "firedtv: failed to register protocol\n");
@@ -275,17 +278,8 @@ static int __init fdtv_init(void)
275 return ret; 278 return ret;
276} 279}
277 280
278static void __exit fdtv_exit(void) 281void __exit fdtv_1394_exit(void)
279{ 282{
280 hpsb_unregister_protocol(&fdtv_driver); 283 hpsb_unregister_protocol(&fdtv_driver);
281 hpsb_unregister_highlevel(&fdtv_highlevel); 284 hpsb_unregister_highlevel(&fdtv_highlevel);
282} 285}
283
284module_init(fdtv_init);
285module_exit(fdtv_exit);
286
287MODULE_AUTHOR("Andreas Monitzer <andy@monitzer.com>");
288MODULE_AUTHOR("Ben Backx <ben@bbackx.com>");
289MODULE_DESCRIPTION("FireDTV DVB Driver");
290MODULE_LICENSE("GPL");
291MODULE_SUPPORTED_DEVICE("FireDTV DVB");