hpimsgx.c 21 KB

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