firesat_1394.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468
  1. /*
  2. * FireSAT DVB driver
  3. *
  4. * Copyright (c) 2004 Andreas Monitzer <andy@monitzer.com>
  5. * Copyright (c) 2007-2008 Ben Backx <ben@bbackx.com>
  6. *
  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.
  11. */
  12. #include <linux/init.h>
  13. #include <linux/slab.h>
  14. #include <linux/wait.h>
  15. #include <linux/module.h>
  16. #include <linux/delay.h>
  17. #include <linux/time.h>
  18. #include <linux/errno.h>
  19. #include <linux/interrupt.h>
  20. #include <linux/semaphore.h>
  21. #include <ieee1394_hotplug.h>
  22. #include <nodemgr.h>
  23. #include <highlevel.h>
  24. #include <ohci1394.h>
  25. #include <hosts.h>
  26. #include <dvbdev.h>
  27. #include "firesat.h"
  28. #include "avc_api.h"
  29. #include "cmp.h"
  30. #include "firesat-rc.h"
  31. #include "firesat-ci.h"
  32. #define FIRESAT_Vendor_ID 0x001287
  33. static struct ieee1394_device_id firesat_id_table[] = {
  34. {
  35. /* FloppyDTV S/CI and FloppyDTV S2 */
  36. .match_flags = IEEE1394_MATCH_MODEL_ID | IEEE1394_MATCH_SPECIFIER_ID,
  37. .model_id = 0x000024,
  38. .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff,
  39. },{
  40. /* FloppyDTV T/CI */
  41. .match_flags = IEEE1394_MATCH_MODEL_ID | IEEE1394_MATCH_SPECIFIER_ID,
  42. .model_id = 0x000025,
  43. .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff,
  44. },{
  45. /* FloppyDTV C/CI */
  46. .match_flags = IEEE1394_MATCH_MODEL_ID | IEEE1394_MATCH_SPECIFIER_ID,
  47. .model_id = 0x000026,
  48. .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff,
  49. },{
  50. /* FireDTV S/CI and FloppyDTV S2 */
  51. .match_flags = IEEE1394_MATCH_MODEL_ID | IEEE1394_MATCH_SPECIFIER_ID,
  52. .model_id = 0x000034,
  53. .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff,
  54. },{
  55. /* FireDTV T/CI */
  56. .match_flags = IEEE1394_MATCH_MODEL_ID | IEEE1394_MATCH_SPECIFIER_ID,
  57. .model_id = 0x000035,
  58. .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff,
  59. },{
  60. /* FireDTV C/CI */
  61. .match_flags = IEEE1394_MATCH_MODEL_ID | IEEE1394_MATCH_SPECIFIER_ID,
  62. .model_id = 0x000036,
  63. .specifier_id = AVC_UNIT_SPEC_ID_ENTRY & 0xffffff,
  64. }, { }
  65. };
  66. MODULE_DEVICE_TABLE(ieee1394, firesat_id_table);
  67. /* list of all firesat devices */
  68. LIST_HEAD(firesat_list);
  69. spinlock_t firesat_list_lock = SPIN_LOCK_UNLOCKED;
  70. static void firesat_add_host(struct hpsb_host *host);
  71. static void firesat_remove_host(struct hpsb_host *host);
  72. static void firesat_host_reset(struct hpsb_host *host);
  73. /*
  74. static void iso_receive(struct hpsb_host *host, int channel, quadlet_t *data,
  75. size_t length);
  76. */
  77. static void fcp_request(struct hpsb_host *host,
  78. int nodeid,
  79. int direction,
  80. int cts,
  81. u8 *data,
  82. size_t length);
  83. static struct hpsb_highlevel firesat_highlevel = {
  84. .name = "FireSAT",
  85. .add_host = firesat_add_host,
  86. .remove_host = firesat_remove_host,
  87. .host_reset = firesat_host_reset,
  88. // FIXME .iso_receive = iso_receive,
  89. .fcp_request = fcp_request,
  90. };
  91. static void firesat_add_host (struct hpsb_host *host)
  92. {
  93. struct ti_ohci *ohci = (struct ti_ohci *)host->hostdata;
  94. /* We only work with the OHCI-1394 driver */
  95. if (strcmp(host->driver->name, OHCI1394_DRIVER_NAME))
  96. return;
  97. if (!hpsb_create_hostinfo(&firesat_highlevel, host, 0)) {
  98. printk(KERN_ERR "Cannot allocate hostinfo\n");
  99. return;
  100. }
  101. hpsb_set_hostinfo(&firesat_highlevel, host, ohci);
  102. hpsb_set_hostinfo_key(&firesat_highlevel, host, ohci->host->id);
  103. }
  104. static void firesat_remove_host (struct hpsb_host *host)
  105. {
  106. }
  107. static void firesat_host_reset(struct hpsb_host *host)
  108. {
  109. printk(KERN_INFO "FireSAT host_reset (nodeid = 0x%x, hosts active = %d)\n",host->node_id,host->nodes_active);
  110. }
  111. struct firewireheader {
  112. union {
  113. struct {
  114. unsigned char tcode:4;
  115. unsigned char sy:4;
  116. unsigned char tag:2;
  117. unsigned char channel:6;
  118. unsigned char length_l;
  119. unsigned char length_h;
  120. } hdr;
  121. unsigned long val;
  122. };
  123. };
  124. struct CIPHeader {
  125. union {
  126. struct {
  127. unsigned char syncbits:2;
  128. unsigned char sid:6;
  129. unsigned char dbs;
  130. unsigned char fn:2;
  131. unsigned char qpc:3;
  132. unsigned char sph:1;
  133. unsigned char rsv:2;
  134. unsigned char dbc;
  135. unsigned char syncbits2:2;
  136. unsigned char fmt:6;
  137. unsigned long fdf:24;
  138. } cip;
  139. unsigned long long val;
  140. };
  141. };
  142. struct MPEG2Header {
  143. union {
  144. struct {
  145. unsigned char sync; // must be 0x47
  146. unsigned char transport_error_indicator:1;
  147. unsigned char payload_unit_start_indicator:1;
  148. unsigned char transport_priority:1;
  149. unsigned short pid:13;
  150. unsigned char transport_scrambling_control:2;
  151. unsigned char adaption_field_control:2;
  152. unsigned char continuity_counter:4;
  153. } hdr;
  154. unsigned long val;
  155. };
  156. };
  157. #if 0
  158. static void iso_receive(struct hpsb_host *host,
  159. int channel,
  160. quadlet_t *data,
  161. size_t length)
  162. {
  163. struct firesat *firesat = NULL;
  164. struct firesat *firesat_entry;
  165. unsigned long flags;
  166. // printk(KERN_INFO "FireSAT iso_receive: channel %d, length = %d\n", channel, length);
  167. if (length <= 12)
  168. return; // ignore empty packets
  169. else {
  170. spin_lock_irqsave(&firesat_list_lock, flags);
  171. list_for_each_entry(firesat_entry,&firesat_list,list) {
  172. if(firesat_entry->host == host && firesat_entry->isochannel == channel) {
  173. firesat=firesat_entry;
  174. break;
  175. }
  176. }
  177. spin_unlock_irqrestore(&firesat_list_lock, flags);
  178. if (firesat) {
  179. char *buf= ((char*)data) + sizeof(struct firewireheader)+sizeof(struct CIPHeader);
  180. int count = (length-sizeof(struct CIPHeader)) / 192;
  181. // 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]);
  182. while (count--) {
  183. if (buf[sizeof(quadlet_t) /*timestamp*/] == 0x47)
  184. dvb_dmx_swfilter_packets(&firesat->demux, &buf[sizeof(quadlet_t)], 1);
  185. else
  186. printk("%s: invalid packet, skipping\n", __func__);
  187. buf += 188 + sizeof (quadlet_t) /* timestamp */;
  188. }
  189. }
  190. }
  191. }
  192. #endif
  193. static void fcp_request(struct hpsb_host *host,
  194. int nodeid,
  195. int direction,
  196. int cts,
  197. u8 *data,
  198. size_t length)
  199. {
  200. struct firesat *firesat = NULL;
  201. struct firesat *firesat_entry;
  202. unsigned long flags;
  203. if (length > 0 && ((data[0] & 0xf0) >> 4) == 0) {
  204. spin_lock_irqsave(&firesat_list_lock, flags);
  205. list_for_each_entry(firesat_entry,&firesat_list,list) {
  206. if (firesat_entry->host == host &&
  207. firesat_entry->nodeentry->nodeid == nodeid &&
  208. (firesat_entry->subunit == (data[1]&0x7) ||
  209. (firesat_entry->subunit == 0 &&
  210. (data[1]&0x7) == 0x7))) {
  211. firesat=firesat_entry;
  212. break;
  213. }
  214. }
  215. spin_unlock_irqrestore(&firesat_list_lock, flags);
  216. if (firesat)
  217. AVCRecv(firesat,data,length);
  218. else
  219. printk("%s: received fcp request from unknown source, ignored\n", __func__);
  220. } // else ignore
  221. }
  222. static int firesat_probe(struct device *dev)
  223. {
  224. struct unit_directory *ud = container_of(dev, struct unit_directory, device);
  225. struct firesat *firesat;
  226. struct dvb_frontend *fe;
  227. unsigned long flags;
  228. int result;
  229. unsigned char subunitcount = 0xff, subunit;
  230. struct firesat **firesats = kmalloc(sizeof (void*) * 2,GFP_KERNEL);
  231. if (!firesats) {
  232. printk("%s: couldn't allocate memory.\n", __func__);
  233. return -ENOMEM;
  234. }
  235. // 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);
  236. printk(KERN_INFO "%s: loading device\n", __func__);
  237. firesats[0] = NULL;
  238. firesats[1] = NULL;
  239. ud->device.driver_data = firesats;
  240. for (subunit = 0; subunit < subunitcount; subunit++) {
  241. if (!(firesat = kmalloc(sizeof (struct firesat), GFP_KERNEL)) ||
  242. !(fe = kmalloc(sizeof (struct dvb_frontend), GFP_KERNEL))) {
  243. printk("%s: couldn't allocate memory.\n", __func__);
  244. kfree(firesats);
  245. return -ENOMEM;
  246. }
  247. memset(firesat, 0, sizeof (struct firesat));
  248. firesat->host = ud->ne->host;
  249. firesat->guid = ud->ne->guid;
  250. firesat->guid_vendor_id = ud->ne->guid_vendor_id;
  251. firesat->nodeentry = ud->ne;
  252. firesat->isochannel = -1;
  253. firesat->tone = 0xff;
  254. firesat->voltage = 0xff;
  255. if (!(firesat->respfrm = kmalloc(sizeof (AVCRspFrm), GFP_KERNEL))) {
  256. printk("%s: couldn't allocate memory.\n", __func__);
  257. kfree(firesat);
  258. return -ENOMEM;
  259. }
  260. sema_init(&firesat->avc_sem, 1);
  261. atomic_set(&firesat->avc_reply_received, 1);
  262. sema_init(&firesat->demux_sem, 1);
  263. atomic_set(&firesat->reschedule_remotecontrol, 0);
  264. spin_lock_irqsave(&firesat_list_lock, flags);
  265. INIT_LIST_HEAD(&firesat->list);
  266. list_add_tail(&firesat->list, &firesat_list);
  267. spin_unlock_irqrestore(&firesat_list_lock, flags);
  268. if (subunit == 0) {
  269. firesat->subunit = 0x7; // 0x7 = don't care
  270. if (AVCSubUnitInfo(firesat, &subunitcount)) {
  271. printk("%s: AVC subunit info command failed.\n",__func__);
  272. spin_lock_irqsave(&firesat_list_lock, flags);
  273. list_del(&firesat->list);
  274. spin_unlock_irqrestore(&firesat_list_lock, flags);
  275. kfree(firesat);
  276. return -EIO;
  277. }
  278. }
  279. printk(KERN_INFO "%s: subunit count = %d\n", __func__, subunitcount);
  280. firesat->subunit = subunit;
  281. if (AVCIdentifySubunit(firesat, NULL, (int*)&firesat->type, &firesat->has_ci)) {
  282. printk("%s: cannot identify subunit %d\n", __func__, subunit);
  283. spin_lock_irqsave(&firesat_list_lock, flags);
  284. list_del(&firesat->list);
  285. spin_unlock_irqrestore(&firesat_list_lock, flags);
  286. kfree(firesat);
  287. continue;
  288. }
  289. // ----
  290. firesat_dvbdev_init(firesat, dev, fe);
  291. // ----
  292. firesats[subunit] = firesat;
  293. } // loop for all tuners
  294. //beta ;-) Disable remote control stuff to avoid crashing
  295. //if(firesats[0])
  296. // AVCRegisterRemoteControl(firesats[0]);
  297. return 0;
  298. }
  299. static int firesat_remove(struct device *dev)
  300. {
  301. struct unit_directory *ud = container_of(dev, struct unit_directory, device);
  302. struct dvb_frontend* fe;
  303. struct firesat **firesats = ud->device.driver_data;
  304. int k;
  305. unsigned long flags;
  306. if (firesats) {
  307. for (k = 0; k < 2; k++)
  308. if (firesats[k]) {
  309. if (firesats[k]->has_ci)
  310. firesat_ca_release(firesats[k]);
  311. #if 0
  312. if (!(fe = kmalloc(sizeof (struct dvb_frontend), GFP_KERNEL))) {
  313. fe->ops = firesat_ops;
  314. fe->dvb = firesats[k]->adapter;
  315. dvb_unregister_frontend(fe);
  316. kfree(fe);
  317. }
  318. #endif
  319. dvb_net_release(&firesats[k]->dvbnet);
  320. firesats[k]->demux.dmx.close(&firesats[k]->demux.dmx);
  321. firesats[k]->demux.dmx.remove_frontend(&firesats[k]->demux.dmx, &firesats[k]->frontend);
  322. dvb_dmxdev_release(&firesats[k]->dmxdev);
  323. dvb_dmx_release(&firesats[k]->demux);
  324. dvb_unregister_adapter(firesats[k]->adapter);
  325. spin_lock_irqsave(&firesat_list_lock, flags);
  326. list_del(&firesats[k]->list);
  327. spin_unlock_irqrestore(&firesat_list_lock, flags);
  328. kfree(firesats[k]->adapter);
  329. kfree(firesats[k]->respfrm);
  330. kfree(firesats[k]);
  331. }
  332. kfree(firesats);
  333. } else
  334. printk("%s: can't get firesat handle\n", __func__);
  335. printk(KERN_INFO "FireSAT: Removing device with vendor id 0x%x, model id 0x%x.\n",ud->vendor_id,ud->model_id);
  336. return 0;
  337. }
  338. static int firesat_update(struct unit_directory *ud)
  339. {
  340. struct firesat **firesats = ud->device.driver_data;
  341. int k;
  342. // loop over subunits
  343. for (k = 0; k < 2; k++)
  344. if (firesats[k]) {
  345. firesats[k]->nodeentry = ud->ne;
  346. if (firesats[k]->isochannel >= 0)
  347. try_CMPEstablishPPconnection(firesats[k], firesats[k]->subunit, firesats[k]->isochannel);
  348. }
  349. return 0;
  350. }
  351. static struct hpsb_protocol_driver firesat_driver = {
  352. .name = "FireSAT",
  353. .id_table = firesat_id_table,
  354. .update = firesat_update,
  355. .driver = {
  356. //.name and .bus are filled in for us in more recent linux versions
  357. //.name = "FireSAT",
  358. //.bus = &ieee1394_bus_type,
  359. .probe = firesat_probe,
  360. .remove = firesat_remove,
  361. },
  362. };
  363. static int __init firesat_init(void)
  364. {
  365. int ret;
  366. printk(KERN_INFO "FireSAT loaded\n");
  367. hpsb_register_highlevel(&firesat_highlevel);
  368. ret = hpsb_register_protocol(&firesat_driver);
  369. if (ret) {
  370. printk(KERN_ERR "FireSAT: failed to register protocol\n");
  371. hpsb_unregister_highlevel(&firesat_highlevel);
  372. return ret;
  373. }
  374. //Crash in this function, just disable RC for the time being...
  375. //Don't forget to uncomment in firesat_exit and firesat_probe when you enable this.
  376. /*if((ret=firesat_register_rc()))
  377. printk("%s: firesat_register_rc return error code %d (ignored)\n", __func__, ret);*/
  378. return 0;
  379. }
  380. static void __exit firesat_exit(void)
  381. {
  382. hpsb_unregister_protocol(&firesat_driver);
  383. hpsb_unregister_highlevel(&firesat_highlevel);
  384. printk(KERN_INFO "FireSAT quit\n");
  385. }
  386. module_init(firesat_init);
  387. module_exit(firesat_exit);
  388. MODULE_AUTHOR("Andreas Monitzer <andy@monitzer.com>");
  389. MODULE_AUTHOR("Ben Backx <ben@bbackx.com>");
  390. MODULE_DESCRIPTION("FireSAT DVB Driver");
  391. MODULE_LICENSE("GPL");
  392. MODULE_SUPPORTED_DEVICE("FireSAT DVB");