hpimsgx.c 22 KB

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