hpimsgx.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810
  1. /******************************************************************************
  2. AudioScience HPI driver
  3. Copyright (C) 1997-2014 AudioScience Inc. <support@audioscience.com>
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of version 2 of the GNU General Public License as
  6. published by the Free Software Foundation;
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  14. Extended Message Function With Response Caching
  15. (C) Copyright AudioScience Inc. 2002
  16. *****************************************************************************/
  17. #define SOURCEFILE_NAME "hpimsgx.c"
  18. #include "hpi_internal.h"
  19. #include "hpi_version.h"
  20. #include "hpimsginit.h"
  21. #include "hpicmn.h"
  22. #include "hpimsgx.h"
  23. #include "hpidebug.h"
  24. static struct pci_device_id asihpi_pci_tbl[] = {
  25. #include "hpipcida.h"
  26. };
  27. static struct hpios_spinlock msgx_lock;
  28. static hpi_handler_func *hpi_entry_points[HPI_MAX_ADAPTERS];
  29. static int logging_enabled = 1;
  30. static hpi_handler_func *hpi_lookup_entry_point_function(const struct hpi_pci
  31. *pci_info)
  32. {
  33. int i;
  34. for (i = 0; asihpi_pci_tbl[i].vendor != 0; i++) {
  35. if (asihpi_pci_tbl[i].vendor != PCI_ANY_ID
  36. && asihpi_pci_tbl[i].vendor !=
  37. pci_info->pci_dev->vendor)
  38. continue;
  39. if (asihpi_pci_tbl[i].device != PCI_ANY_ID
  40. && asihpi_pci_tbl[i].device !=
  41. pci_info->pci_dev->device)
  42. continue;
  43. if (asihpi_pci_tbl[i].subvendor != PCI_ANY_ID
  44. && asihpi_pci_tbl[i].subvendor !=
  45. pci_info->pci_dev->subsystem_vendor)
  46. continue;
  47. if (asihpi_pci_tbl[i].subdevice != PCI_ANY_ID
  48. && asihpi_pci_tbl[i].subdevice !=
  49. pci_info->pci_dev->subsystem_device)
  50. continue;
  51. /* HPI_DEBUG_LOG(DEBUG, " %x,%lx\n", i,
  52. asihpi_pci_tbl[i].driver_data); */
  53. return (hpi_handler_func *) asihpi_pci_tbl[i].driver_data;
  54. }
  55. return NULL;
  56. }
  57. static inline void hw_entry_point(struct hpi_message *phm,
  58. struct hpi_response *phr)
  59. {
  60. if ((phm->adapter_index < HPI_MAX_ADAPTERS)
  61. && hpi_entry_points[phm->adapter_index])
  62. hpi_entry_points[phm->adapter_index] (phm, phr);
  63. else
  64. hpi_init_response(phr, phm->object, phm->function,
  65. HPI_ERROR_PROCESSING_MESSAGE);
  66. }
  67. static void adapter_open(struct hpi_message *phm, struct hpi_response *phr);
  68. static void adapter_close(struct hpi_message *phm, struct hpi_response *phr);
  69. static void mixer_open(struct hpi_message *phm, struct hpi_response *phr);
  70. static void mixer_close(struct hpi_message *phm, struct hpi_response *phr);
  71. static void outstream_open(struct hpi_message *phm, struct hpi_response *phr,
  72. void *h_owner);
  73. static void outstream_close(struct hpi_message *phm, struct hpi_response *phr,
  74. void *h_owner);
  75. static void instream_open(struct hpi_message *phm, struct hpi_response *phr,
  76. void *h_owner);
  77. static void instream_close(struct hpi_message *phm, struct hpi_response *phr,
  78. void *h_owner);
  79. static void HPIMSGX__reset(u16 adapter_index);
  80. static u16 HPIMSGX__init(struct hpi_message *phm, struct hpi_response *phr);
  81. static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner);
  82. #ifndef DISABLE_PRAGMA_PACK1
  83. #pragma pack(push, 1)
  84. #endif
  85. struct hpi_subsys_response {
  86. struct hpi_response_header h;
  87. struct hpi_subsys_res s;
  88. };
  89. struct hpi_adapter_response {
  90. struct hpi_response_header h;
  91. struct hpi_adapter_res a;
  92. };
  93. struct hpi_mixer_response {
  94. struct hpi_response_header h;
  95. struct hpi_mixer_res m;
  96. };
  97. struct hpi_stream_response {
  98. struct hpi_response_header h;
  99. struct hpi_stream_res d;
  100. };
  101. struct adapter_info {
  102. u16 type;
  103. u16 num_instreams;
  104. u16 num_outstreams;
  105. };
  106. struct asi_open_state {
  107. int open_flag;
  108. void *h_owner;
  109. };
  110. #ifndef DISABLE_PRAGMA_PACK1
  111. #pragma pack(pop)
  112. #endif
  113. /* Globals */
  114. static struct hpi_adapter_response rESP_HPI_ADAPTER_OPEN[HPI_MAX_ADAPTERS];
  115. static struct hpi_stream_response
  116. rESP_HPI_OSTREAM_OPEN[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
  117. static struct hpi_stream_response
  118. rESP_HPI_ISTREAM_OPEN[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
  119. static struct hpi_mixer_response rESP_HPI_MIXER_OPEN[HPI_MAX_ADAPTERS];
  120. static struct adapter_info aDAPTER_INFO[HPI_MAX_ADAPTERS];
  121. /* use these to keep track of opens from user mode apps/DLLs */
  122. static struct asi_open_state
  123. outstream_user_open[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
  124. static struct asi_open_state
  125. instream_user_open[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
  126. static void subsys_message(struct hpi_message *phm, struct hpi_response *phr,
  127. void *h_owner)
  128. {
  129. if (phm->adapter_index != HPI_ADAPTER_INDEX_INVALID)
  130. HPI_DEBUG_LOG(WARNING,
  131. "suspicious adapter index %d in subsys message 0x%x.\n",
  132. phm->adapter_index, phm->function);
  133. switch (phm->function) {
  134. case HPI_SUBSYS_GET_VERSION:
  135. hpi_init_response(phr, HPI_OBJ_SUBSYSTEM,
  136. HPI_SUBSYS_GET_VERSION, 0);
  137. phr->u.s.version = HPI_VER >> 8; /* return major.minor */
  138. phr->u.s.data = HPI_VER; /* return major.minor.release */
  139. break;
  140. case HPI_SUBSYS_OPEN:
  141. /*do not propagate the message down the chain */
  142. hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_OPEN, 0);
  143. break;
  144. case HPI_SUBSYS_CLOSE:
  145. /*do not propagate the message down the chain */
  146. hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_CLOSE,
  147. 0);
  148. HPIMSGX__cleanup(HPIMSGX_ALLADAPTERS, h_owner);
  149. break;
  150. case HPI_SUBSYS_DRIVER_LOAD:
  151. /* Initialize this module's internal state */
  152. hpios_msgxlock_init(&msgx_lock);
  153. memset(&hpi_entry_points, 0, sizeof(hpi_entry_points));
  154. /* Init subsys_findadapters response to no-adapters */
  155. HPIMSGX__reset(HPIMSGX_ALLADAPTERS);
  156. hpi_init_response(phr, HPI_OBJ_SUBSYSTEM,
  157. HPI_SUBSYS_DRIVER_LOAD, 0);
  158. /* individual HPIs dont implement driver load */
  159. HPI_COMMON(phm, phr);
  160. break;
  161. case HPI_SUBSYS_DRIVER_UNLOAD:
  162. HPI_COMMON(phm, phr);
  163. HPIMSGX__cleanup(HPIMSGX_ALLADAPTERS, h_owner);
  164. hpi_init_response(phr, HPI_OBJ_SUBSYSTEM,
  165. HPI_SUBSYS_DRIVER_UNLOAD, 0);
  166. return;
  167. case HPI_SUBSYS_GET_NUM_ADAPTERS:
  168. case HPI_SUBSYS_GET_ADAPTER:
  169. HPI_COMMON(phm, phr);
  170. break;
  171. case HPI_SUBSYS_CREATE_ADAPTER:
  172. HPIMSGX__init(phm, phr);
  173. break;
  174. default:
  175. /* Must explicitly handle every subsys message in this switch */
  176. hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function,
  177. HPI_ERROR_INVALID_FUNC);
  178. break;
  179. }
  180. }
  181. static void adapter_message(struct hpi_message *phm, struct hpi_response *phr,
  182. void *h_owner)
  183. {
  184. switch (phm->function) {
  185. case HPI_ADAPTER_OPEN:
  186. adapter_open(phm, phr);
  187. break;
  188. case HPI_ADAPTER_CLOSE:
  189. adapter_close(phm, phr);
  190. break;
  191. case HPI_ADAPTER_DELETE:
  192. HPIMSGX__cleanup(phm->adapter_index, h_owner);
  193. {
  194. struct hpi_message hm;
  195. struct hpi_response hr;
  196. hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
  197. HPI_ADAPTER_CLOSE);
  198. hm.adapter_index = phm->adapter_index;
  199. hw_entry_point(&hm, &hr);
  200. }
  201. hw_entry_point(phm, phr);
  202. break;
  203. default:
  204. hw_entry_point(phm, phr);
  205. break;
  206. }
  207. }
  208. static void mixer_message(struct hpi_message *phm, struct hpi_response *phr)
  209. {
  210. switch (phm->function) {
  211. case HPI_MIXER_OPEN:
  212. mixer_open(phm, phr);
  213. break;
  214. case HPI_MIXER_CLOSE:
  215. mixer_close(phm, phr);
  216. break;
  217. default:
  218. hw_entry_point(phm, phr);
  219. break;
  220. }
  221. }
  222. static void outstream_message(struct hpi_message *phm,
  223. struct hpi_response *phr, void *h_owner)
  224. {
  225. if (phm->obj_index >= aDAPTER_INFO[phm->adapter_index].num_outstreams) {
  226. hpi_init_response(phr, HPI_OBJ_OSTREAM, phm->function,
  227. HPI_ERROR_INVALID_OBJ_INDEX);
  228. return;
  229. }
  230. switch (phm->function) {
  231. case HPI_OSTREAM_OPEN:
  232. outstream_open(phm, phr, h_owner);
  233. break;
  234. case HPI_OSTREAM_CLOSE:
  235. outstream_close(phm, phr, h_owner);
  236. break;
  237. default:
  238. hw_entry_point(phm, phr);
  239. break;
  240. }
  241. }
  242. static void instream_message(struct hpi_message *phm,
  243. struct hpi_response *phr, void *h_owner)
  244. {
  245. if (phm->obj_index >= aDAPTER_INFO[phm->adapter_index].num_instreams) {
  246. hpi_init_response(phr, HPI_OBJ_ISTREAM, phm->function,
  247. HPI_ERROR_INVALID_OBJ_INDEX);
  248. return;
  249. }
  250. switch (phm->function) {
  251. case HPI_ISTREAM_OPEN:
  252. instream_open(phm, phr, h_owner);
  253. break;
  254. case HPI_ISTREAM_CLOSE:
  255. instream_close(phm, phr, h_owner);
  256. break;
  257. default:
  258. hw_entry_point(phm, phr);
  259. break;
  260. }
  261. }
  262. /* NOTE: HPI_Message() must be defined in the driver as a wrapper for
  263. * HPI_MessageEx so that functions in hpifunc.c compile.
  264. */
  265. void hpi_send_recv_ex(struct hpi_message *phm, struct hpi_response *phr,
  266. void *h_owner)
  267. {
  268. if (logging_enabled)
  269. HPI_DEBUG_MESSAGE(DEBUG, phm);
  270. if (phm->type != HPI_TYPE_REQUEST) {
  271. hpi_init_response(phr, phm->object, phm->function,
  272. HPI_ERROR_INVALID_TYPE);
  273. return;
  274. }
  275. if (phm->adapter_index >= HPI_MAX_ADAPTERS
  276. && phm->adapter_index != HPIMSGX_ALLADAPTERS) {
  277. hpi_init_response(phr, phm->object, phm->function,
  278. HPI_ERROR_BAD_ADAPTER_NUMBER);
  279. return;
  280. }
  281. switch (phm->object) {
  282. case HPI_OBJ_SUBSYSTEM:
  283. subsys_message(phm, phr, h_owner);
  284. break;
  285. case HPI_OBJ_ADAPTER:
  286. adapter_message(phm, phr, h_owner);
  287. break;
  288. case HPI_OBJ_MIXER:
  289. mixer_message(phm, phr);
  290. break;
  291. case HPI_OBJ_OSTREAM:
  292. outstream_message(phm, phr, h_owner);
  293. break;
  294. case HPI_OBJ_ISTREAM:
  295. instream_message(phm, phr, h_owner);
  296. break;
  297. default:
  298. hw_entry_point(phm, phr);
  299. break;
  300. }
  301. if (logging_enabled)
  302. HPI_DEBUG_RESPONSE(phr);
  303. if (phr->error >= HPI_ERROR_DSP_COMMUNICATION) {
  304. hpi_debug_level_set(HPI_DEBUG_LEVEL_ERROR);
  305. logging_enabled = 0;
  306. }
  307. }
  308. static void adapter_open(struct hpi_message *phm, struct hpi_response *phr)
  309. {
  310. HPI_DEBUG_LOG(VERBOSE, "adapter_open\n");
  311. memcpy(phr, &rESP_HPI_ADAPTER_OPEN[phm->adapter_index],
  312. sizeof(rESP_HPI_ADAPTER_OPEN[0]));
  313. }
  314. static void adapter_close(struct hpi_message *phm, struct hpi_response *phr)
  315. {
  316. HPI_DEBUG_LOG(VERBOSE, "adapter_close\n");
  317. hpi_init_response(phr, HPI_OBJ_ADAPTER, HPI_ADAPTER_CLOSE, 0);
  318. }
  319. static void mixer_open(struct hpi_message *phm, struct hpi_response *phr)
  320. {
  321. memcpy(phr, &rESP_HPI_MIXER_OPEN[phm->adapter_index],
  322. sizeof(rESP_HPI_MIXER_OPEN[0]));
  323. }
  324. static void mixer_close(struct hpi_message *phm, struct hpi_response *phr)
  325. {
  326. hpi_init_response(phr, HPI_OBJ_MIXER, HPI_MIXER_CLOSE, 0);
  327. }
  328. static void instream_open(struct hpi_message *phm, struct hpi_response *phr,
  329. void *h_owner)
  330. {
  331. struct hpi_message hm;
  332. struct hpi_response hr;
  333. hpi_init_response(phr, HPI_OBJ_ISTREAM, HPI_ISTREAM_OPEN, 0);
  334. hpios_msgxlock_lock(&msgx_lock);
  335. if (instream_user_open[phm->adapter_index][phm->obj_index].open_flag)
  336. phr->error = HPI_ERROR_OBJ_ALREADY_OPEN;
  337. else if (rESP_HPI_ISTREAM_OPEN[phm->adapter_index]
  338. [phm->obj_index].h.error)
  339. memcpy(phr,
  340. &rESP_HPI_ISTREAM_OPEN[phm->adapter_index][phm->
  341. obj_index],
  342. sizeof(rESP_HPI_ISTREAM_OPEN[0][0]));
  343. else {
  344. instream_user_open[phm->adapter_index][phm->
  345. obj_index].open_flag = 1;
  346. hpios_msgxlock_unlock(&msgx_lock);
  347. /* issue a reset */
  348. hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
  349. HPI_ISTREAM_RESET);
  350. hm.adapter_index = phm->adapter_index;
  351. hm.obj_index = phm->obj_index;
  352. hw_entry_point(&hm, &hr);
  353. hpios_msgxlock_lock(&msgx_lock);
  354. if (hr.error) {
  355. instream_user_open[phm->adapter_index][phm->
  356. obj_index].open_flag = 0;
  357. phr->error = hr.error;
  358. } else {
  359. instream_user_open[phm->adapter_index][phm->
  360. obj_index].open_flag = 1;
  361. instream_user_open[phm->adapter_index][phm->
  362. obj_index].h_owner = h_owner;
  363. memcpy(phr,
  364. &rESP_HPI_ISTREAM_OPEN[phm->adapter_index]
  365. [phm->obj_index],
  366. sizeof(rESP_HPI_ISTREAM_OPEN[0][0]));
  367. }
  368. }
  369. hpios_msgxlock_unlock(&msgx_lock);
  370. }
  371. static void instream_close(struct hpi_message *phm, struct hpi_response *phr,
  372. void *h_owner)
  373. {
  374. struct hpi_message hm;
  375. struct hpi_response hr;
  376. hpi_init_response(phr, HPI_OBJ_ISTREAM, HPI_ISTREAM_CLOSE, 0);
  377. hpios_msgxlock_lock(&msgx_lock);
  378. if (h_owner ==
  379. instream_user_open[phm->adapter_index][phm->
  380. obj_index].h_owner) {
  381. /* HPI_DEBUG_LOG(INFO,"closing adapter %d "
  382. "instream %d owned by %p\n",
  383. phm->wAdapterIndex, phm->wObjIndex, hOwner); */
  384. instream_user_open[phm->adapter_index][phm->
  385. obj_index].h_owner = NULL;
  386. hpios_msgxlock_unlock(&msgx_lock);
  387. /* issue a reset */
  388. hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
  389. HPI_ISTREAM_RESET);
  390. hm.adapter_index = phm->adapter_index;
  391. hm.obj_index = phm->obj_index;
  392. hw_entry_point(&hm, &hr);
  393. hpios_msgxlock_lock(&msgx_lock);
  394. if (hr.error) {
  395. instream_user_open[phm->adapter_index][phm->
  396. obj_index].h_owner = h_owner;
  397. phr->error = hr.error;
  398. } else {
  399. instream_user_open[phm->adapter_index][phm->
  400. obj_index].open_flag = 0;
  401. instream_user_open[phm->adapter_index][phm->
  402. obj_index].h_owner = NULL;
  403. }
  404. } else {
  405. HPI_DEBUG_LOG(WARNING,
  406. "%p trying to close %d instream %d owned by %p\n",
  407. h_owner, phm->adapter_index, phm->obj_index,
  408. instream_user_open[phm->adapter_index][phm->
  409. obj_index].h_owner);
  410. phr->error = HPI_ERROR_OBJ_NOT_OPEN;
  411. }
  412. hpios_msgxlock_unlock(&msgx_lock);
  413. }
  414. static void outstream_open(struct hpi_message *phm, struct hpi_response *phr,
  415. void *h_owner)
  416. {
  417. struct hpi_message hm;
  418. struct hpi_response hr;
  419. hpi_init_response(phr, HPI_OBJ_OSTREAM, HPI_OSTREAM_OPEN, 0);
  420. hpios_msgxlock_lock(&msgx_lock);
  421. if (outstream_user_open[phm->adapter_index][phm->obj_index].open_flag)
  422. phr->error = HPI_ERROR_OBJ_ALREADY_OPEN;
  423. else if (rESP_HPI_OSTREAM_OPEN[phm->adapter_index]
  424. [phm->obj_index].h.error)
  425. memcpy(phr,
  426. &rESP_HPI_OSTREAM_OPEN[phm->adapter_index][phm->
  427. obj_index],
  428. sizeof(rESP_HPI_OSTREAM_OPEN[0][0]));
  429. else {
  430. outstream_user_open[phm->adapter_index][phm->
  431. obj_index].open_flag = 1;
  432. hpios_msgxlock_unlock(&msgx_lock);
  433. /* issue a reset */
  434. hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
  435. HPI_OSTREAM_RESET);
  436. hm.adapter_index = phm->adapter_index;
  437. hm.obj_index = phm->obj_index;
  438. hw_entry_point(&hm, &hr);
  439. hpios_msgxlock_lock(&msgx_lock);
  440. if (hr.error) {
  441. outstream_user_open[phm->adapter_index][phm->
  442. obj_index].open_flag = 0;
  443. phr->error = hr.error;
  444. } else {
  445. outstream_user_open[phm->adapter_index][phm->
  446. obj_index].open_flag = 1;
  447. outstream_user_open[phm->adapter_index][phm->
  448. obj_index].h_owner = h_owner;
  449. memcpy(phr,
  450. &rESP_HPI_OSTREAM_OPEN[phm->adapter_index]
  451. [phm->obj_index],
  452. sizeof(rESP_HPI_OSTREAM_OPEN[0][0]));
  453. }
  454. }
  455. hpios_msgxlock_unlock(&msgx_lock);
  456. }
  457. static void outstream_close(struct hpi_message *phm, struct hpi_response *phr,
  458. void *h_owner)
  459. {
  460. struct hpi_message hm;
  461. struct hpi_response hr;
  462. hpi_init_response(phr, HPI_OBJ_OSTREAM, HPI_OSTREAM_CLOSE, 0);
  463. hpios_msgxlock_lock(&msgx_lock);
  464. if (h_owner ==
  465. outstream_user_open[phm->adapter_index][phm->
  466. obj_index].h_owner) {
  467. /* HPI_DEBUG_LOG(INFO,"closing adapter %d "
  468. "outstream %d owned by %p\n",
  469. phm->wAdapterIndex, phm->wObjIndex, hOwner); */
  470. outstream_user_open[phm->adapter_index][phm->
  471. obj_index].h_owner = NULL;
  472. hpios_msgxlock_unlock(&msgx_lock);
  473. /* issue a reset */
  474. hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
  475. HPI_OSTREAM_RESET);
  476. hm.adapter_index = phm->adapter_index;
  477. hm.obj_index = phm->obj_index;
  478. hw_entry_point(&hm, &hr);
  479. hpios_msgxlock_lock(&msgx_lock);
  480. if (hr.error) {
  481. outstream_user_open[phm->adapter_index][phm->
  482. obj_index].h_owner = h_owner;
  483. phr->error = hr.error;
  484. } else {
  485. outstream_user_open[phm->adapter_index][phm->
  486. obj_index].open_flag = 0;
  487. outstream_user_open[phm->adapter_index][phm->
  488. obj_index].h_owner = NULL;
  489. }
  490. } else {
  491. HPI_DEBUG_LOG(WARNING,
  492. "%p trying to close %d outstream %d owned by %p\n",
  493. h_owner, phm->adapter_index, phm->obj_index,
  494. outstream_user_open[phm->adapter_index][phm->
  495. obj_index].h_owner);
  496. phr->error = HPI_ERROR_OBJ_NOT_OPEN;
  497. }
  498. hpios_msgxlock_unlock(&msgx_lock);
  499. }
  500. static u16 adapter_prepare(u16 adapter)
  501. {
  502. struct hpi_message hm;
  503. struct hpi_response hr;
  504. /* Open the adapter and streams */
  505. u16 i;
  506. /* call to HPI_ADAPTER_OPEN */
  507. hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
  508. HPI_ADAPTER_OPEN);
  509. hm.adapter_index = adapter;
  510. hw_entry_point(&hm, &hr);
  511. memcpy(&rESP_HPI_ADAPTER_OPEN[adapter], &hr,
  512. sizeof(rESP_HPI_ADAPTER_OPEN[0]));
  513. if (hr.error)
  514. return hr.error;
  515. /* call to HPI_ADAPTER_GET_INFO */
  516. hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
  517. HPI_ADAPTER_GET_INFO);
  518. hm.adapter_index = adapter;
  519. hw_entry_point(&hm, &hr);
  520. if (hr.error)
  521. return hr.error;
  522. aDAPTER_INFO[adapter].num_outstreams = hr.u.ax.info.num_outstreams;
  523. aDAPTER_INFO[adapter].num_instreams = hr.u.ax.info.num_instreams;
  524. aDAPTER_INFO[adapter].type = hr.u.ax.info.adapter_type;
  525. /* call to HPI_OSTREAM_OPEN */
  526. for (i = 0; i < aDAPTER_INFO[adapter].num_outstreams; i++) {
  527. hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
  528. HPI_OSTREAM_OPEN);
  529. hm.adapter_index = adapter;
  530. hm.obj_index = i;
  531. hw_entry_point(&hm, &hr);
  532. memcpy(&rESP_HPI_OSTREAM_OPEN[adapter][i], &hr,
  533. sizeof(rESP_HPI_OSTREAM_OPEN[0][0]));
  534. outstream_user_open[adapter][i].open_flag = 0;
  535. outstream_user_open[adapter][i].h_owner = NULL;
  536. }
  537. /* call to HPI_ISTREAM_OPEN */
  538. for (i = 0; i < aDAPTER_INFO[adapter].num_instreams; i++) {
  539. hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
  540. HPI_ISTREAM_OPEN);
  541. hm.adapter_index = adapter;
  542. hm.obj_index = i;
  543. hw_entry_point(&hm, &hr);
  544. memcpy(&rESP_HPI_ISTREAM_OPEN[adapter][i], &hr,
  545. sizeof(rESP_HPI_ISTREAM_OPEN[0][0]));
  546. instream_user_open[adapter][i].open_flag = 0;
  547. instream_user_open[adapter][i].h_owner = NULL;
  548. }
  549. /* call to HPI_MIXER_OPEN */
  550. hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER, HPI_MIXER_OPEN);
  551. hm.adapter_index = adapter;
  552. hw_entry_point(&hm, &hr);
  553. memcpy(&rESP_HPI_MIXER_OPEN[adapter], &hr,
  554. sizeof(rESP_HPI_MIXER_OPEN[0]));
  555. return 0;
  556. }
  557. static void HPIMSGX__reset(u16 adapter_index)
  558. {
  559. int i;
  560. u16 adapter;
  561. struct hpi_response hr;
  562. if (adapter_index == HPIMSGX_ALLADAPTERS) {
  563. for (adapter = 0; adapter < HPI_MAX_ADAPTERS; adapter++) {
  564. hpi_init_response(&hr, HPI_OBJ_ADAPTER,
  565. HPI_ADAPTER_OPEN, HPI_ERROR_BAD_ADAPTER);
  566. memcpy(&rESP_HPI_ADAPTER_OPEN[adapter], &hr,
  567. sizeof(rESP_HPI_ADAPTER_OPEN[adapter]));
  568. hpi_init_response(&hr, HPI_OBJ_MIXER, HPI_MIXER_OPEN,
  569. HPI_ERROR_INVALID_OBJ);
  570. memcpy(&rESP_HPI_MIXER_OPEN[adapter], &hr,
  571. sizeof(rESP_HPI_MIXER_OPEN[adapter]));
  572. for (i = 0; i < HPI_MAX_STREAMS; i++) {
  573. hpi_init_response(&hr, HPI_OBJ_OSTREAM,
  574. HPI_OSTREAM_OPEN,
  575. HPI_ERROR_INVALID_OBJ);
  576. memcpy(&rESP_HPI_OSTREAM_OPEN[adapter][i],
  577. &hr,
  578. sizeof(rESP_HPI_OSTREAM_OPEN[adapter]
  579. [i]));
  580. hpi_init_response(&hr, HPI_OBJ_ISTREAM,
  581. HPI_ISTREAM_OPEN,
  582. HPI_ERROR_INVALID_OBJ);
  583. memcpy(&rESP_HPI_ISTREAM_OPEN[adapter][i],
  584. &hr,
  585. sizeof(rESP_HPI_ISTREAM_OPEN[adapter]
  586. [i]));
  587. }
  588. }
  589. } else if (adapter_index < HPI_MAX_ADAPTERS) {
  590. rESP_HPI_ADAPTER_OPEN[adapter_index].h.error =
  591. HPI_ERROR_BAD_ADAPTER;
  592. rESP_HPI_MIXER_OPEN[adapter_index].h.error =
  593. HPI_ERROR_INVALID_OBJ;
  594. for (i = 0; i < HPI_MAX_STREAMS; i++) {
  595. rESP_HPI_OSTREAM_OPEN[adapter_index][i].h.error =
  596. HPI_ERROR_INVALID_OBJ;
  597. rESP_HPI_ISTREAM_OPEN[adapter_index][i].h.error =
  598. HPI_ERROR_INVALID_OBJ;
  599. }
  600. }
  601. }
  602. static u16 HPIMSGX__init(struct hpi_message *phm,
  603. /* HPI_SUBSYS_CREATE_ADAPTER structure with */
  604. /* resource list or NULL=find all */
  605. struct hpi_response *phr
  606. /* response from HPI_ADAPTER_GET_INFO */
  607. )
  608. {
  609. hpi_handler_func *entry_point_func;
  610. struct hpi_response hr;
  611. /* Init response here so we can pass in previous adapter list */
  612. hpi_init_response(&hr, phm->object, phm->function,
  613. HPI_ERROR_INVALID_OBJ);
  614. entry_point_func =
  615. hpi_lookup_entry_point_function(phm->u.s.resource.r.pci);
  616. if (entry_point_func) {
  617. HPI_DEBUG_MESSAGE(DEBUG, phm);
  618. entry_point_func(phm, &hr);
  619. } else {
  620. phr->error = HPI_ERROR_PROCESSING_MESSAGE;
  621. return phr->error;
  622. }
  623. if (hr.error == 0) {
  624. /* the adapter was created successfully
  625. save the mapping for future use */
  626. hpi_entry_points[hr.u.s.adapter_index] = entry_point_func;
  627. /* prepare adapter (pre-open streams etc.) */
  628. HPI_DEBUG_LOG(DEBUG,
  629. "HPI_SUBSYS_CREATE_ADAPTER successful,"
  630. " preparing adapter\n");
  631. adapter_prepare(hr.u.s.adapter_index);
  632. }
  633. memcpy(phr, &hr, hr.size);
  634. return phr->error;
  635. }
  636. static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner)
  637. {
  638. int i, adapter, adapter_limit;
  639. if (!h_owner)
  640. return;
  641. if (adapter_index == HPIMSGX_ALLADAPTERS) {
  642. adapter = 0;
  643. adapter_limit = HPI_MAX_ADAPTERS;
  644. } else {
  645. adapter = adapter_index;
  646. adapter_limit = adapter + 1;
  647. }
  648. for (; adapter < adapter_limit; adapter++) {
  649. /* printk(KERN_INFO "Cleanup adapter #%d\n",wAdapter); */
  650. for (i = 0; i < HPI_MAX_STREAMS; i++) {
  651. if (h_owner ==
  652. outstream_user_open[adapter][i].h_owner) {
  653. struct hpi_message hm;
  654. struct hpi_response hr;
  655. HPI_DEBUG_LOG(DEBUG,
  656. "Close adapter %d ostream %d\n",
  657. adapter, i);
  658. hpi_init_message_response(&hm, &hr,
  659. HPI_OBJ_OSTREAM, HPI_OSTREAM_RESET);
  660. hm.adapter_index = (u16)adapter;
  661. hm.obj_index = (u16)i;
  662. hw_entry_point(&hm, &hr);
  663. hm.function = HPI_OSTREAM_HOSTBUFFER_FREE;
  664. hw_entry_point(&hm, &hr);
  665. hm.function = HPI_OSTREAM_GROUP_RESET;
  666. hw_entry_point(&hm, &hr);
  667. outstream_user_open[adapter][i].open_flag = 0;
  668. outstream_user_open[adapter][i].h_owner =
  669. NULL;
  670. }
  671. if (h_owner == instream_user_open[adapter][i].h_owner) {
  672. struct hpi_message hm;
  673. struct hpi_response hr;
  674. HPI_DEBUG_LOG(DEBUG,
  675. "Close adapter %d istream %d\n",
  676. adapter, i);
  677. hpi_init_message_response(&hm, &hr,
  678. HPI_OBJ_ISTREAM, HPI_ISTREAM_RESET);
  679. hm.adapter_index = (u16)adapter;
  680. hm.obj_index = (u16)i;
  681. hw_entry_point(&hm, &hr);
  682. hm.function = HPI_ISTREAM_HOSTBUFFER_FREE;
  683. hw_entry_point(&hm, &hr);
  684. hm.function = HPI_ISTREAM_GROUP_RESET;
  685. hw_entry_point(&hm, &hr);
  686. instream_user_open[adapter][i].open_flag = 0;
  687. instream_user_open[adapter][i].h_owner = NULL;
  688. }
  689. }
  690. }
  691. }