hpimsgx.c 21 KB

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