2 * FireDTV driver (formerly known as FireSAT)
4 * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
5 * Copyright (C) 2007-2008 Ben Backx <ben@bbackx.com>
6 * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of
11 * the License, or (at your option) any later version.
14 #include <linux/device.h>
15 #include <linux/errno.h>
16 #include <linux/kernel.h>
17 #include <linux/list.h>
18 #include <linux/spinlock.h>
19 #include <linux/types.h>
23 #include <highlevel.h>
31 static LIST_HEAD(node_list
);
32 static DEFINE_SPINLOCK(node_list_lock
);
34 #define FIREWIRE_HEADER_SIZE 4
35 #define CIP_HEADER_SIZE 8
37 static void rawiso_activity_cb(struct hpsb_iso
*iso
)
39 struct firedtv
*f
, *fdtv
= NULL
;
40 unsigned int i
, num
, packet
;
45 spin_lock_irqsave(&node_list_lock
, flags
);
46 list_for_each_entry(f
, &node_list
, list
)
47 if (f
->backend_data
== iso
) {
51 spin_unlock_irqrestore(&node_list_lock
, flags
);
53 packet
= iso
->first_packet
;
54 num
= hpsb_iso_n_ready(iso
);
57 dev_err(fdtv
->device
, "received at unknown iso channel\n");
61 for (i
= 0; i
< num
; i
++, packet
= (packet
+ 1) % iso
->buf_packets
) {
62 buf
= dma_region_i(&iso
->data_buf
, unsigned char,
63 iso
->infos
[packet
].offset
+ CIP_HEADER_SIZE
);
64 count
= (iso
->infos
[packet
].len
- CIP_HEADER_SIZE
) /
65 (188 + FIREWIRE_HEADER_SIZE
);
67 /* ignore empty packet */
68 if (iso
->infos
[packet
].len
<= CIP_HEADER_SIZE
)
72 if (buf
[FIREWIRE_HEADER_SIZE
] == 0x47)
73 dvb_dmx_swfilter_packets(&fdtv
->demux
,
74 &buf
[FIREWIRE_HEADER_SIZE
], 1);
77 "skipping invalid packet\n");
78 buf
+= 188 + FIREWIRE_HEADER_SIZE
;
82 hpsb_iso_recv_release_packets(iso
, num
);
85 static inline struct node_entry
*node_of(struct firedtv
*fdtv
)
87 return container_of(fdtv
->device
, struct unit_directory
, device
)->ne
;
90 static int node_lock(struct firedtv
*fdtv
, u64 addr
, void *data
, __be32 arg
)
92 return hpsb_node_lock(node_of(fdtv
), addr
, EXTCODE_COMPARE_SWAP
, data
,
93 (__force quadlet_t
)arg
);
96 static int node_read(struct firedtv
*fdtv
, u64 addr
, void *data
, size_t len
)
98 return hpsb_node_read(node_of(fdtv
), addr
, data
, len
);
101 static int node_write(struct firedtv
*fdtv
, u64 addr
, void *data
, size_t len
)
103 return hpsb_node_write(node_of(fdtv
), addr
, data
, len
);
106 #define FDTV_ISO_BUFFER_PACKETS 256
107 #define FDTV_ISO_BUFFER_SIZE (FDTV_ISO_BUFFER_PACKETS * 200)
109 static int start_iso(struct firedtv
*fdtv
)
111 struct hpsb_iso
*iso_handle
;
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 */
119 if (iso_handle
== NULL
) {
120 dev_err(fdtv
->device
, "cannot initialize iso receive\n");
123 fdtv
->backend_data
= iso_handle
;
125 ret
= hpsb_iso_recv_start(iso_handle
, -1, -1, 0);
127 dev_err(fdtv
->device
, "cannot start iso receive\n");
128 hpsb_iso_shutdown(iso_handle
);
129 fdtv
->backend_data
= NULL
;
134 static void stop_iso(struct firedtv
*fdtv
)
136 struct hpsb_iso
*iso_handle
= fdtv
->backend_data
;
138 if (iso_handle
!= NULL
) {
139 hpsb_iso_stop(iso_handle
);
140 hpsb_iso_shutdown(iso_handle
);
142 fdtv
->backend_data
= NULL
;
145 static const struct firedtv_backend fdtv_1394_backend
= {
149 .start_iso
= start_iso
,
150 .stop_iso
= stop_iso
,
153 static void fcp_request(struct hpsb_host
*host
, int nodeid
, int direction
,
154 int cts
, u8
*data
, size_t length
)
156 struct firedtv
*f
, *fdtv
= NULL
;
160 if (length
== 0 || (data
[0] & 0xf0) != 0)
165 spin_lock_irqsave(&node_list_lock
, flags
);
166 list_for_each_entry(f
, &node_list
, list
)
167 if (node_of(f
)->host
== host
&&
168 node_of(f
)->nodeid
== nodeid
&&
169 (f
->subunit
== su
|| (f
->subunit
== 0 && su
== 0x7))) {
173 spin_unlock_irqrestore(&node_list_lock
, flags
);
176 avc_recv(fdtv
, data
, length
);
179 static int node_probe(struct device
*dev
)
181 struct unit_directory
*ud
=
182 container_of(dev
, struct unit_directory
, device
);
183 struct firedtv
*fdtv
;
187 kv_len
= (ud
->model_name_kv
->value
.leaf
.len
- 2) * sizeof(quadlet_t
);
188 kv_str
= CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(ud
->model_name_kv
);
190 fdtv
= fdtv_alloc(dev
, &fdtv_1394_backend
, kv_str
, kv_len
);
195 * Work around a bug in udev's path_id script: Use the fw-host's dev
196 * instead of the unit directory's dev as parent of the input device.
198 err
= fdtv_register_rc(fdtv
, dev
->parent
->parent
);
202 spin_lock_irq(&node_list_lock
);
203 list_add_tail(&fdtv
->list
, &node_list
);
204 spin_unlock_irq(&node_list_lock
);
206 err
= avc_identify_subunit(fdtv
);
210 err
= fdtv_dvb_register(fdtv
);
214 avc_register_remote_control(fdtv
);
217 spin_lock_irq(&node_list_lock
);
218 list_del(&fdtv
->list
);
219 spin_unlock_irq(&node_list_lock
);
220 fdtv_unregister_rc(fdtv
);
226 static int node_remove(struct device
*dev
)
228 struct firedtv
*fdtv
= dev_get_drvdata(dev
);
230 fdtv_dvb_unregister(fdtv
);
232 spin_lock_irq(&node_list_lock
);
233 list_del(&fdtv
->list
);
234 spin_unlock_irq(&node_list_lock
);
236 cancel_work_sync(&fdtv
->remote_ctrl_work
);
237 fdtv_unregister_rc(fdtv
);
243 static int node_update(struct unit_directory
*ud
)
245 struct firedtv
*fdtv
= dev_get_drvdata(&ud
->device
);
247 if (fdtv
->isochannel
>= 0)
248 cmp_establish_pp_connection(fdtv
, fdtv
->subunit
,
253 static struct hpsb_protocol_driver fdtv_driver
= {
255 .update
= node_update
,
258 .remove
= node_remove
,
262 static struct hpsb_highlevel fdtv_highlevel
= {
264 .fcp_request
= fcp_request
,
267 int __init
fdtv_1394_init(struct ieee1394_device_id id_table
[])
271 hpsb_register_highlevel(&fdtv_highlevel
);
272 fdtv_driver
.id_table
= id_table
;
273 ret
= hpsb_register_protocol(&fdtv_driver
);
275 printk(KERN_ERR
"firedtv: failed to register protocol\n");
276 hpsb_unregister_highlevel(&fdtv_highlevel
);
281 void __exit
fdtv_1394_exit(void)
283 hpsb_unregister_protocol(&fdtv_driver
);
284 hpsb_unregister_highlevel(&fdtv_highlevel
);