smscoreapi.c 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178
  1. /*
  2. * Driver for the Siano SMS10xx USB dongle
  3. *
  4. * Copyright (c) 2008 <TODO: INSERT ALL COPYRIGHT OWNERS and MAINT. NAMES HERE>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. *
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. */
  21. /*!
  22. \file smscoreapi.c
  23. \brief Siano core API module
  24. This file contains implementation for the interface to sms core component
  25. \par Copyright (c), 2005-2008 Siano Mobile Silicon, Inc.
  26. \par This program is free software; you can redistribute it and/or modify
  27. it under the terms of the GNU General Public License version 3 as
  28. published by the Free Software Foundation;
  29. Software distributed under the License is distributed on an "AS
  30. IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  31. implied.
  32. \author Anatoly Greenblat
  33. */
  34. #include <linux/kernel.h>
  35. #include <linux/init.h>
  36. #include <linux/module.h>
  37. #include <linux/moduleparam.h>
  38. #include <linux/dma-mapping.h>
  39. #include <linux/delay.h>
  40. #include <asm/io.h>
  41. #include <linux/firmware.h>
  42. #include "smscoreapi.h"
  43. typedef struct _smscore_device_notifyee
  44. {
  45. struct list_head entry;
  46. hotplug_t hotplug;
  47. } smscore_device_notifyee_t;
  48. typedef struct _smscore_client
  49. {
  50. struct list_head entry;
  51. smscore_device_t *coredev;
  52. void *context;
  53. int data_type;
  54. onresponse_t onresponse_handler;
  55. onremove_t onremove_handler;
  56. } *psmscore_client_t;
  57. typedef struct _smscore_subclient
  58. {
  59. struct list_head entry;
  60. smscore_client_t *client;
  61. int id;
  62. } smscore_subclient_t;
  63. typedef struct _smscore_device
  64. {
  65. struct list_head entry;
  66. struct list_head clients;
  67. struct list_head subclients;
  68. spinlock_t clientslock;
  69. struct list_head buffers;
  70. spinlock_t bufferslock;
  71. int num_buffers;
  72. void *common_buffer;
  73. int common_buffer_size;
  74. dma_addr_t common_buffer_phys;
  75. void *context;
  76. struct device *device;
  77. char devpath[32];
  78. unsigned long device_flags;
  79. setmode_t setmode_handler;
  80. detectmode_t detectmode_handler;
  81. sendrequest_t sendrequest_handler;
  82. preload_t preload_handler;
  83. postload_t postload_handler;
  84. int mode, modes_supported;
  85. struct completion version_ex_done, data_download_done, trigger_done;
  86. struct completion init_device_done, reload_start_done, resume_done;
  87. } *psmscore_device_t;
  88. typedef struct _smscore_registry_entry
  89. {
  90. struct list_head entry;
  91. char devpath[32];
  92. int mode;
  93. } smscore_registry_entry_t;
  94. struct list_head g_smscore_notifyees;
  95. struct list_head g_smscore_devices;
  96. kmutex_t g_smscore_deviceslock;
  97. struct list_head g_smscore_registry;
  98. kmutex_t g_smscore_registrylock;
  99. static int default_mode = 1;
  100. module_param(default_mode, int, 0644);
  101. MODULE_PARM_DESC(default_mode, "default firmware id (device mode)");
  102. int smscore_registry_getmode(char* devpath)
  103. {
  104. smscore_registry_entry_t *entry;
  105. struct list_head *next;
  106. kmutex_lock(&g_smscore_registrylock);
  107. for (next = g_smscore_registry.next; next != &g_smscore_registry; next = next->next)
  108. {
  109. entry = (smscore_registry_entry_t *) next;
  110. if (!strcmp(entry->devpath, devpath))
  111. {
  112. kmutex_unlock(&g_smscore_registrylock);
  113. return entry->mode;
  114. }
  115. }
  116. entry = (smscore_registry_entry_t *) kmalloc(sizeof(smscore_registry_entry_t), GFP_KERNEL);
  117. if (entry)
  118. {
  119. entry->mode = default_mode;
  120. strcpy(entry->devpath, devpath);
  121. list_add(&entry->entry, &g_smscore_registry);
  122. }
  123. kmutex_unlock(&g_smscore_registrylock);
  124. return default_mode;
  125. }
  126. void smscore_registry_setmode(char* devpath, int mode)
  127. {
  128. smscore_registry_entry_t *entry;
  129. struct list_head *next;
  130. kmutex_lock(&g_smscore_registrylock);
  131. for (next = g_smscore_registry.next; next != &g_smscore_registry; next = next->next)
  132. {
  133. entry = (smscore_registry_entry_t *) next;
  134. if (!strcmp(entry->devpath, devpath))
  135. {
  136. entry->mode = mode;
  137. break;
  138. }
  139. }
  140. kmutex_unlock(&g_smscore_registrylock);
  141. }
  142. void list_add_locked(struct list_head *new, struct list_head *head, spinlock_t* lock)
  143. {
  144. unsigned long flags;
  145. spin_lock_irqsave(lock, flags);
  146. list_add(new, head);
  147. spin_unlock_irqrestore(lock, flags);
  148. }
  149. /**
  150. * register a client callback that called when device plugged in/unplugged
  151. * NOTE: if devices exist callback is called immediately for each device
  152. *
  153. * @param hotplug callback
  154. *
  155. * @return 0 on success, <0 on error.
  156. */
  157. int smscore_register_hotplug(hotplug_t hotplug)
  158. {
  159. smscore_device_notifyee_t *notifyee;
  160. struct list_head *next, *first;
  161. int rc = 0;
  162. kmutex_lock(&g_smscore_deviceslock);
  163. notifyee = kmalloc(sizeof(smscore_device_notifyee_t), GFP_KERNEL);
  164. if (notifyee)
  165. {
  166. // now notify callback about existing devices
  167. first = &g_smscore_devices;
  168. for (next = first->next; next != first && !rc; next = next->next)
  169. {
  170. smscore_device_t *coredev = (smscore_device_t *) next;
  171. rc = hotplug(coredev, coredev->device, 1);
  172. }
  173. if (rc >= 0)
  174. {
  175. notifyee->hotplug = hotplug;
  176. list_add(&notifyee->entry, &g_smscore_notifyees);
  177. }
  178. else
  179. kfree(notifyee);
  180. }
  181. else
  182. rc = -ENOMEM;
  183. kmutex_unlock(&g_smscore_deviceslock);
  184. return rc;
  185. }
  186. /**
  187. * unregister a client callback that called when device plugged in/unplugged
  188. *
  189. * @param hotplug callback
  190. *
  191. */
  192. void smscore_unregister_hotplug(hotplug_t hotplug)
  193. {
  194. struct list_head *next, *first;
  195. kmutex_lock(&g_smscore_deviceslock);
  196. first = &g_smscore_notifyees;
  197. for (next = first->next; next != first;)
  198. {
  199. smscore_device_notifyee_t *notifyee = (smscore_device_notifyee_t *) next;
  200. next = next->next;
  201. if (notifyee->hotplug == hotplug)
  202. {
  203. list_del(&notifyee->entry);
  204. kfree(notifyee);
  205. }
  206. }
  207. kmutex_unlock(&g_smscore_deviceslock);
  208. }
  209. void smscore_notify_clients(smscore_device_t *coredev)
  210. {
  211. smscore_client_t* client;
  212. // the client must call smscore_unregister_client from remove handler
  213. while (!list_empty(&coredev->clients))
  214. {
  215. client = (smscore_client_t *) coredev->clients.next;
  216. client->onremove_handler(client->context);
  217. }
  218. }
  219. int smscore_notify_callbacks(smscore_device_t *coredev, struct device *device, int arrival)
  220. {
  221. struct list_head *next, *first;
  222. int rc = 0;
  223. // note: must be called under g_deviceslock
  224. first = &g_smscore_notifyees;
  225. for (next = first->next; next != first; next = next->next)
  226. {
  227. rc = ((smscore_device_notifyee_t *) next)->hotplug(coredev, device, arrival);
  228. if (rc < 0)
  229. break;
  230. }
  231. return rc;
  232. }
  233. smscore_buffer_t *smscore_createbuffer(u8* buffer, void* common_buffer, dma_addr_t common_buffer_phys)
  234. {
  235. smscore_buffer_t *cb = kmalloc(sizeof(smscore_buffer_t), GFP_KERNEL);
  236. if (!cb)
  237. {
  238. printk(KERN_INFO "%s kmalloc(...) failed\n", __FUNCTION__);
  239. return NULL;
  240. }
  241. cb->p = buffer;
  242. cb->offset_in_common = buffer - (u8*) common_buffer;
  243. cb->phys = common_buffer_phys + cb->offset_in_common;
  244. return cb;
  245. }
  246. /**
  247. * creates coredev object for a device, prepares buffers, creates buffer mappings, notifies
  248. * registered hotplugs about new device.
  249. *
  250. * @param params device pointer to struct with device specific parameters and handlers
  251. * @param coredev pointer to a value that receives created coredev object
  252. *
  253. * @return 0 on success, <0 on error.
  254. */
  255. int smscore_register_device(smsdevice_params_t *params, smscore_device_t **coredev)
  256. {
  257. smscore_device_t* dev;
  258. u8 *buffer;
  259. dev = kzalloc(sizeof(smscore_device_t), GFP_KERNEL);
  260. if (!dev)
  261. {
  262. printk(KERN_INFO "%s kzalloc(...) failed\n", __FUNCTION__);
  263. return -ENOMEM;
  264. }
  265. // init list entry so it could be safe in smscore_unregister_device
  266. INIT_LIST_HEAD(&dev->entry);
  267. // init queues
  268. INIT_LIST_HEAD(&dev->clients);
  269. INIT_LIST_HEAD(&dev->subclients);
  270. INIT_LIST_HEAD(&dev->buffers);
  271. // init locks
  272. spin_lock_init(&dev->clientslock);
  273. spin_lock_init(&dev->bufferslock);
  274. // init completion events
  275. init_completion(&dev->version_ex_done);
  276. init_completion(&dev->data_download_done);
  277. init_completion(&dev->trigger_done);
  278. init_completion(&dev->init_device_done);
  279. init_completion(&dev->reload_start_done);
  280. init_completion(&dev->resume_done);
  281. // alloc common buffer
  282. dev->common_buffer_size = params->buffer_size * params->num_buffers;
  283. dev->common_buffer = dma_alloc_coherent(NULL, dev->common_buffer_size, &dev->common_buffer_phys, GFP_KERNEL | GFP_DMA);
  284. if (!dev->common_buffer)
  285. {
  286. smscore_unregister_device(dev);
  287. return -ENOMEM;
  288. }
  289. // prepare dma buffers
  290. for (buffer = dev->common_buffer; dev->num_buffers < params->num_buffers; dev->num_buffers ++, buffer += params->buffer_size)
  291. {
  292. smscore_buffer_t *cb = smscore_createbuffer(buffer, dev->common_buffer, dev->common_buffer_phys);
  293. if (!cb)
  294. {
  295. smscore_unregister_device(dev);
  296. return -ENOMEM;
  297. }
  298. smscore_putbuffer(dev, cb);
  299. }
  300. printk(KERN_INFO "%s allocated %d buffers\n", __FUNCTION__, dev->num_buffers);
  301. dev->mode = DEVICE_MODE_NONE;
  302. dev->context = params->context;
  303. dev->device = params->device;
  304. dev->setmode_handler = params->setmode_handler;
  305. dev->detectmode_handler = params->detectmode_handler;
  306. dev->sendrequest_handler = params->sendrequest_handler;
  307. dev->preload_handler = params->preload_handler;
  308. dev->postload_handler = params->postload_handler;
  309. dev->device_flags = params->flags;
  310. strcpy(dev->devpath, params->devpath);
  311. // add device to devices list
  312. kmutex_lock(&g_smscore_deviceslock);
  313. list_add(&dev->entry, &g_smscore_devices);
  314. kmutex_unlock(&g_smscore_deviceslock);
  315. *coredev = dev;
  316. printk(KERN_INFO "%s device %p created\n", __FUNCTION__, dev);
  317. return 0;
  318. }
  319. /**
  320. * sets initial device mode and notifies client hotplugs that device is ready
  321. *
  322. * @param coredev pointer to a coredev object returned by smscore_register_device
  323. *
  324. * @return 0 on success, <0 on error.
  325. */
  326. int smscore_start_device(smscore_device_t *coredev)
  327. {
  328. int rc = smscore_set_device_mode(coredev, smscore_registry_getmode(coredev->devpath));
  329. if (rc < 0)
  330. return rc;
  331. kmutex_lock(&g_smscore_deviceslock);
  332. rc = smscore_notify_callbacks(coredev, coredev->device, 1);
  333. printk(KERN_INFO "%s device %p started, rc %d\n", __FUNCTION__, coredev, rc);
  334. kmutex_unlock(&g_smscore_deviceslock);
  335. return rc;
  336. }
  337. int smscore_sendrequest_and_wait(smscore_device_t *coredev, void* buffer, size_t size, struct completion *completion)
  338. {
  339. int rc = coredev->sendrequest_handler(coredev->context, buffer, size);
  340. if (rc < 0)
  341. return rc;
  342. return wait_for_completion_timeout(completion, msecs_to_jiffies(1000)) ? 0 : -ETIME;
  343. }
  344. int smscore_load_firmware_family2(smscore_device_t *coredev, void *buffer, size_t size)
  345. {
  346. SmsFirmware_ST* firmware = (SmsFirmware_ST*) buffer;
  347. SmsMsgHdr_ST *msg;
  348. UINT32 mem_address = firmware->StartAddress;
  349. u8* payload = firmware->Payload;
  350. int rc = 0;
  351. if (coredev->preload_handler)
  352. {
  353. rc = coredev->preload_handler(coredev->context);
  354. if (rc < 0)
  355. return rc;
  356. }
  357. // PAGE_SIZE buffer shall be enough and dma aligned
  358. msg = (SmsMsgHdr_ST *) kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA);
  359. if (!msg)
  360. return -ENOMEM;
  361. if (coredev->mode != DEVICE_MODE_NONE)
  362. {
  363. SMS_INIT_MSG(msg, MSG_SW_RELOAD_START_REQ, sizeof(SmsMsgHdr_ST));
  364. rc = smscore_sendrequest_and_wait(coredev, msg, msg->msgLength, &coredev->reload_start_done);
  365. mem_address = *(UINT32*) &payload[20];
  366. }
  367. while (size && rc >= 0)
  368. {
  369. SmsDataDownload_ST *DataMsg = (SmsDataDownload_ST *) msg;
  370. int payload_size = min((int) size, SMS_MAX_PAYLOAD_SIZE);
  371. SMS_INIT_MSG(msg, MSG_SMS_DATA_DOWNLOAD_REQ, (UINT16)(sizeof(SmsMsgHdr_ST) + sizeof(UINT32) + payload_size));
  372. DataMsg->MemAddr = mem_address;
  373. memcpy(DataMsg->Payload, payload, payload_size);
  374. if (coredev->device_flags & SMS_ROM_NO_RESPONSE && coredev->mode == DEVICE_MODE_NONE)
  375. rc = coredev->sendrequest_handler(coredev->context, DataMsg, DataMsg->xMsgHeader.msgLength);
  376. else
  377. rc = smscore_sendrequest_and_wait(coredev, DataMsg, DataMsg->xMsgHeader.msgLength, &coredev->data_download_done);
  378. payload += payload_size;
  379. size -= payload_size;
  380. mem_address += payload_size;
  381. }
  382. if (rc >= 0)
  383. {
  384. if (coredev->mode == DEVICE_MODE_NONE)
  385. {
  386. SmsMsgData_ST* TriggerMsg = (SmsMsgData_ST*) msg;
  387. SMS_INIT_MSG(msg, MSG_SMS_SWDOWNLOAD_TRIGGER_REQ, sizeof(SmsMsgHdr_ST) + sizeof(UINT32) * 5);
  388. TriggerMsg->msgData[0] = firmware->StartAddress; // Entry point
  389. TriggerMsg->msgData[1] = 5; // Priority
  390. TriggerMsg->msgData[2] = 0x200; // Stack size
  391. TriggerMsg->msgData[3] = 0; // Parameter
  392. TriggerMsg->msgData[4] = 4; // Task ID
  393. if (coredev->device_flags & SMS_ROM_NO_RESPONSE)
  394. {
  395. rc = coredev->sendrequest_handler(coredev->context, TriggerMsg, TriggerMsg->xMsgHeader.msgLength);
  396. msleep(100);
  397. }
  398. else
  399. rc = smscore_sendrequest_and_wait(coredev, TriggerMsg, TriggerMsg->xMsgHeader.msgLength, &coredev->trigger_done);
  400. }
  401. else
  402. {
  403. SMS_INIT_MSG(msg, MSG_SW_RELOAD_EXEC_REQ, sizeof(SmsMsgHdr_ST));
  404. rc = coredev->sendrequest_handler(coredev->context, msg, msg->msgLength);
  405. }
  406. }
  407. printk("%s %d \n", __func__, rc);
  408. kfree(msg);
  409. return (rc >= 0 && coredev->postload_handler) ?
  410. coredev->postload_handler(coredev->context) :
  411. rc;
  412. }
  413. /**
  414. * loads specified firmware into a buffer and calls device loadfirmware_handler
  415. *
  416. * @param coredev pointer to a coredev object returned by smscore_register_device
  417. * @param filename null-terminated string specifies firmware file name
  418. * @param loadfirmware_handler device handler that loads firmware
  419. *
  420. * @return 0 on success, <0 on error.
  421. */
  422. int smscore_load_firmware(smscore_device_t *coredev, char* filename, loadfirmware_t loadfirmware_handler)
  423. {
  424. int rc = -ENOENT;
  425. const struct firmware *fw;
  426. u8* fw_buffer;
  427. if (loadfirmware_handler == NULL && !(coredev->device_flags & SMS_DEVICE_FAMILY2))
  428. return -EINVAL;
  429. rc = request_firmware(&fw, filename, coredev->device);
  430. if (rc < 0)
  431. {
  432. printk(KERN_INFO "%s failed to open \"%s\"\n", __FUNCTION__, filename);
  433. return rc;
  434. }
  435. fw_buffer = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT), GFP_KERNEL | GFP_DMA);
  436. if (fw_buffer)
  437. {
  438. memcpy(fw_buffer, fw->data, fw->size);
  439. rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ?
  440. smscore_load_firmware_family2(coredev, fw_buffer, fw->size) :
  441. loadfirmware_handler(coredev->context, fw_buffer, fw->size);
  442. kfree(fw_buffer);
  443. }
  444. else
  445. {
  446. printk(KERN_INFO "%s failed to allocate firmware buffer\n", __FUNCTION__);
  447. rc = -ENOMEM;
  448. }
  449. release_firmware(fw);
  450. return rc;
  451. }
  452. /**
  453. * notifies all clients registered with the device, notifies hotplugs, frees all buffers and coredev object
  454. *
  455. * @param coredev pointer to a coredev object returned by smscore_register_device
  456. *
  457. * @return 0 on success, <0 on error.
  458. */
  459. void smscore_unregister_device(smscore_device_t *coredev)
  460. {
  461. smscore_buffer_t *cb;
  462. int num_buffers = 0;
  463. kmutex_lock(&g_smscore_deviceslock);
  464. smscore_notify_clients(coredev);
  465. smscore_notify_callbacks(coredev, NULL, 0);
  466. // at this point all buffers should be back
  467. // onresponse must no longer be called
  468. while (1)
  469. {
  470. while ((cb = smscore_getbuffer(coredev)))
  471. {
  472. kfree(cb);
  473. num_buffers ++;
  474. }
  475. if (num_buffers == coredev->num_buffers)
  476. break;
  477. printk(KERN_INFO "%s waiting for %d buffer(s)\n", __FUNCTION__, coredev->num_buffers - num_buffers);
  478. msleep(100);
  479. }
  480. printk(KERN_INFO "%s freed %d buffers\n", __FUNCTION__, num_buffers);
  481. if (coredev->common_buffer)
  482. dma_free_coherent(NULL, coredev->common_buffer_size, coredev->common_buffer, coredev->common_buffer_phys);
  483. list_del(&coredev->entry);
  484. kfree(coredev);
  485. kmutex_unlock(&g_smscore_deviceslock);
  486. printk(KERN_INFO "%s device %p destroyed\n", __FUNCTION__, coredev);
  487. }
  488. int smscore_detect_mode(smscore_device_t *coredev)
  489. {
  490. void *buffer = kmalloc(sizeof(SmsMsgHdr_ST) + SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
  491. SmsMsgHdr_ST *msg = (SmsMsgHdr_ST *) SMS_ALIGN_ADDRESS(buffer);
  492. int rc;
  493. if (!buffer)
  494. return -ENOMEM;
  495. SMS_INIT_MSG(msg, MSG_SMS_GET_VERSION_EX_REQ, sizeof(SmsMsgHdr_ST));
  496. rc = smscore_sendrequest_and_wait(coredev, msg, msg->msgLength, &coredev->version_ex_done);
  497. if (rc == -ETIME)
  498. {
  499. printk("%s: MSG_SMS_GET_VERSION_EX_REQ failed first try\n", __FUNCTION__);
  500. if (wait_for_completion_timeout(&coredev->resume_done, msecs_to_jiffies(5000)))
  501. {
  502. rc = smscore_sendrequest_and_wait(coredev, msg, msg->msgLength, &coredev->version_ex_done);
  503. if (rc < 0)
  504. {
  505. printk("%s: MSG_SMS_GET_VERSION_EX_REQ failed second try, rc %d\n", __FUNCTION__, rc);
  506. }
  507. }
  508. else
  509. rc = -ETIME;
  510. }
  511. kfree(buffer);
  512. return rc;
  513. }
  514. char *smscore_fw_lkup[] =
  515. {
  516. "dvb_nova_12mhz.inp",
  517. "dvb_nova_12mhz.inp",
  518. "tdmb_nova.inp",
  519. "none",
  520. "dvb_nova_12mhz.inp",
  521. "isdbt_nova_12mhz.inp",
  522. "isdbt_nova_12mhz.inp",
  523. "cmmb_nova_12mhz.inp",
  524. "none",
  525. };
  526. /**
  527. * calls device handler to change mode of operation
  528. * NOTE: stellar/usb may disconnect when changing mode
  529. *
  530. * @param coredev pointer to a coredev object returned by smscore_register_device
  531. * @param mode requested mode of operation
  532. *
  533. * @return 0 on success, <0 on error.
  534. */
  535. int smscore_set_device_mode(smscore_device_t *coredev, int mode)
  536. {
  537. void *buffer;
  538. int rc = 0;
  539. if (coredev->device_flags & SMS_DEVICE_FAMILY2)
  540. {
  541. if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_RAW_TUNER)
  542. {
  543. printk(KERN_INFO "%s invalid mode specified %d\n", __FUNCTION__, mode);
  544. return -EINVAL;
  545. }
  546. if (!(coredev->device_flags & SMS_DEVICE_NOT_READY))
  547. {
  548. rc = smscore_detect_mode(coredev);
  549. if (rc < 0)
  550. return rc;
  551. }
  552. if (coredev->mode == mode)
  553. {
  554. printk(KERN_INFO "%s device mode %d already set\n", __FUNCTION__, mode);
  555. return 0;
  556. }
  557. if (!(coredev->modes_supported & (1 << mode)))
  558. {
  559. rc = smscore_load_firmware(coredev, smscore_fw_lkup[mode], NULL);
  560. if (rc < 0)
  561. return rc;
  562. }
  563. else
  564. {
  565. printk(KERN_INFO "%s mode %d supported by running firmware\n", __FUNCTION__, mode);
  566. }
  567. buffer = kmalloc(sizeof(SmsMsgData_ST) + SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);
  568. if (buffer)
  569. {
  570. SmsMsgData_ST *msg = (SmsMsgData_ST *) SMS_ALIGN_ADDRESS(buffer);
  571. SMS_INIT_MSG(&msg->xMsgHeader, MSG_SMS_INIT_DEVICE_REQ, sizeof(SmsMsgData_ST));
  572. msg->msgData[0] = mode;
  573. rc = smscore_sendrequest_and_wait(coredev, msg, msg->xMsgHeader.msgLength, &coredev->init_device_done);
  574. kfree(buffer);
  575. }
  576. else
  577. rc = -ENOMEM;
  578. }
  579. else
  580. {
  581. if (coredev->detectmode_handler)
  582. coredev->detectmode_handler(coredev->context, &coredev->mode);
  583. if (coredev->mode != mode && coredev->setmode_handler)
  584. rc = coredev->setmode_handler(coredev->context, mode);
  585. }
  586. smscore_registry_setmode(coredev->devpath, mode);
  587. if (rc >= 0)
  588. {
  589. coredev->mode = mode;
  590. coredev->device_flags &= ~SMS_DEVICE_NOT_READY;
  591. }
  592. return rc;
  593. }
  594. /**
  595. * calls device handler to get current mode of operation
  596. *
  597. * @param coredev pointer to a coredev object returned by smscore_register_device
  598. *
  599. * @return current mode
  600. */
  601. int smscore_get_device_mode(smscore_device_t *coredev)
  602. {
  603. return coredev->mode;
  604. }
  605. smscore_client_t* smscore_getclient_by_type(smscore_device_t *coredev, int data_type)
  606. {
  607. smscore_client_t *client = NULL;
  608. struct list_head *next, *first;
  609. unsigned long flags;
  610. if (!data_type)
  611. return NULL;
  612. spin_lock_irqsave(&coredev->clientslock, flags);
  613. first = &coredev->clients;
  614. for (next = first->next; next != first; next = next->next)
  615. {
  616. if (((smscore_client_t*) next)->data_type == data_type)
  617. {
  618. client = (smscore_client_t*) next;
  619. break;
  620. }
  621. }
  622. spin_unlock_irqrestore(&coredev->clientslock, flags);
  623. return client;
  624. }
  625. smscore_client_t* smscore_getclient_by_id(smscore_device_t *coredev, int id)
  626. {
  627. smscore_client_t *client = NULL;
  628. struct list_head *next, *first;
  629. unsigned long flags;
  630. spin_lock_irqsave(&coredev->clientslock, flags);
  631. first = &coredev->subclients;
  632. for (next = first->next; next != first; next = next->next)
  633. {
  634. if (((smscore_subclient_t*) next)->id == id)
  635. {
  636. client = ((smscore_subclient_t*) next)->client;
  637. break;
  638. }
  639. }
  640. spin_unlock_irqrestore(&coredev->clientslock, flags);
  641. return client;
  642. }
  643. /**
  644. * find client by response id/type, call clients onresponse handler
  645. * return buffer to pool on error
  646. *
  647. * @param coredev pointer to a coredev object returned by smscore_register_device
  648. * @param cb pointer to response buffer descriptor
  649. *
  650. */
  651. void smscore_onresponse(smscore_device_t *coredev, smscore_buffer_t *cb)
  652. {
  653. SmsMsgHdr_ST *phdr = (SmsMsgHdr_ST *)((u8*) cb->p + cb->offset);
  654. smscore_client_t * client = smscore_getclient_by_type(coredev, phdr->msgType);
  655. int rc = -EBUSY;
  656. static unsigned long last_sample_time = 0;
  657. static int data_total = 0;
  658. unsigned long time_now = jiffies_to_msecs(jiffies);
  659. if (!last_sample_time)
  660. last_sample_time = time_now;
  661. if (time_now - last_sample_time > 10000)
  662. {
  663. printk("\n%s data rate %d bytes/secs\n", __func__, (int)((data_total * 1000) / (time_now - last_sample_time)));
  664. last_sample_time = time_now;
  665. data_total = 0;
  666. }
  667. data_total += cb->size;
  668. if (!client)
  669. client = smscore_getclient_by_id(coredev, phdr->msgDstId);
  670. if (client)
  671. rc = client->onresponse_handler(client->context, cb);
  672. if (rc < 0)
  673. {
  674. switch (phdr->msgType)
  675. {
  676. case MSG_SMS_GET_VERSION_EX_RES:
  677. {
  678. SmsVersionRes_ST *ver = (SmsVersionRes_ST*) phdr;
  679. printk("%s: MSG_SMS_GET_VERSION_EX_RES id %d prots 0x%x ver %d.%d\n", __FUNCTION__, ver->FirmwareId, ver->SupportedProtocols, ver->RomVersionMajor, ver->RomVersionMinor);
  680. coredev->mode = ver->FirmwareId == 255 ? DEVICE_MODE_NONE : ver->FirmwareId;
  681. coredev->modes_supported = ver->SupportedProtocols;
  682. complete(&coredev->version_ex_done);
  683. break;
  684. }
  685. case MSG_SMS_INIT_DEVICE_RES:
  686. printk("%s: MSG_SMS_INIT_DEVICE_RES\n", __FUNCTION__);
  687. complete(&coredev->init_device_done);
  688. break;
  689. case MSG_SW_RELOAD_START_RES:
  690. printk("%s: MSG_SW_RELOAD_START_RES\n", __FUNCTION__);
  691. complete(&coredev->reload_start_done);
  692. break;
  693. case MSG_SMS_DATA_DOWNLOAD_RES:
  694. complete(&coredev->data_download_done);
  695. break;
  696. case MSG_SW_RELOAD_EXEC_RES:
  697. printk("%s: MSG_SW_RELOAD_EXEC_RES\n", __FUNCTION__);
  698. break;
  699. case MSG_SMS_SWDOWNLOAD_TRIGGER_RES:
  700. printk("%s: MSG_SMS_SWDOWNLOAD_TRIGGER_RES\n", __FUNCTION__);
  701. complete(&coredev->trigger_done);
  702. break;
  703. case MSG_SMS_SLEEP_RESUME_COMP_IND:
  704. complete(&coredev->resume_done);
  705. break;
  706. default:
  707. printk(KERN_INFO "%s no client (%p) or error (%d), type:%d dstid:%d\n", __FUNCTION__, client, rc, phdr->msgType, phdr->msgDstId);
  708. }
  709. smscore_putbuffer(coredev, cb);
  710. }
  711. }
  712. /**
  713. * return pointer to next free buffer descriptor from core pool
  714. *
  715. * @param coredev pointer to a coredev object returned by smscore_register_device
  716. *
  717. * @return pointer to descriptor on success, NULL on error.
  718. */
  719. smscore_buffer_t *smscore_getbuffer(smscore_device_t *coredev)
  720. {
  721. smscore_buffer_t *cb = NULL;
  722. unsigned long flags;
  723. spin_lock_irqsave(&coredev->bufferslock, flags);
  724. if (!list_empty(&coredev->buffers))
  725. {
  726. cb = (smscore_buffer_t *) coredev->buffers.next;
  727. list_del(&cb->entry);
  728. }
  729. spin_unlock_irqrestore(&coredev->bufferslock, flags);
  730. return cb;
  731. }
  732. /**
  733. * return buffer descriptor to a pool
  734. *
  735. * @param coredev pointer to a coredev object returned by smscore_register_device
  736. * @param cb pointer buffer descriptor
  737. *
  738. */
  739. void smscore_putbuffer(smscore_device_t *coredev, smscore_buffer_t *cb)
  740. {
  741. list_add_locked(&cb->entry, &coredev->buffers, &coredev->bufferslock);
  742. }
  743. int smscore_validate_client(smscore_device_t *coredev, smscore_client_t *client, int id)
  744. {
  745. smscore_client_t *existing_client;
  746. smscore_subclient_t *subclient;
  747. if (!id)
  748. return 0;
  749. existing_client = smscore_getclient_by_id(coredev, id);
  750. if (existing_client == client)
  751. return 0;
  752. if (existing_client)
  753. return -EBUSY;
  754. subclient = kzalloc(sizeof(smscore_subclient_t), GFP_KERNEL);
  755. if (!subclient)
  756. return -ENOMEM;
  757. subclient->client = client;
  758. subclient->id = id;
  759. list_add_locked(&subclient->entry, &coredev->subclients, &coredev->clientslock);
  760. return 0;
  761. }
  762. /**
  763. * creates smsclient object, check that id is taken by another client
  764. *
  765. * @param coredev pointer to a coredev object from clients hotplug
  766. * @param initial_id all messages with this id would be sent to this client
  767. * @param data_type all messages of this type would be sent to this client
  768. * @param onresponse_handler client handler that is called to process incoming messages
  769. * @param onremove_handler client handler that is called when device is removed
  770. * @param context client-specific context
  771. * @param client pointer to a value that receives created smsclient object
  772. *
  773. * @return 0 on success, <0 on error.
  774. */
  775. int smscore_register_client(smscore_device_t *coredev, smsclient_params_t *params, smscore_client_t **client)
  776. {
  777. smscore_client_t* newclient;
  778. int rc;
  779. // check that no other channel with same data type exists
  780. if (params->data_type && smscore_getclient_by_type(coredev, params->data_type))
  781. return -EEXIST;
  782. newclient = kzalloc(sizeof(smscore_client_t), GFP_KERNEL);
  783. if (!newclient)
  784. return -ENOMEM;
  785. // check that no other channel with same id exists
  786. rc = smscore_validate_client(coredev, newclient, params->initial_id);
  787. if (rc < 0)
  788. {
  789. kfree(newclient);
  790. return rc;
  791. }
  792. newclient->coredev = coredev;
  793. newclient->data_type = params->data_type;
  794. newclient->onresponse_handler = params->onresponse_handler;
  795. newclient->onremove_handler = params->onremove_handler;
  796. newclient->context = params->context;
  797. list_add_locked(&newclient->entry, &coredev->clients, &coredev->clientslock);
  798. *client = newclient;
  799. printk(KERN_INFO "%s %p %d %d\n", __FUNCTION__, params->context, params->data_type, params->initial_id);
  800. return 0;
  801. }
  802. /**
  803. * frees smsclient object and all subclients associated with it
  804. *
  805. * @param client pointer to smsclient object returned by smscore_register_client
  806. *
  807. */
  808. void smscore_unregister_client(smscore_client_t *client)
  809. {
  810. smscore_device_t *coredev = client->coredev;
  811. struct list_head *next, *first;
  812. unsigned long flags;
  813. spin_lock_irqsave(&coredev->clientslock, flags);
  814. first = &coredev->subclients;
  815. for (next = first->next; next != first;)
  816. {
  817. smscore_subclient_t *subclient = (smscore_subclient_t *) next;
  818. next = next->next;
  819. if (subclient->client == client)
  820. {
  821. list_del(&subclient->entry);
  822. kfree(subclient);
  823. }
  824. }
  825. printk(KERN_INFO "%s %p %d\n", __FUNCTION__, client->context, client->data_type);
  826. list_del(&client->entry);
  827. kfree(client);
  828. spin_unlock_irqrestore(&coredev->clientslock, flags);
  829. }
  830. /**
  831. * verifies that source id is not taken by another client,
  832. * calls device handler to send requests to the device
  833. *
  834. * @param client pointer to smsclient object returned by smscore_register_client
  835. * @param buffer pointer to a request buffer
  836. * @param size size (in bytes) of request buffer
  837. *
  838. * @return 0 on success, <0 on error.
  839. */
  840. int smsclient_sendrequest(smscore_client_t *client, void *buffer, size_t size)
  841. {
  842. smscore_device_t* coredev = client->coredev;
  843. SmsMsgHdr_ST* phdr = (SmsMsgHdr_ST*) buffer;
  844. // check that no other channel with same id exists
  845. int rc = smscore_validate_client(client->coredev, client, phdr->msgSrcId);
  846. if (rc < 0)
  847. return rc;
  848. return coredev->sendrequest_handler(coredev->context, buffer, size);
  849. }
  850. /**
  851. * return the size of large (common) buffer
  852. *
  853. * @param coredev pointer to a coredev object from clients hotplug
  854. *
  855. * @return size (in bytes) of the buffer
  856. */
  857. int smscore_get_common_buffer_size(smscore_device_t *coredev)
  858. {
  859. return coredev->common_buffer_size;
  860. }
  861. /**
  862. * maps common buffer (if supported by platform)
  863. *
  864. * @param coredev pointer to a coredev object from clients hotplug
  865. * @param vma pointer to vma struct from mmap handler
  866. *
  867. * @return 0 on success, <0 on error.
  868. */
  869. int smscore_map_common_buffer(smscore_device_t *coredev, struct vm_area_struct * vma)
  870. {
  871. unsigned long end = vma->vm_end, start = vma->vm_start, size = PAGE_ALIGN(coredev->common_buffer_size);
  872. if (!(vma->vm_flags & (VM_READ | VM_SHARED)) || (vma->vm_flags & VM_WRITE))
  873. {
  874. printk(KERN_INFO "%s invalid vm flags\n", __FUNCTION__);
  875. return -EINVAL;
  876. }
  877. if ((end - start) != size)
  878. {
  879. printk(KERN_INFO "%s invalid size %d expected %d\n", __FUNCTION__, (int)(end - start), (int) size);
  880. return -EINVAL;
  881. }
  882. if (remap_pfn_range(vma, start, coredev->common_buffer_phys >> PAGE_SHIFT, size, pgprot_noncached(vma->vm_page_prot)))
  883. {
  884. printk(KERN_INFO "%s remap_page_range failed\n", __FUNCTION__);
  885. return -EAGAIN;
  886. }
  887. return 0;
  888. }
  889. int smscore_module_init(void)
  890. {
  891. int rc = 0;
  892. INIT_LIST_HEAD(&g_smscore_notifyees);
  893. INIT_LIST_HEAD(&g_smscore_devices);
  894. kmutex_init(&g_smscore_deviceslock);
  895. INIT_LIST_HEAD(&g_smscore_registry);
  896. kmutex_init(&g_smscore_registrylock);
  897. /* USB Register */
  898. rc = smsusb_register();
  899. /* DVB Register */
  900. rc = smsdvb_register();
  901. printk(KERN_INFO "%s, rc %d\n", __FUNCTION__, rc);
  902. return rc;
  903. }
  904. void smscore_module_exit(void)
  905. {
  906. kmutex_lock(&g_smscore_deviceslock);
  907. while (!list_empty(&g_smscore_notifyees))
  908. {
  909. smscore_device_notifyee_t *notifyee = (smscore_device_notifyee_t *) g_smscore_notifyees.next;
  910. list_del(&notifyee->entry);
  911. kfree(notifyee);
  912. }
  913. kmutex_unlock(&g_smscore_deviceslock);
  914. kmutex_lock(&g_smscore_registrylock);
  915. while (!list_empty(&g_smscore_registry))
  916. {
  917. smscore_registry_entry_t *entry = (smscore_registry_entry_t *) g_smscore_registry.next;
  918. list_del(&entry->entry);
  919. kfree(entry);
  920. }
  921. kmutex_unlock(&g_smscore_registrylock);
  922. /* DVB UnRegister */
  923. smsdvb_unregister();
  924. /* Unregister USB */
  925. smsusb_unregister();
  926. printk(KERN_INFO "%s\n", __FUNCTION__);
  927. }
  928. module_init(smscore_module_init);
  929. module_exit(smscore_module_exit);
  930. MODULE_DESCRIPTION("smscore");
  931. MODULE_AUTHOR("Anatoly Greenblatt,,, (anatolyg@siano-ms.com)");
  932. MODULE_LICENSE("GPL");