4 * Copyright (c) 2004 Andreas Monitzer <andy@monitzer.com>
5 * Copyright (c) 2007-2008 Ben Backx <ben@bbackx.com>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
13 #include <linux/init.h>
14 #include <linux/slab.h>
15 #include <linux/wait.h>
16 #include <linux/module.h>
17 #include <linux/delay.h>
18 #include <linux/time.h>
19 #include <linux/errno.h>
20 #include <linux/interrupt.h>
21 #include <linux/semaphore.h>
22 #include <ieee1394_hotplug.h>
24 #include <highlevel.h>
32 #include "firesat-rc.h"
33 #include "firesat-ci.h"
35 #define FIRESAT_Vendor_ID 0x001287
37 static struct ieee1394_device_id firesat_id_table
[] = {
40 /* FloppyDTV S/CI and FloppyDTV S2 */
41 .match_flags
= IEEE1394_MATCH_MODEL_ID
| IEEE1394_MATCH_SPECIFIER_ID
,
43 .specifier_id
= AVC_UNIT_SPEC_ID_ENTRY
& 0xffffff,
46 .match_flags
= IEEE1394_MATCH_MODEL_ID
| IEEE1394_MATCH_SPECIFIER_ID
,
48 .specifier_id
= AVC_UNIT_SPEC_ID_ENTRY
& 0xffffff,
51 .match_flags
= IEEE1394_MATCH_MODEL_ID
| IEEE1394_MATCH_SPECIFIER_ID
,
53 .specifier_id
= AVC_UNIT_SPEC_ID_ENTRY
& 0xffffff,
55 /* FireDTV S/CI and FloppyDTV S2 */
56 .match_flags
= IEEE1394_MATCH_MODEL_ID
| IEEE1394_MATCH_SPECIFIER_ID
,
58 .specifier_id
= AVC_UNIT_SPEC_ID_ENTRY
& 0xffffff,
61 .match_flags
= IEEE1394_MATCH_MODEL_ID
| IEEE1394_MATCH_SPECIFIER_ID
,
63 .specifier_id
= AVC_UNIT_SPEC_ID_ENTRY
& 0xffffff,
66 .match_flags
= IEEE1394_MATCH_MODEL_ID
| IEEE1394_MATCH_SPECIFIER_ID
,
68 .specifier_id
= AVC_UNIT_SPEC_ID_ENTRY
& 0xffffff,
72 MODULE_DEVICE_TABLE(ieee1394
, firesat_id_table
);
74 /* list of all firesat devices */
75 LIST_HEAD(firesat_list
);
76 spinlock_t firesat_list_lock
= SPIN_LOCK_UNLOCKED
;
78 static void firesat_add_host(struct hpsb_host
*host
);
79 static void firesat_remove_host(struct hpsb_host
*host
);
80 static void firesat_host_reset(struct hpsb_host
*host
);
83 static void iso_receive(struct hpsb_host *host, int channel, quadlet_t *data,
87 static void fcp_request(struct hpsb_host
*host
,
94 static struct hpsb_highlevel firesat_highlevel
= {
96 .add_host
= firesat_add_host
,
97 .remove_host
= firesat_remove_host
,
98 .host_reset
= firesat_host_reset
,
99 // FIXME .iso_receive = iso_receive,
100 .fcp_request
= fcp_request
,
103 static void firesat_add_host (struct hpsb_host
*host
)
105 struct ti_ohci
*ohci
= (struct ti_ohci
*)host
->hostdata
;
107 /* We only work with the OHCI-1394 driver */
108 if (strcmp(host
->driver
->name
, OHCI1394_DRIVER_NAME
))
111 if (!hpsb_create_hostinfo(&firesat_highlevel
, host
, 0)) {
112 printk(KERN_ERR
"Cannot allocate hostinfo\n");
116 hpsb_set_hostinfo(&firesat_highlevel
, host
, ohci
);
117 hpsb_set_hostinfo_key(&firesat_highlevel
, host
, ohci
->host
->id
);
120 static void firesat_remove_host (struct hpsb_host
*host
)
125 static void firesat_host_reset(struct hpsb_host
*host
)
127 printk(KERN_INFO
"FireSAT host_reset (nodeid = 0x%x, hosts active = %d)\n",host
->node_id
,host
->nodes_active
);
130 struct firewireheader
{
133 unsigned char tcode
:4;
136 unsigned char channel
:6;
138 unsigned char length_l
;
139 unsigned char length_h
;
148 unsigned char syncbits
:2;
156 unsigned char syncbits2
:2;
158 unsigned long fdf
:24;
160 unsigned long long val
;
167 unsigned char sync
; // must be 0x47
168 unsigned char transport_error_indicator
:1;
169 unsigned char payload_unit_start_indicator
:1;
170 unsigned char transport_priority
:1;
171 unsigned short pid
:13;
172 unsigned char transport_scrambling_control
:2;
173 unsigned char adaption_field_control
:2;
174 unsigned char continuity_counter
:4;
181 static void iso_receive(struct hpsb_host
*host
,
186 struct firesat
*firesat
= NULL
;
187 struct firesat
*firesat_entry
;
190 // printk(KERN_INFO "FireSAT iso_receive: channel %d, length = %d\n", channel, length);
193 return; // ignore empty packets
196 spin_lock_irqsave(&firesat_list_lock
, flags
);
197 list_for_each_entry(firesat_entry
,&firesat_list
,list
) {
198 if(firesat_entry
->host
== host
&& firesat_entry
->isochannel
== channel
) {
199 firesat
=firesat_entry
;
203 spin_unlock_irqrestore(&firesat_list_lock
, flags
);
206 char *buf
= ((char*)data
) + sizeof(struct firewireheader
)+sizeof(struct CIPHeader
);
207 int count
= (length
-sizeof(struct CIPHeader
)) / 192;
209 // printk(KERN_INFO "%s: length = %u\n data[0] = %08x\n data[1] = %08x\n data[2] = %08x\n data[3] = %08x\n data[4] = %08x\n",__func__, length, data[0],data[1],data[2],data[3],data[4]);
213 if (buf
[sizeof(quadlet_t
) /*timestamp*/] == 0x47)
214 dvb_dmx_swfilter_packets(&firesat
->demux
, &buf
[sizeof(quadlet_t
)], 1);
216 printk("%s: invalid packet, skipping\n", __func__
);
217 buf
+= 188 + sizeof (quadlet_t
) /* timestamp */;
224 static void fcp_request(struct hpsb_host
*host
,
231 struct firesat
*firesat
= NULL
;
232 struct firesat
*firesat_entry
;
235 if (length
> 0 && ((data
[0] & 0xf0) >> 4) == 0) {
237 spin_lock_irqsave(&firesat_list_lock
, flags
);
238 list_for_each_entry(firesat_entry
,&firesat_list
,list
) {
239 if (firesat_entry
->host
== host
&&
240 firesat_entry
->nodeentry
->nodeid
== nodeid
&&
241 (firesat_entry
->subunit
== (data
[1]&0x7) ||
242 (firesat_entry
->subunit
== 0 &&
243 (data
[1]&0x7) == 0x7))) {
244 firesat
=firesat_entry
;
248 spin_unlock_irqrestore(&firesat_list_lock
, flags
);
251 AVCRecv(firesat
,data
,length
);
253 printk("%s: received fcp request from unknown source, ignored\n", __func__
);
257 static int firesat_probe(struct device
*dev
)
259 struct unit_directory
*ud
= container_of(dev
, struct unit_directory
, device
);
260 struct firesat
*firesat
;
261 struct dvb_frontend
*fe
;
264 unsigned char subunitcount
= 0xff, subunit
;
265 struct firesat
**firesats
= kmalloc(sizeof (void*) * 2,GFP_KERNEL
);
268 printk("%s: couldn't allocate memory.\n", __func__
);
272 // printk(KERN_INFO "FireSAT: Detected device with GUID %08lx%04lx%04lx\n",(unsigned long)((ud->ne->guid)>>32),(unsigned long)(ud->ne->guid & 0xFFFF),(unsigned long)ud->ne->guid_vendor_id);
273 printk(KERN_INFO
"%s: loading device\n", __func__
);
278 ud
->device
.driver_data
= firesats
;
280 for (subunit
= 0; subunit
< subunitcount
; subunit
++) {
282 if (!(firesat
= kmalloc(sizeof (struct firesat
), GFP_KERNEL
)) ||
283 !(fe
= kmalloc(sizeof (struct dvb_frontend
), GFP_KERNEL
))) {
285 printk("%s: couldn't allocate memory.\n", __func__
);
290 memset(firesat
, 0, sizeof (struct firesat
));
292 firesat
->host
= ud
->ne
->host
;
293 firesat
->guid
= ud
->ne
->guid
;
294 firesat
->guid_vendor_id
= ud
->ne
->guid_vendor_id
;
295 firesat
->nodeentry
= ud
->ne
;
296 firesat
->isochannel
= -1;
297 firesat
->tone
= 0xff;
298 firesat
->voltage
= 0xff;
300 if (!(firesat
->respfrm
= kmalloc(sizeof (AVCRspFrm
), GFP_KERNEL
))) {
301 printk("%s: couldn't allocate memory.\n", __func__
);
306 sema_init(&firesat
->avc_sem
, 1);
307 atomic_set(&firesat
->avc_reply_received
, 1);
308 sema_init(&firesat
->demux_sem
, 1);
309 atomic_set(&firesat
->reschedule_remotecontrol
, 0);
311 spin_lock_irqsave(&firesat_list_lock
, flags
);
312 INIT_LIST_HEAD(&firesat
->list
);
313 list_add_tail(&firesat
->list
, &firesat_list
);
314 spin_unlock_irqrestore(&firesat_list_lock
, flags
);
317 firesat
->subunit
= 0x7; // 0x7 = don't care
318 if (AVCSubUnitInfo(firesat
, &subunitcount
)) {
319 printk("%s: AVC subunit info command failed.\n",__func__
);
320 spin_lock_irqsave(&firesat_list_lock
, flags
);
321 list_del(&firesat
->list
);
322 spin_unlock_irqrestore(&firesat_list_lock
, flags
);
328 printk(KERN_INFO
"%s: subunit count = %d\n", __func__
, subunitcount
);
330 firesat
->subunit
= subunit
;
332 if (AVCIdentifySubunit(firesat
, NULL
, (int*)&firesat
->type
, &firesat
->has_ci
)) {
333 printk("%s: cannot identify subunit %d\n", __func__
, subunit
);
334 spin_lock_irqsave(&firesat_list_lock
, flags
);
335 list_del(&firesat
->list
);
336 spin_unlock_irqrestore(&firesat_list_lock
, flags
);
342 firesat_dvbdev_init(firesat
, dev
, fe
);
344 firesats
[subunit
] = firesat
;
345 } // loop for all tuners
347 //beta ;-) Disable remote control stuff to avoid crashing
349 // AVCRegisterRemoteControl(firesats[0]);
354 static int firesat_remove(struct device
*dev
)
356 struct unit_directory
*ud
= container_of(dev
, struct unit_directory
, device
);
357 struct dvb_frontend
* fe
;
358 struct firesat
**firesats
= ud
->device
.driver_data
;
363 for (k
= 0; k
< 2; k
++)
365 if (firesats
[k
]->has_ci
)
366 firesat_ca_release(firesats
[k
]);
369 if (!(fe
= kmalloc(sizeof (struct dvb_frontend
), GFP_KERNEL
))) {
370 fe
->ops
= firesat_ops
;
371 fe
->dvb
= firesats
[k
]->adapter
;
373 dvb_unregister_frontend(fe
);
377 dvb_net_release(&firesats
[k
]->dvbnet
);
378 firesats
[k
]->demux
.dmx
.close(&firesats
[k
]->demux
.dmx
);
379 firesats
[k
]->demux
.dmx
.remove_frontend(&firesats
[k
]->demux
.dmx
, &firesats
[k
]->frontend
);
380 dvb_dmxdev_release(&firesats
[k
]->dmxdev
);
381 dvb_dmx_release(&firesats
[k
]->demux
);
382 dvb_unregister_adapter(firesats
[k
]->adapter
);
384 spin_lock_irqsave(&firesat_list_lock
, flags
);
385 list_del(&firesats
[k
]->list
);
386 spin_unlock_irqrestore(&firesat_list_lock
, flags
);
388 kfree(firesats
[k
]->adapter
);
389 kfree(firesats
[k
]->respfrm
);
394 printk("%s: can't get firesat handle\n", __func__
);
396 printk(KERN_INFO
"FireSAT: Removing device with vendor id 0x%x, model id 0x%x.\n",ud
->vendor_id
,ud
->model_id
);
401 static int firesat_update(struct unit_directory
*ud
)
403 struct firesat
**firesats
= ud
->device
.driver_data
;
405 // loop over subunits
407 for (k
= 0; k
< 2; k
++)
409 firesats
[k
]->nodeentry
= ud
->ne
;
411 if (firesats
[k
]->isochannel
>= 0)
412 try_CMPEstablishPPconnection(firesats
[k
], firesats
[k
]->subunit
, firesats
[k
]->isochannel
);
418 static struct hpsb_protocol_driver firesat_driver
= {
421 .id_table
= firesat_id_table
,
422 .update
= firesat_update
,
425 //.name and .bus are filled in for us in more recent linux versions
427 //.bus = &ieee1394_bus_type,
428 .probe
= firesat_probe
,
429 .remove
= firesat_remove
,
433 static int __init
firesat_init(void)
437 printk(KERN_INFO
"FireSAT loaded\n");
438 hpsb_register_highlevel(&firesat_highlevel
);
439 ret
= hpsb_register_protocol(&firesat_driver
);
441 printk(KERN_ERR
"FireSAT: failed to register protocol\n");
442 hpsb_unregister_highlevel(&firesat_highlevel
);
446 //Crash in this function, just disable RC for the time being...
447 //Don't forget to uncomment in firesat_exit and firesat_probe when you enable this.
448 /*if((ret=firesat_register_rc()))
449 printk("%s: firesat_register_rc return error code %d (ignored)\n", __func__, ret);*/
454 static void __exit
firesat_exit(void)
456 hpsb_unregister_protocol(&firesat_driver
);
457 hpsb_unregister_highlevel(&firesat_highlevel
);
458 printk(KERN_INFO
"FireSAT quit\n");
461 module_init(firesat_init
);
462 module_exit(firesat_exit
);
464 MODULE_AUTHOR("Andreas Monitzer <andy@monitzer.com>");
465 MODULE_AUTHOR("Ben Backx <ben@bbackx.com>");
466 MODULE_DESCRIPTION("FireSAT DVB Driver");
467 MODULE_LICENSE("GPL");
468 MODULE_SUPPORTED_DEVICE("FireSAT DVB");