2 * FireDTV driver -- firewire I/O backend
5 #include <linux/device.h>
6 #include <linux/errno.h>
7 #include <linux/firewire.h>
8 #include <linux/firewire-constants.h>
9 #include <linux/kernel.h>
10 #include <linux/list.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>
23 #include <asm/system.h>
25 #include <dvb_demux.h>
29 static LIST_HEAD(node_list
);
30 static DEFINE_SPINLOCK(node_list_lock
);
32 static inline struct fw_device
*device_of(struct firedtv
*fdtv
)
34 return fw_device(fdtv
->device
->parent
);
37 static int node_req(struct firedtv
*fdtv
, u64 addr
, void *data
, size_t len
,
40 struct fw_device
*device
= device_of(fdtv
);
41 int rcode
, generation
= device
->generation
;
43 smp_rmb(); /* node_id vs. generation */
45 rcode
= fw_run_transaction(device
->card
, tcode
, device
->node_id
,
46 generation
, device
->max_speed
, addr
, data
, len
);
48 return rcode
!= RCODE_COMPLETE
? -EIO
: 0;
51 int fdtv_lock(struct firedtv
*fdtv
, u64 addr
, void *data
)
53 return node_req(fdtv
, addr
, data
, 8, TCODE_LOCK_COMPARE_SWAP
);
56 int fdtv_read(struct firedtv
*fdtv
, u64 addr
, void *data
)
58 return node_req(fdtv
, addr
, data
, 4, TCODE_READ_QUADLET_REQUEST
);
61 int fdtv_write(struct firedtv
*fdtv
, u64 addr
, void *data
, size_t len
)
63 return node_req(fdtv
, addr
, data
, len
, TCODE_WRITE_BLOCK_REQUEST
);
66 #define ISO_HEADER_SIZE 4
67 #define CIP_HEADER_SIZE 8
68 #define MPEG2_TS_HEADER_SIZE 4
69 #define MPEG2_TS_SOURCE_PACKET_SIZE (4 + 188)
71 #define MAX_PACKET_SIZE 1024 /* 776, rounded up to 2^n */
72 #define PACKETS_PER_PAGE (PAGE_SIZE / MAX_PACKET_SIZE)
73 #define N_PACKETS 64 /* buffer size */
74 #define N_PAGES DIV_ROUND_UP(N_PACKETS, PACKETS_PER_PAGE)
75 #define IRQ_INTERVAL 16
77 struct fdtv_ir_context
{
78 struct fw_iso_context
*context
;
79 struct fw_iso_buffer buffer
;
85 static int queue_iso(struct fdtv_ir_context
*ctx
, int index
)
87 struct fw_iso_packet p
;
89 p
.payload_length
= MAX_PACKET_SIZE
;
90 p
.interrupt
= !(++ctx
->interrupt_packet
& (IRQ_INTERVAL
- 1));
92 p
.header_length
= ISO_HEADER_SIZE
;
94 return fw_iso_context_queue(ctx
->context
, &p
, &ctx
->buffer
,
95 index
* MAX_PACKET_SIZE
);
98 static void handle_iso(struct fw_iso_context
*context
, u32 cycle
,
99 size_t header_length
, void *header
, void *data
)
101 struct firedtv
*fdtv
= data
;
102 struct fdtv_ir_context
*ctx
= fdtv
->ir_context
;
104 int length
, err
, i
= ctx
->current_packet
;
107 for (h
= header
, h_end
= h
+ header_length
/ 4; h
< h_end
; h
++) {
108 length
= be32_to_cpup(h
) >> 16;
109 if (unlikely(length
> MAX_PACKET_SIZE
)) {
110 dev_err(fdtv
->device
, "length = %d\n", length
);
111 length
= MAX_PACKET_SIZE
;
114 p
= ctx
->pages
[i
/ PACKETS_PER_PAGE
]
115 + (i
% PACKETS_PER_PAGE
) * MAX_PACKET_SIZE
;
118 for (p
+= CIP_HEADER_SIZE
+ MPEG2_TS_HEADER_SIZE
; p
< p_end
;
119 p
+= MPEG2_TS_SOURCE_PACKET_SIZE
)
120 dvb_dmx_swfilter_packets(&fdtv
->demux
, p
, 1);
122 err
= queue_iso(ctx
, i
);
124 dev_err(fdtv
->device
, "requeue failed\n");
126 i
= (i
+ 1) & (N_PACKETS
- 1);
128 fw_iso_context_queue_flush(ctx
->context
);
129 ctx
->current_packet
= i
;
132 int fdtv_start_iso(struct firedtv
*fdtv
)
134 struct fdtv_ir_context
*ctx
;
135 struct fw_device
*device
= device_of(fdtv
);
138 ctx
= kmalloc(sizeof(*ctx
), GFP_KERNEL
);
142 ctx
->context
= fw_iso_context_create(device
->card
,
143 FW_ISO_CONTEXT_RECEIVE
, fdtv
->isochannel
,
144 device
->max_speed
, ISO_HEADER_SIZE
, handle_iso
, fdtv
);
145 if (IS_ERR(ctx
->context
)) {
146 err
= PTR_ERR(ctx
->context
);
150 err
= fw_iso_buffer_init(&ctx
->buffer
, device
->card
,
151 N_PAGES
, DMA_FROM_DEVICE
);
153 goto fail_context_destroy
;
155 ctx
->interrupt_packet
= 0;
156 ctx
->current_packet
= 0;
158 for (i
= 0; i
< N_PAGES
; i
++)
159 ctx
->pages
[i
] = page_address(ctx
->buffer
.pages
[i
]);
161 for (i
= 0; i
< N_PACKETS
; i
++) {
162 err
= queue_iso(ctx
, i
);
167 err
= fw_iso_context_start(ctx
->context
, -1, 0,
168 FW_ISO_CONTEXT_MATCH_ALL_TAGS
);
172 fdtv
->ir_context
= ctx
;
176 fw_iso_buffer_destroy(&ctx
->buffer
, device
->card
);
177 fail_context_destroy
:
178 fw_iso_context_destroy(ctx
->context
);
185 void fdtv_stop_iso(struct firedtv
*fdtv
)
187 struct fdtv_ir_context
*ctx
= fdtv
->ir_context
;
189 fw_iso_context_stop(ctx
->context
);
190 fw_iso_buffer_destroy(&ctx
->buffer
, device_of(fdtv
)->card
);
191 fw_iso_context_destroy(ctx
->context
);
195 static void handle_fcp(struct fw_card
*card
, struct fw_request
*request
,
196 int tcode
, int destination
, int source
, int generation
,
197 unsigned long long offset
, void *payload
, size_t length
,
200 struct firedtv
*f
, *fdtv
= NULL
;
201 struct fw_device
*device
;
205 if (length
< 2 || (((u8
*)payload
)[0] & 0xf0) != 0)
208 su
= ((u8
*)payload
)[1] & 0x7;
210 spin_lock_irqsave(&node_list_lock
, flags
);
211 list_for_each_entry(f
, &node_list
, list
) {
212 device
= device_of(f
);
213 if (device
->generation
!= generation
)
216 smp_rmb(); /* node_id vs. generation */
218 if (device
->card
== card
&&
219 device
->node_id
== source
&&
220 (f
->subunit
== su
|| (f
->subunit
== 0 && su
== 0x7))) {
225 spin_unlock_irqrestore(&node_list_lock
, flags
);
228 avc_recv(fdtv
, payload
, length
);
231 static struct fw_address_handler fcp_handler
= {
232 .length
= CSR_FCP_END
- CSR_FCP_RESPONSE
,
233 .address_callback
= handle_fcp
,
236 static const struct fw_address_region fcp_region
= {
237 .start
= CSR_REGISTER_BASE
+ CSR_FCP_RESPONSE
,
238 .end
= CSR_REGISTER_BASE
+ CSR_FCP_END
,
241 static const char * const model_names
[] = {
242 [FIREDTV_UNKNOWN
] = "unknown type",
243 [FIREDTV_DVB_S
] = "FireDTV S/CI",
244 [FIREDTV_DVB_C
] = "FireDTV C/CI",
245 [FIREDTV_DVB_T
] = "FireDTV T/CI",
246 [FIREDTV_DVB_S2
] = "FireDTV S2 ",
249 /* Adjust the template string if models with longer names appear. */
250 #define MAX_MODEL_NAME_LEN sizeof("FireDTV ????")
252 static int node_probe(struct device
*dev
)
254 struct firedtv
*fdtv
;
255 char name
[MAX_MODEL_NAME_LEN
];
256 int name_len
, i
, err
;
258 fdtv
= kzalloc(sizeof(*fdtv
), GFP_KERNEL
);
262 dev_set_drvdata(dev
, fdtv
);
264 fdtv
->isochannel
= -1;
265 fdtv
->voltage
= 0xff;
268 mutex_init(&fdtv
->avc_mutex
);
269 init_waitqueue_head(&fdtv
->avc_wait
);
270 mutex_init(&fdtv
->demux_mutex
);
271 INIT_WORK(&fdtv
->remote_ctrl_work
, avc_remote_ctrl_work
);
273 name_len
= fw_csr_string(fw_unit(dev
)->directory
, CSR_MODEL
,
275 for (i
= ARRAY_SIZE(model_names
); --i
; )
276 if (strlen(model_names
[i
]) <= name_len
&&
277 strncmp(name
, model_names
[i
], name_len
) == 0)
281 err
= fdtv_register_rc(fdtv
, dev
);
285 spin_lock_irq(&node_list_lock
);
286 list_add_tail(&fdtv
->list
, &node_list
);
287 spin_unlock_irq(&node_list_lock
);
289 err
= avc_identify_subunit(fdtv
);
293 err
= fdtv_dvb_register(fdtv
, model_names
[fdtv
->type
]);
297 avc_register_remote_control(fdtv
);
301 spin_lock_irq(&node_list_lock
);
302 list_del(&fdtv
->list
);
303 spin_unlock_irq(&node_list_lock
);
304 fdtv_unregister_rc(fdtv
);
311 static int node_remove(struct device
*dev
)
313 struct firedtv
*fdtv
= dev_get_drvdata(dev
);
315 fdtv_dvb_unregister(fdtv
);
317 spin_lock_irq(&node_list_lock
);
318 list_del(&fdtv
->list
);
319 spin_unlock_irq(&node_list_lock
);
321 fdtv_unregister_rc(fdtv
);
327 static void node_update(struct fw_unit
*unit
)
329 struct firedtv
*fdtv
= dev_get_drvdata(&unit
->device
);
331 if (fdtv
->isochannel
>= 0)
332 cmp_establish_pp_connection(fdtv
, fdtv
->subunit
,
336 #define MATCH_FLAGS (IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID | \
337 IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION)
339 #define DIGITAL_EVERYWHERE_OUI 0x001287
340 #define AVC_UNIT_SPEC_ID_ENTRY 0x00a02d
341 #define AVC_SW_VERSION_ENTRY 0x010001
343 static const struct ieee1394_device_id fdtv_id_table
[] = {
345 /* FloppyDTV S/CI and FloppyDTV S2 */
346 .match_flags
= MATCH_FLAGS
,
347 .vendor_id
= DIGITAL_EVERYWHERE_OUI
,
348 .model_id
= 0x000024,
349 .specifier_id
= AVC_UNIT_SPEC_ID_ENTRY
,
350 .version
= AVC_SW_VERSION_ENTRY
,
353 .match_flags
= MATCH_FLAGS
,
354 .vendor_id
= DIGITAL_EVERYWHERE_OUI
,
355 .model_id
= 0x000025,
356 .specifier_id
= AVC_UNIT_SPEC_ID_ENTRY
,
357 .version
= AVC_SW_VERSION_ENTRY
,
360 .match_flags
= MATCH_FLAGS
,
361 .vendor_id
= DIGITAL_EVERYWHERE_OUI
,
362 .model_id
= 0x000026,
363 .specifier_id
= AVC_UNIT_SPEC_ID_ENTRY
,
364 .version
= AVC_SW_VERSION_ENTRY
,
366 /* FireDTV S/CI and FloppyDTV S2 */
367 .match_flags
= MATCH_FLAGS
,
368 .vendor_id
= DIGITAL_EVERYWHERE_OUI
,
369 .model_id
= 0x000034,
370 .specifier_id
= AVC_UNIT_SPEC_ID_ENTRY
,
371 .version
= AVC_SW_VERSION_ENTRY
,
374 .match_flags
= MATCH_FLAGS
,
375 .vendor_id
= DIGITAL_EVERYWHERE_OUI
,
376 .model_id
= 0x000035,
377 .specifier_id
= AVC_UNIT_SPEC_ID_ENTRY
,
378 .version
= AVC_SW_VERSION_ENTRY
,
381 .match_flags
= MATCH_FLAGS
,
382 .vendor_id
= DIGITAL_EVERYWHERE_OUI
,
383 .model_id
= 0x000036,
384 .specifier_id
= AVC_UNIT_SPEC_ID_ENTRY
,
385 .version
= AVC_SW_VERSION_ENTRY
,
388 MODULE_DEVICE_TABLE(ieee1394
, fdtv_id_table
);
390 static struct fw_driver fdtv_driver
= {
392 .owner
= THIS_MODULE
,
396 .remove
= node_remove
,
398 .update
= node_update
,
399 .id_table
= fdtv_id_table
,
402 static int __init
fdtv_init(void)
406 ret
= fw_core_add_address_handler(&fcp_handler
, &fcp_region
);
410 ret
= driver_register(&fdtv_driver
.driver
);
412 fw_core_remove_address_handler(&fcp_handler
);
417 static void __exit
fdtv_exit(void)
419 driver_unregister(&fdtv_driver
.driver
);
420 fw_core_remove_address_handler(&fcp_handler
);
423 module_init(fdtv_init
);
424 module_exit(fdtv_exit
);
426 MODULE_AUTHOR("Andreas Monitzer <andy@monitzer.com>");
427 MODULE_AUTHOR("Ben Backx <ben@bbackx.com>");
428 MODULE_DESCRIPTION("FireDTV DVB Driver");
429 MODULE_LICENSE("GPL");
430 MODULE_SUPPORTED_DEVICE("FireDTV DVB");