Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
firedtv-fw.c
Go to the documentation of this file.
1 /*
2  * FireDTV driver -- firewire I/O backend
3  */
4 
5 #include <linux/device.h>
6 #include <linux/errno.h>
7 #include <linux/firewire.h>
9 #include <linux/kernel.h>
10 #include <linux/list.h>
11 #include <linux/mm.h>
12 #include <linux/mod_devicetable.h>
13 #include <linux/module.h>
14 #include <linux/mutex.h>
15 #include <linux/slab.h>
16 #include <linux/spinlock.h>
17 #include <linux/string.h>
18 #include <linux/types.h>
19 #include <linux/wait.h>
20 #include <linux/workqueue.h>
21 
22 #include <asm/page.h>
23 
24 #include <dvb_demux.h>
25 
26 #include "firedtv.h"
27 
28 static LIST_HEAD(node_list);
29 static DEFINE_SPINLOCK(node_list_lock);
30 
31 static inline struct fw_device *device_of(struct firedtv *fdtv)
32 {
33  return fw_device(fdtv->device->parent);
34 }
35 
36 static int node_req(struct firedtv *fdtv, u64 addr, void *data, size_t len,
37  int tcode)
38 {
39  struct fw_device *device = device_of(fdtv);
40  int rcode, generation = device->generation;
41 
42  smp_rmb(); /* node_id vs. generation */
43 
44  rcode = fw_run_transaction(device->card, tcode, device->node_id,
45  generation, device->max_speed, addr, data, len);
46 
47  return rcode != RCODE_COMPLETE ? -EIO : 0;
48 }
49 
50 int fdtv_lock(struct firedtv *fdtv, u64 addr, void *data)
51 {
52  return node_req(fdtv, addr, data, 8, TCODE_LOCK_COMPARE_SWAP);
53 }
54 
55 int fdtv_read(struct firedtv *fdtv, u64 addr, void *data)
56 {
57  return node_req(fdtv, addr, data, 4, TCODE_READ_QUADLET_REQUEST);
58 }
59 
60 int fdtv_write(struct firedtv *fdtv, u64 addr, void *data, size_t len)
61 {
62  return node_req(fdtv, addr, data, len, TCODE_WRITE_BLOCK_REQUEST);
63 }
64 
65 #define ISO_HEADER_SIZE 4
66 #define CIP_HEADER_SIZE 8
67 #define MPEG2_TS_HEADER_SIZE 4
68 #define MPEG2_TS_SOURCE_PACKET_SIZE (4 + 188)
69 
70 #define MAX_PACKET_SIZE 1024 /* 776, rounded up to 2^n */
71 #define PACKETS_PER_PAGE (PAGE_SIZE / MAX_PACKET_SIZE)
72 #define N_PACKETS 64 /* buffer size */
73 #define N_PAGES DIV_ROUND_UP(N_PACKETS, PACKETS_PER_PAGE)
74 #define IRQ_INTERVAL 16
75 
81  char *pages[N_PAGES];
82 };
83 
84 static int queue_iso(struct fdtv_ir_context *ctx, int index)
85 {
86  struct fw_iso_packet p;
87 
89  p.interrupt = !(++ctx->interrupt_packet & (IRQ_INTERVAL - 1));
90  p.skip = 0;
92 
93  return fw_iso_context_queue(ctx->context, &p, &ctx->buffer,
94  index * MAX_PACKET_SIZE);
95 }
96 
97 static void handle_iso(struct fw_iso_context *context, u32 cycle,
98  size_t header_length, void *header, void *data)
99 {
100  struct firedtv *fdtv = data;
101  struct fdtv_ir_context *ctx = fdtv->ir_context;
102  __be32 *h, *h_end;
103  int length, err, i = ctx->current_packet;
104  char *p, *p_end;
105 
106  for (h = header, h_end = h + header_length / 4; h < h_end; h++) {
107  length = be32_to_cpup(h) >> 16;
108  if (unlikely(length > MAX_PACKET_SIZE)) {
109  dev_err(fdtv->device, "length = %d\n", length);
110  length = MAX_PACKET_SIZE;
111  }
112 
113  p = ctx->pages[i / PACKETS_PER_PAGE]
115  p_end = p + length;
116 
117  for (p += CIP_HEADER_SIZE + MPEG2_TS_HEADER_SIZE; p < p_end;
119  dvb_dmx_swfilter_packets(&fdtv->demux, p, 1);
120 
121  err = queue_iso(ctx, i);
122  if (unlikely(err))
123  dev_err(fdtv->device, "requeue failed\n");
124 
125  i = (i + 1) & (N_PACKETS - 1);
126  }
128  ctx->current_packet = i;
129 }
130 
131 int fdtv_start_iso(struct firedtv *fdtv)
132 {
133  struct fdtv_ir_context *ctx;
134  struct fw_device *device = device_of(fdtv);
135  int i, err;
136 
137  ctx = kmalloc(sizeof(*ctx), GFP_KERNEL);
138  if (!ctx)
139  return -ENOMEM;
140 
141  ctx->context = fw_iso_context_create(device->card,
143  device->max_speed, ISO_HEADER_SIZE, handle_iso, fdtv);
144  if (IS_ERR(ctx->context)) {
145  err = PTR_ERR(ctx->context);
146  goto fail_free;
147  }
148 
149  err = fw_iso_buffer_init(&ctx->buffer, device->card,
151  if (err)
152  goto fail_context_destroy;
153 
154  ctx->interrupt_packet = 0;
155  ctx->current_packet = 0;
156 
157  for (i = 0; i < N_PAGES; i++)
158  ctx->pages[i] = page_address(ctx->buffer.pages[i]);
159 
160  for (i = 0; i < N_PACKETS; i++) {
161  err = queue_iso(ctx, i);
162  if (err)
163  goto fail;
164  }
165 
166  err = fw_iso_context_start(ctx->context, -1, 0,
168  if (err)
169  goto fail;
170 
171  fdtv->ir_context = ctx;
172 
173  return 0;
174 fail:
175  fw_iso_buffer_destroy(&ctx->buffer, device->card);
176 fail_context_destroy:
178 fail_free:
179  kfree(ctx);
180 
181  return err;
182 }
183 
184 void fdtv_stop_iso(struct firedtv *fdtv)
185 {
186  struct fdtv_ir_context *ctx = fdtv->ir_context;
187 
189  fw_iso_buffer_destroy(&ctx->buffer, device_of(fdtv)->card);
191  kfree(ctx);
192 }
193 
194 static void handle_fcp(struct fw_card *card, struct fw_request *request,
195  int tcode, int destination, int source, int generation,
196  unsigned long long offset, void *payload, size_t length,
197  void *callback_data)
198 {
199  struct firedtv *f, *fdtv = NULL;
200  struct fw_device *device;
201  unsigned long flags;
202  int su;
203 
204  if (length < 2 || (((u8 *)payload)[0] & 0xf0) != 0)
205  return;
206 
207  su = ((u8 *)payload)[1] & 0x7;
208 
209  spin_lock_irqsave(&node_list_lock, flags);
210  list_for_each_entry(f, &node_list, list) {
211  device = device_of(f);
212  if (device->generation != generation)
213  continue;
214 
215  smp_rmb(); /* node_id vs. generation */
216 
217  if (device->card == card &&
218  device->node_id == source &&
219  (f->subunit == su || (f->subunit == 0 && su == 0x7))) {
220  fdtv = f;
221  break;
222  }
223  }
224  spin_unlock_irqrestore(&node_list_lock, flags);
225 
226  if (fdtv)
227  avc_recv(fdtv, payload, length);
228 }
229 
230 static struct fw_address_handler fcp_handler = {
231  .length = CSR_FCP_END - CSR_FCP_RESPONSE,
232  .address_callback = handle_fcp,
233 };
234 
235 static const struct fw_address_region fcp_region = {
238 };
239 
240 static const char * const model_names[] = {
241  [FIREDTV_UNKNOWN] = "unknown type",
242  [FIREDTV_DVB_S] = "FireDTV S/CI",
243  [FIREDTV_DVB_C] = "FireDTV C/CI",
244  [FIREDTV_DVB_T] = "FireDTV T/CI",
245  [FIREDTV_DVB_S2] = "FireDTV S2 ",
246 };
247 
248 /* Adjust the template string if models with longer names appear. */
249 #define MAX_MODEL_NAME_LEN sizeof("FireDTV ????")
250 
251 static int node_probe(struct device *dev)
252 {
253  struct firedtv *fdtv;
254  char name[MAX_MODEL_NAME_LEN];
255  int name_len, i, err;
256 
257  fdtv = kzalloc(sizeof(*fdtv), GFP_KERNEL);
258  if (!fdtv)
259  return -ENOMEM;
260 
261  dev_set_drvdata(dev, fdtv);
262  fdtv->device = dev;
263  fdtv->isochannel = -1;
264  fdtv->voltage = 0xff;
265  fdtv->tone = 0xff;
266 
267  mutex_init(&fdtv->avc_mutex);
269  mutex_init(&fdtv->demux_mutex);
271 
272  name_len = fw_csr_string(fw_unit(dev)->directory, CSR_MODEL,
273  name, sizeof(name));
274  for (i = ARRAY_SIZE(model_names); --i; )
275  if (strlen(model_names[i]) <= name_len &&
276  strncmp(name, model_names[i], name_len) == 0)
277  break;
278  fdtv->type = i;
279 
280  err = fdtv_register_rc(fdtv, dev);
281  if (err)
282  goto fail_free;
283 
284  spin_lock_irq(&node_list_lock);
285  list_add_tail(&fdtv->list, &node_list);
286  spin_unlock_irq(&node_list_lock);
287 
288  err = avc_identify_subunit(fdtv);
289  if (err)
290  goto fail;
291 
292  err = fdtv_dvb_register(fdtv, model_names[fdtv->type]);
293  if (err)
294  goto fail;
295 
297 
298  return 0;
299 fail:
300  spin_lock_irq(&node_list_lock);
301  list_del(&fdtv->list);
302  spin_unlock_irq(&node_list_lock);
303  fdtv_unregister_rc(fdtv);
304 fail_free:
305  kfree(fdtv);
306 
307  return err;
308 }
309 
310 static int node_remove(struct device *dev)
311 {
312  struct firedtv *fdtv = dev_get_drvdata(dev);
313 
314  fdtv_dvb_unregister(fdtv);
315 
316  spin_lock_irq(&node_list_lock);
317  list_del(&fdtv->list);
318  spin_unlock_irq(&node_list_lock);
319 
320  fdtv_unregister_rc(fdtv);
321 
322  kfree(fdtv);
323  return 0;
324 }
325 
326 static void node_update(struct fw_unit *unit)
327 {
328  struct firedtv *fdtv = dev_get_drvdata(&unit->device);
329 
330  if (fdtv->isochannel >= 0)
332  fdtv->isochannel);
333 }
334 
335 #define MATCH_FLAGS (IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID | \
336  IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION)
337 
338 #define DIGITAL_EVERYWHERE_OUI 0x001287
339 #define AVC_UNIT_SPEC_ID_ENTRY 0x00a02d
340 #define AVC_SW_VERSION_ENTRY 0x010001
341 
342 static const struct ieee1394_device_id fdtv_id_table[] = {
343  {
344  /* FloppyDTV S/CI and FloppyDTV S2 */
345  .match_flags = MATCH_FLAGS,
346  .vendor_id = DIGITAL_EVERYWHERE_OUI,
347  .model_id = 0x000024,
348  .specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
349  .version = AVC_SW_VERSION_ENTRY,
350  }, {
351  /* FloppyDTV T/CI */
352  .match_flags = MATCH_FLAGS,
353  .vendor_id = DIGITAL_EVERYWHERE_OUI,
354  .model_id = 0x000025,
355  .specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
356  .version = AVC_SW_VERSION_ENTRY,
357  }, {
358  /* FloppyDTV C/CI */
359  .match_flags = MATCH_FLAGS,
360  .vendor_id = DIGITAL_EVERYWHERE_OUI,
361  .model_id = 0x000026,
362  .specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
363  .version = AVC_SW_VERSION_ENTRY,
364  }, {
365  /* FireDTV S/CI and FloppyDTV S2 */
366  .match_flags = MATCH_FLAGS,
367  .vendor_id = DIGITAL_EVERYWHERE_OUI,
368  .model_id = 0x000034,
369  .specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
370  .version = AVC_SW_VERSION_ENTRY,
371  }, {
372  /* FireDTV T/CI */
373  .match_flags = MATCH_FLAGS,
374  .vendor_id = DIGITAL_EVERYWHERE_OUI,
375  .model_id = 0x000035,
376  .specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
377  .version = AVC_SW_VERSION_ENTRY,
378  }, {
379  /* FireDTV C/CI */
380  .match_flags = MATCH_FLAGS,
381  .vendor_id = DIGITAL_EVERYWHERE_OUI,
382  .model_id = 0x000036,
383  .specifier_id = AVC_UNIT_SPEC_ID_ENTRY,
384  .version = AVC_SW_VERSION_ENTRY,
385  }, {}
386 };
387 MODULE_DEVICE_TABLE(ieee1394, fdtv_id_table);
388 
389 static struct fw_driver fdtv_driver = {
390  .driver = {
391  .owner = THIS_MODULE,
392  .name = "firedtv",
393  .bus = &fw_bus_type,
394  .probe = node_probe,
395  .remove = node_remove,
396  },
397  .update = node_update,
398  .id_table = fdtv_id_table,
399 };
400 
401 static int __init fdtv_init(void)
402 {
403  int ret;
404 
405  ret = fw_core_add_address_handler(&fcp_handler, &fcp_region);
406  if (ret < 0)
407  return ret;
408 
409  ret = driver_register(&fdtv_driver.driver);
410  if (ret < 0)
411  fw_core_remove_address_handler(&fcp_handler);
412 
413  return ret;
414 }
415 
416 static void __exit fdtv_exit(void)
417 {
418  driver_unregister(&fdtv_driver.driver);
419  fw_core_remove_address_handler(&fcp_handler);
420 }
421 
422 module_init(fdtv_init);
423 module_exit(fdtv_exit);
424 
425 MODULE_AUTHOR("Andreas Monitzer <[email protected]>");
426 MODULE_AUTHOR("Ben Backx <[email protected]>");
427 MODULE_DESCRIPTION("FireDTV DVB Driver");
428 MODULE_LICENSE("GPL");
429 MODULE_SUPPORTED_DEVICE("FireDTV DVB");