hpimsgx.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799
  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 Caching
  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. /* Init subsys_findadapters response to no-adapters */
  153. HPIMSGX__reset(HPIMSGX_ALLADAPTERS);
  154. hpi_init_response(phr, HPI_OBJ_SUBSYSTEM,
  155. HPI_SUBSYS_DRIVER_LOAD, 0);
  156. /* individual HPIs dont implement driver load */
  157. HPI_COMMON(phm, phr);
  158. break;
  159. case HPI_SUBSYS_DRIVER_UNLOAD:
  160. HPI_COMMON(phm, phr);
  161. HPIMSGX__cleanup(HPIMSGX_ALLADAPTERS, h_owner);
  162. hpi_init_response(phr, HPI_OBJ_SUBSYSTEM,
  163. HPI_SUBSYS_DRIVER_UNLOAD, 0);
  164. return;
  165. case HPI_SUBSYS_GET_NUM_ADAPTERS:
  166. case HPI_SUBSYS_GET_ADAPTER:
  167. HPI_COMMON(phm, phr);
  168. break;
  169. case HPI_SUBSYS_CREATE_ADAPTER:
  170. HPIMSGX__init(phm, phr);
  171. break;
  172. default:
  173. /* Must explicitly handle every subsys message in this switch */
  174. hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function,
  175. HPI_ERROR_INVALID_FUNC);
  176. break;
  177. }
  178. }
  179. static void adapter_message(struct hpi_message *phm, struct hpi_response *phr,
  180. void *h_owner)
  181. {
  182. switch (phm->function) {
  183. case HPI_ADAPTER_OPEN:
  184. adapter_open(phm, phr);
  185. break;
  186. case HPI_ADAPTER_CLOSE:
  187. adapter_close(phm, phr);
  188. break;
  189. case HPI_ADAPTER_DELETE:
  190. HPIMSGX__cleanup(phm->adapter_index, h_owner);
  191. {
  192. struct hpi_message hm;
  193. struct hpi_response hr;
  194. hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
  195. HPI_ADAPTER_CLOSE);
  196. hm.adapter_index = phm->adapter_index;
  197. hw_entry_point(&hm, &hr);
  198. }
  199. hw_entry_point(phm, phr);
  200. break;
  201. default:
  202. hw_entry_point(phm, phr);
  203. break;
  204. }
  205. }
  206. static void mixer_message(struct hpi_message *phm, struct hpi_response *phr)
  207. {
  208. switch (phm->function) {
  209. case HPI_MIXER_OPEN:
  210. mixer_open(phm, phr);
  211. break;
  212. case HPI_MIXER_CLOSE:
  213. mixer_close(phm, phr);
  214. break;
  215. default:
  216. hw_entry_point(phm, phr);
  217. break;
  218. }
  219. }
  220. static void outstream_message(struct hpi_message *phm,
  221. struct hpi_response *phr, void *h_owner)
  222. {
  223. if (phm->obj_index >= aDAPTER_INFO[phm->adapter_index].num_outstreams) {
  224. hpi_init_response(phr, HPI_OBJ_OSTREAM, phm->function,
  225. HPI_ERROR_INVALID_OBJ_INDEX);
  226. return;
  227. }
  228. switch (phm->function) {
  229. case HPI_OSTREAM_OPEN:
  230. outstream_open(phm, phr, h_owner);
  231. break;
  232. case HPI_OSTREAM_CLOSE:
  233. outstream_close(phm, phr, h_owner);
  234. break;
  235. default:
  236. hw_entry_point(phm, phr);
  237. break;
  238. }
  239. }
  240. static void instream_message(struct hpi_message *phm,
  241. struct hpi_response *phr, void *h_owner)
  242. {
  243. if (phm->obj_index >= aDAPTER_INFO[phm->adapter_index].num_instreams) {
  244. hpi_init_response(phr, HPI_OBJ_ISTREAM, phm->function,
  245. HPI_ERROR_INVALID_OBJ_INDEX);
  246. return;
  247. }
  248. switch (phm->function) {
  249. case HPI_ISTREAM_OPEN:
  250. instream_open(phm, phr, h_owner);
  251. break;
  252. case HPI_ISTREAM_CLOSE:
  253. instream_close(phm, phr, h_owner);
  254. break;
  255. default:
  256. hw_entry_point(phm, phr);
  257. break;
  258. }
  259. }
  260. /* NOTE: HPI_Message() must be defined in the driver as a wrapper for
  261. * HPI_MessageEx so that functions in hpifunc.c compile.
  262. */
  263. void hpi_send_recv_ex(struct hpi_message *phm, struct hpi_response *phr,
  264. void *h_owner)
  265. {
  266. HPI_DEBUG_MESSAGE(DEBUG, phm);
  267. if (phm->type != HPI_TYPE_REQUEST) {
  268. hpi_init_response(phr, phm->object, phm->function,
  269. HPI_ERROR_INVALID_TYPE);
  270. return;
  271. }
  272. if (phm->adapter_index >= HPI_MAX_ADAPTERS
  273. && phm->adapter_index != HPIMSGX_ALLADAPTERS) {
  274. hpi_init_response(phr, phm->object, phm->function,
  275. HPI_ERROR_BAD_ADAPTER_NUMBER);
  276. return;
  277. }
  278. switch (phm->object) {
  279. case HPI_OBJ_SUBSYSTEM:
  280. subsys_message(phm, phr, h_owner);
  281. break;
  282. case HPI_OBJ_ADAPTER:
  283. adapter_message(phm, phr, h_owner);
  284. break;
  285. case HPI_OBJ_MIXER:
  286. mixer_message(phm, phr);
  287. break;
  288. case HPI_OBJ_OSTREAM:
  289. outstream_message(phm, phr, h_owner);
  290. break;
  291. case HPI_OBJ_ISTREAM:
  292. instream_message(phm, phr, h_owner);
  293. break;
  294. default:
  295. hw_entry_point(phm, phr);
  296. break;
  297. }
  298. HPI_DEBUG_RESPONSE(phr);
  299. }
  300. static void adapter_open(struct hpi_message *phm, struct hpi_response *phr)
  301. {
  302. HPI_DEBUG_LOG(VERBOSE, "adapter_open\n");
  303. memcpy(phr, &rESP_HPI_ADAPTER_OPEN[phm->adapter_index],
  304. sizeof(rESP_HPI_ADAPTER_OPEN[0]));
  305. }
  306. static void adapter_close(struct hpi_message *phm, struct hpi_response *phr)
  307. {
  308. HPI_DEBUG_LOG(VERBOSE, "adapter_close\n");
  309. hpi_init_response(phr, HPI_OBJ_ADAPTER, HPI_ADAPTER_CLOSE, 0);
  310. }
  311. static void mixer_open(struct hpi_message *phm, struct hpi_response *phr)
  312. {
  313. memcpy(phr, &rESP_HPI_MIXER_OPEN[phm->adapter_index],
  314. sizeof(rESP_HPI_MIXER_OPEN[0]));
  315. }
  316. static void mixer_close(struct hpi_message *phm, struct hpi_response *phr)
  317. {
  318. hpi_init_response(phr, HPI_OBJ_MIXER, HPI_MIXER_CLOSE, 0);
  319. }
  320. static void instream_open(struct hpi_message *phm, struct hpi_response *phr,
  321. void *h_owner)
  322. {
  323. struct hpi_message hm;
  324. struct hpi_response hr;
  325. hpi_init_response(phr, HPI_OBJ_ISTREAM, HPI_ISTREAM_OPEN, 0);
  326. hpios_msgxlock_lock(&msgx_lock);
  327. if (instream_user_open[phm->adapter_index][phm->obj_index].open_flag)
  328. phr->error = HPI_ERROR_OBJ_ALREADY_OPEN;
  329. else if (rESP_HPI_ISTREAM_OPEN[phm->adapter_index]
  330. [phm->obj_index].h.error)
  331. memcpy(phr,
  332. &rESP_HPI_ISTREAM_OPEN[phm->adapter_index][phm->
  333. obj_index],
  334. sizeof(rESP_HPI_ISTREAM_OPEN[0][0]));
  335. else {
  336. instream_user_open[phm->adapter_index][phm->
  337. obj_index].open_flag = 1;
  338. hpios_msgxlock_unlock(&msgx_lock);
  339. /* issue a reset */
  340. hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
  341. HPI_ISTREAM_RESET);
  342. hm.adapter_index = phm->adapter_index;
  343. hm.obj_index = phm->obj_index;
  344. hw_entry_point(&hm, &hr);
  345. hpios_msgxlock_lock(&msgx_lock);
  346. if (hr.error) {
  347. instream_user_open[phm->adapter_index][phm->
  348. obj_index].open_flag = 0;
  349. phr->error = hr.error;
  350. } else {
  351. instream_user_open[phm->adapter_index][phm->
  352. obj_index].open_flag = 1;
  353. instream_user_open[phm->adapter_index][phm->
  354. obj_index].h_owner = h_owner;
  355. memcpy(phr,
  356. &rESP_HPI_ISTREAM_OPEN[phm->adapter_index]
  357. [phm->obj_index],
  358. sizeof(rESP_HPI_ISTREAM_OPEN[0][0]));
  359. }
  360. }
  361. hpios_msgxlock_unlock(&msgx_lock);
  362. }
  363. static void instream_close(struct hpi_message *phm, struct hpi_response *phr,
  364. void *h_owner)
  365. {
  366. struct hpi_message hm;
  367. struct hpi_response hr;
  368. hpi_init_response(phr, HPI_OBJ_ISTREAM, HPI_ISTREAM_CLOSE, 0);
  369. hpios_msgxlock_lock(&msgx_lock);
  370. if (h_owner ==
  371. instream_user_open[phm->adapter_index][phm->
  372. obj_index].h_owner) {
  373. /* HPI_DEBUG_LOG(INFO,"closing adapter %d "
  374. "instream %d owned by %p\n",
  375. phm->wAdapterIndex, phm->wObjIndex, hOwner); */
  376. instream_user_open[phm->adapter_index][phm->
  377. obj_index].h_owner = NULL;
  378. hpios_msgxlock_unlock(&msgx_lock);
  379. /* issue a reset */
  380. hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
  381. HPI_ISTREAM_RESET);
  382. hm.adapter_index = phm->adapter_index;
  383. hm.obj_index = phm->obj_index;
  384. hw_entry_point(&hm, &hr);
  385. hpios_msgxlock_lock(&msgx_lock);
  386. if (hr.error) {
  387. instream_user_open[phm->adapter_index][phm->
  388. obj_index].h_owner = h_owner;
  389. phr->error = hr.error;
  390. } else {
  391. instream_user_open[phm->adapter_index][phm->
  392. obj_index].open_flag = 0;
  393. instream_user_open[phm->adapter_index][phm->
  394. obj_index].h_owner = NULL;
  395. }
  396. } else {
  397. HPI_DEBUG_LOG(WARNING,
  398. "%p trying to close %d instream %d owned by %p\n",
  399. h_owner, phm->adapter_index, phm->obj_index,
  400. instream_user_open[phm->adapter_index][phm->
  401. obj_index].h_owner);
  402. phr->error = HPI_ERROR_OBJ_NOT_OPEN;
  403. }
  404. hpios_msgxlock_unlock(&msgx_lock);
  405. }
  406. static void outstream_open(struct hpi_message *phm, struct hpi_response *phr,
  407. void *h_owner)
  408. {
  409. struct hpi_message hm;
  410. struct hpi_response hr;
  411. hpi_init_response(phr, HPI_OBJ_OSTREAM, HPI_OSTREAM_OPEN, 0);
  412. hpios_msgxlock_lock(&msgx_lock);
  413. if (outstream_user_open[phm->adapter_index][phm->obj_index].open_flag)
  414. phr->error = HPI_ERROR_OBJ_ALREADY_OPEN;
  415. else if (rESP_HPI_OSTREAM_OPEN[phm->adapter_index]
  416. [phm->obj_index].h.error)
  417. memcpy(phr,
  418. &rESP_HPI_OSTREAM_OPEN[phm->adapter_index][phm->
  419. obj_index],
  420. sizeof(rESP_HPI_OSTREAM_OPEN[0][0]));
  421. else {
  422. outstream_user_open[phm->adapter_index][phm->
  423. obj_index].open_flag = 1;
  424. hpios_msgxlock_unlock(&msgx_lock);
  425. /* issue a reset */
  426. hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
  427. HPI_OSTREAM_RESET);
  428. hm.adapter_index = phm->adapter_index;
  429. hm.obj_index = phm->obj_index;
  430. hw_entry_point(&hm, &hr);
  431. hpios_msgxlock_lock(&msgx_lock);
  432. if (hr.error) {
  433. outstream_user_open[phm->adapter_index][phm->
  434. obj_index].open_flag = 0;
  435. phr->error = hr.error;
  436. } else {
  437. outstream_user_open[phm->adapter_index][phm->
  438. obj_index].open_flag = 1;
  439. outstream_user_open[phm->adapter_index][phm->
  440. obj_index].h_owner = h_owner;
  441. memcpy(phr,
  442. &rESP_HPI_OSTREAM_OPEN[phm->adapter_index]
  443. [phm->obj_index],
  444. sizeof(rESP_HPI_OSTREAM_OPEN[0][0]));
  445. }
  446. }
  447. hpios_msgxlock_unlock(&msgx_lock);
  448. }
  449. static void outstream_close(struct hpi_message *phm, struct hpi_response *phr,
  450. void *h_owner)
  451. {
  452. struct hpi_message hm;
  453. struct hpi_response hr;
  454. hpi_init_response(phr, HPI_OBJ_OSTREAM, HPI_OSTREAM_CLOSE, 0);
  455. hpios_msgxlock_lock(&msgx_lock);
  456. if (h_owner ==
  457. outstream_user_open[phm->adapter_index][phm->
  458. obj_index].h_owner) {
  459. /* HPI_DEBUG_LOG(INFO,"closing adapter %d "
  460. "outstream %d owned by %p\n",
  461. phm->wAdapterIndex, phm->wObjIndex, hOwner); */
  462. outstream_user_open[phm->adapter_index][phm->
  463. obj_index].h_owner = NULL;
  464. hpios_msgxlock_unlock(&msgx_lock);
  465. /* issue a reset */
  466. hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
  467. HPI_OSTREAM_RESET);
  468. hm.adapter_index = phm->adapter_index;
  469. hm.obj_index = phm->obj_index;
  470. hw_entry_point(&hm, &hr);
  471. hpios_msgxlock_lock(&msgx_lock);
  472. if (hr.error) {
  473. outstream_user_open[phm->adapter_index][phm->
  474. obj_index].h_owner = h_owner;
  475. phr->error = hr.error;
  476. } else {
  477. outstream_user_open[phm->adapter_index][phm->
  478. obj_index].open_flag = 0;
  479. outstream_user_open[phm->adapter_index][phm->
  480. obj_index].h_owner = NULL;
  481. }
  482. } else {
  483. HPI_DEBUG_LOG(WARNING,
  484. "%p trying to close %d outstream %d owned by %p\n",
  485. h_owner, phm->adapter_index, phm->obj_index,
  486. outstream_user_open[phm->adapter_index][phm->
  487. obj_index].h_owner);
  488. phr->error = HPI_ERROR_OBJ_NOT_OPEN;
  489. }
  490. hpios_msgxlock_unlock(&msgx_lock);
  491. }
  492. static u16 adapter_prepare(u16 adapter)
  493. {
  494. struct hpi_message hm;
  495. struct hpi_response hr;
  496. /* Open the adapter and streams */
  497. u16 i;
  498. /* call to HPI_ADAPTER_OPEN */
  499. hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
  500. HPI_ADAPTER_OPEN);
  501. hm.adapter_index = adapter;
  502. hw_entry_point(&hm, &hr);
  503. memcpy(&rESP_HPI_ADAPTER_OPEN[adapter], &hr,
  504. sizeof(rESP_HPI_ADAPTER_OPEN[0]));
  505. if (hr.error)
  506. return hr.error;
  507. /* call to HPI_ADAPTER_GET_INFO */
  508. hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
  509. HPI_ADAPTER_GET_INFO);
  510. hm.adapter_index = adapter;
  511. hw_entry_point(&hm, &hr);
  512. if (hr.error)
  513. return hr.error;
  514. aDAPTER_INFO[adapter].num_outstreams = hr.u.ax.info.num_outstreams;
  515. aDAPTER_INFO[adapter].num_instreams = hr.u.ax.info.num_instreams;
  516. aDAPTER_INFO[adapter].type = hr.u.ax.info.adapter_type;
  517. /* call to HPI_OSTREAM_OPEN */
  518. for (i = 0; i < aDAPTER_INFO[adapter].num_outstreams; i++) {
  519. hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
  520. HPI_OSTREAM_OPEN);
  521. hm.adapter_index = adapter;
  522. hm.obj_index = i;
  523. hw_entry_point(&hm, &hr);
  524. memcpy(&rESP_HPI_OSTREAM_OPEN[adapter][i], &hr,
  525. sizeof(rESP_HPI_OSTREAM_OPEN[0][0]));
  526. outstream_user_open[adapter][i].open_flag = 0;
  527. outstream_user_open[adapter][i].h_owner = NULL;
  528. }
  529. /* call to HPI_ISTREAM_OPEN */
  530. for (i = 0; i < aDAPTER_INFO[adapter].num_instreams; i++) {
  531. hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
  532. HPI_ISTREAM_OPEN);
  533. hm.adapter_index = adapter;
  534. hm.obj_index = i;
  535. hw_entry_point(&hm, &hr);
  536. memcpy(&rESP_HPI_ISTREAM_OPEN[adapter][i], &hr,
  537. sizeof(rESP_HPI_ISTREAM_OPEN[0][0]));
  538. instream_user_open[adapter][i].open_flag = 0;
  539. instream_user_open[adapter][i].h_owner = NULL;
  540. }
  541. /* call to HPI_MIXER_OPEN */
  542. hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER, HPI_MIXER_OPEN);
  543. hm.adapter_index = adapter;
  544. hw_entry_point(&hm, &hr);
  545. memcpy(&rESP_HPI_MIXER_OPEN[adapter], &hr,
  546. sizeof(rESP_HPI_MIXER_OPEN[0]));
  547. return 0;
  548. }
  549. static void HPIMSGX__reset(u16 adapter_index)
  550. {
  551. int i;
  552. u16 adapter;
  553. struct hpi_response hr;
  554. if (adapter_index == HPIMSGX_ALLADAPTERS) {
  555. for (adapter = 0; adapter < HPI_MAX_ADAPTERS; adapter++) {
  556. hpi_init_response(&hr, HPI_OBJ_ADAPTER,
  557. HPI_ADAPTER_OPEN, HPI_ERROR_BAD_ADAPTER);
  558. memcpy(&rESP_HPI_ADAPTER_OPEN[adapter], &hr,
  559. sizeof(rESP_HPI_ADAPTER_OPEN[adapter]));
  560. hpi_init_response(&hr, HPI_OBJ_MIXER, HPI_MIXER_OPEN,
  561. HPI_ERROR_INVALID_OBJ);
  562. memcpy(&rESP_HPI_MIXER_OPEN[adapter], &hr,
  563. sizeof(rESP_HPI_MIXER_OPEN[adapter]));
  564. for (i = 0; i < HPI_MAX_STREAMS; i++) {
  565. hpi_init_response(&hr, HPI_OBJ_OSTREAM,
  566. HPI_OSTREAM_OPEN,
  567. HPI_ERROR_INVALID_OBJ);
  568. memcpy(&rESP_HPI_OSTREAM_OPEN[adapter][i],
  569. &hr,
  570. sizeof(rESP_HPI_OSTREAM_OPEN[adapter]
  571. [i]));
  572. hpi_init_response(&hr, HPI_OBJ_ISTREAM,
  573. HPI_ISTREAM_OPEN,
  574. HPI_ERROR_INVALID_OBJ);
  575. memcpy(&rESP_HPI_ISTREAM_OPEN[adapter][i],
  576. &hr,
  577. sizeof(rESP_HPI_ISTREAM_OPEN[adapter]
  578. [i]));
  579. }
  580. }
  581. } else if (adapter_index < HPI_MAX_ADAPTERS) {
  582. rESP_HPI_ADAPTER_OPEN[adapter_index].h.error =
  583. HPI_ERROR_BAD_ADAPTER;
  584. rESP_HPI_MIXER_OPEN[adapter_index].h.error =
  585. HPI_ERROR_INVALID_OBJ;
  586. for (i = 0; i < HPI_MAX_STREAMS; i++) {
  587. rESP_HPI_OSTREAM_OPEN[adapter_index][i].h.error =
  588. HPI_ERROR_INVALID_OBJ;
  589. rESP_HPI_ISTREAM_OPEN[adapter_index][i].h.error =
  590. HPI_ERROR_INVALID_OBJ;
  591. }
  592. }
  593. }
  594. static u16 HPIMSGX__init(struct hpi_message *phm,
  595. /* HPI_SUBSYS_CREATE_ADAPTER structure with */
  596. /* resource list or NULL=find all */
  597. struct hpi_response *phr
  598. /* response from HPI_ADAPTER_GET_INFO */
  599. )
  600. {
  601. hpi_handler_func *entry_point_func;
  602. struct hpi_response hr;
  603. /* Init response here so we can pass in previous adapter list */
  604. hpi_init_response(&hr, phm->object, phm->function,
  605. HPI_ERROR_INVALID_OBJ);
  606. entry_point_func =
  607. hpi_lookup_entry_point_function(phm->u.s.resource.r.pci);
  608. if (entry_point_func) {
  609. HPI_DEBUG_MESSAGE(DEBUG, phm);
  610. entry_point_func(phm, &hr);
  611. } else {
  612. phr->error = HPI_ERROR_PROCESSING_MESSAGE;
  613. return phr->error;
  614. }
  615. if (hr.error == 0) {
  616. /* the adapter was created successfully
  617. save the mapping for future use */
  618. hpi_entry_points[hr.u.s.adapter_index] = entry_point_func;
  619. /* prepare adapter (pre-open streams etc.) */
  620. HPI_DEBUG_LOG(DEBUG,
  621. "HPI_SUBSYS_CREATE_ADAPTER successful,"
  622. " preparing adapter\n");
  623. adapter_prepare(hr.u.s.adapter_index);
  624. }
  625. memcpy(phr, &hr, hr.size);
  626. return phr->error;
  627. }
  628. static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner)
  629. {
  630. int i, adapter, adapter_limit;
  631. if (!h_owner)
  632. return;
  633. if (adapter_index == HPIMSGX_ALLADAPTERS) {
  634. adapter = 0;
  635. adapter_limit = HPI_MAX_ADAPTERS;
  636. } else {
  637. adapter = adapter_index;
  638. adapter_limit = adapter + 1;
  639. }
  640. for (; adapter < adapter_limit; adapter++) {
  641. /* printk(KERN_INFO "Cleanup adapter #%d\n",wAdapter); */
  642. for (i = 0; i < HPI_MAX_STREAMS; i++) {
  643. if (h_owner ==
  644. outstream_user_open[adapter][i].h_owner) {
  645. struct hpi_message hm;
  646. struct hpi_response hr;
  647. HPI_DEBUG_LOG(DEBUG,
  648. "Close adapter %d ostream %d\n",
  649. adapter, i);
  650. hpi_init_message_response(&hm, &hr,
  651. HPI_OBJ_OSTREAM, HPI_OSTREAM_RESET);
  652. hm.adapter_index = (u16)adapter;
  653. hm.obj_index = (u16)i;
  654. hw_entry_point(&hm, &hr);
  655. hm.function = HPI_OSTREAM_HOSTBUFFER_FREE;
  656. hw_entry_point(&hm, &hr);
  657. hm.function = HPI_OSTREAM_GROUP_RESET;
  658. hw_entry_point(&hm, &hr);
  659. outstream_user_open[adapter][i].open_flag = 0;
  660. outstream_user_open[adapter][i].h_owner =
  661. NULL;
  662. }
  663. if (h_owner == instream_user_open[adapter][i].h_owner) {
  664. struct hpi_message hm;
  665. struct hpi_response hr;
  666. HPI_DEBUG_LOG(DEBUG,
  667. "Close adapter %d istream %d\n",
  668. adapter, i);
  669. hpi_init_message_response(&hm, &hr,
  670. HPI_OBJ_ISTREAM, HPI_ISTREAM_RESET);
  671. hm.adapter_index = (u16)adapter;
  672. hm.obj_index = (u16)i;
  673. hw_entry_point(&hm, &hr);
  674. hm.function = HPI_ISTREAM_HOSTBUFFER_FREE;
  675. hw_entry_point(&hm, &hr);
  676. hm.function = HPI_ISTREAM_GROUP_RESET;
  677. hw_entry_point(&hm, &hr);
  678. instream_user_open[adapter][i].open_flag = 0;
  679. instream_user_open[adapter][i].h_owner = NULL;
  680. }
  681. }
  682. }
  683. }