hpimsgx.c 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907
  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 "hpimsgx.h"
  21. #include "hpidebug.h"
  22. static struct pci_device_id asihpi_pci_tbl[] = {
  23. #include "hpipcida.h"
  24. };
  25. static struct hpios_spinlock msgx_lock;
  26. static hpi_handler_func *hpi_entry_points[HPI_MAX_ADAPTERS];
  27. static hpi_handler_func *hpi_lookup_entry_point_function(const struct hpi_pci
  28. *pci_info)
  29. {
  30. int i;
  31. for (i = 0; asihpi_pci_tbl[i].vendor != 0; i++) {
  32. if (asihpi_pci_tbl[i].vendor != PCI_ANY_ID
  33. && asihpi_pci_tbl[i].vendor != pci_info->vendor_id)
  34. continue;
  35. if (asihpi_pci_tbl[i].device != PCI_ANY_ID
  36. && asihpi_pci_tbl[i].device != pci_info->device_id)
  37. continue;
  38. if (asihpi_pci_tbl[i].subvendor != PCI_ANY_ID
  39. && asihpi_pci_tbl[i].subvendor !=
  40. pci_info->subsys_vendor_id)
  41. continue;
  42. if (asihpi_pci_tbl[i].subdevice != PCI_ANY_ID
  43. && asihpi_pci_tbl[i].subdevice !=
  44. pci_info->subsys_device_id)
  45. continue;
  46. HPI_DEBUG_LOG(DEBUG, " %x,%lu\n", i,
  47. asihpi_pci_tbl[i].driver_data);
  48. return (hpi_handler_func *) asihpi_pci_tbl[i].driver_data;
  49. }
  50. return NULL;
  51. }
  52. static inline void hw_entry_point(struct hpi_message *phm,
  53. struct hpi_response *phr)
  54. {
  55. hpi_handler_func *ep;
  56. if (phm->adapter_index < HPI_MAX_ADAPTERS) {
  57. ep = (hpi_handler_func *) hpi_entry_points[phm->
  58. adapter_index];
  59. if (ep) {
  60. HPI_DEBUG_MESSAGE(DEBUG, phm);
  61. ep(phm, phr);
  62. HPI_DEBUG_RESPONSE(phr);
  63. return;
  64. }
  65. }
  66. hpi_init_response(phr, phm->object, phm->function,
  67. HPI_ERROR_PROCESSING_MESSAGE);
  68. }
  69. static void adapter_open(struct hpi_message *phm, struct hpi_response *phr);
  70. static void adapter_close(struct hpi_message *phm, struct hpi_response *phr);
  71. static void mixer_open(struct hpi_message *phm, struct hpi_response *phr);
  72. static void mixer_close(struct hpi_message *phm, struct hpi_response *phr);
  73. static void outstream_open(struct hpi_message *phm, struct hpi_response *phr,
  74. void *h_owner);
  75. static void outstream_close(struct hpi_message *phm, struct hpi_response *phr,
  76. void *h_owner);
  77. static void instream_open(struct hpi_message *phm, struct hpi_response *phr,
  78. void *h_owner);
  79. static void instream_close(struct hpi_message *phm, struct hpi_response *phr,
  80. void *h_owner);
  81. static void HPIMSGX__reset(u16 adapter_index);
  82. static u16 HPIMSGX__init(struct hpi_message *phm, struct hpi_response *phr);
  83. static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner);
  84. #ifndef DISABLE_PRAGMA_PACK1
  85. #pragma pack(push, 1)
  86. #endif
  87. struct hpi_subsys_response {
  88. struct hpi_response_header h;
  89. struct hpi_subsys_res s;
  90. };
  91. struct hpi_adapter_response {
  92. struct hpi_response_header h;
  93. struct hpi_adapter_res a;
  94. };
  95. struct hpi_mixer_response {
  96. struct hpi_response_header h;
  97. struct hpi_mixer_res m;
  98. };
  99. struct hpi_stream_response {
  100. struct hpi_response_header h;
  101. struct hpi_stream_res d;
  102. };
  103. struct adapter_info {
  104. u16 type;
  105. u16 num_instreams;
  106. u16 num_outstreams;
  107. };
  108. struct asi_open_state {
  109. int open_flag;
  110. void *h_owner;
  111. };
  112. #ifndef DISABLE_PRAGMA_PACK1
  113. #pragma pack(pop)
  114. #endif
  115. /* Globals */
  116. static struct hpi_adapter_response rESP_HPI_ADAPTER_OPEN[HPI_MAX_ADAPTERS];
  117. static struct hpi_stream_response
  118. rESP_HPI_OSTREAM_OPEN[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
  119. static struct hpi_stream_response
  120. rESP_HPI_ISTREAM_OPEN[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
  121. static struct hpi_mixer_response rESP_HPI_MIXER_OPEN[HPI_MAX_ADAPTERS];
  122. static struct hpi_subsys_response gRESP_HPI_SUBSYS_FIND_ADAPTERS;
  123. static struct adapter_info aDAPTER_INFO[HPI_MAX_ADAPTERS];
  124. /* use these to keep track of opens from user mode apps/DLLs */
  125. static struct asi_open_state
  126. outstream_user_open[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
  127. static struct asi_open_state
  128. instream_user_open[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
  129. static void subsys_message(struct hpi_message *phm, struct hpi_response *phr,
  130. void *h_owner)
  131. {
  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. hpios_locked_mem_init();
  154. /* Init subsys_findadapters response to no-adapters */
  155. HPIMSGX__reset(HPIMSGX_ALLADAPTERS);
  156. hpi_init_response(phr, HPI_OBJ_SUBSYSTEM,
  157. HPI_SUBSYS_DRIVER_LOAD, 0);
  158. /* individual HPIs dont implement driver load */
  159. HPI_COMMON(phm, phr);
  160. break;
  161. case HPI_SUBSYS_DRIVER_UNLOAD:
  162. HPI_COMMON(phm, phr);
  163. HPIMSGX__cleanup(HPIMSGX_ALLADAPTERS, h_owner);
  164. hpios_locked_mem_free_all();
  165. hpi_init_response(phr, HPI_OBJ_SUBSYSTEM,
  166. HPI_SUBSYS_DRIVER_UNLOAD, 0);
  167. return;
  168. case HPI_SUBSYS_GET_INFO:
  169. HPI_COMMON(phm, phr);
  170. break;
  171. case HPI_SUBSYS_FIND_ADAPTERS:
  172. memcpy(phr, &gRESP_HPI_SUBSYS_FIND_ADAPTERS,
  173. sizeof(gRESP_HPI_SUBSYS_FIND_ADAPTERS));
  174. break;
  175. case HPI_SUBSYS_GET_NUM_ADAPTERS:
  176. memcpy(phr, &gRESP_HPI_SUBSYS_FIND_ADAPTERS,
  177. sizeof(gRESP_HPI_SUBSYS_FIND_ADAPTERS));
  178. phr->function = HPI_SUBSYS_GET_NUM_ADAPTERS;
  179. break;
  180. case HPI_SUBSYS_GET_ADAPTER:
  181. {
  182. int count = phm->adapter_index;
  183. int index = 0;
  184. hpi_init_response(phr, HPI_OBJ_SUBSYSTEM,
  185. HPI_SUBSYS_GET_ADAPTER, 0);
  186. /* This is complicated by the fact that we want to
  187. * "skip" 0's in the adapter list.
  188. * First, make sure we are pointing to a
  189. * non-zero adapter type.
  190. */
  191. while (gRESP_HPI_SUBSYS_FIND_ADAPTERS.
  192. s.aw_adapter_list[index] == 0) {
  193. index++;
  194. if (index >= HPI_MAX_ADAPTERS)
  195. break;
  196. }
  197. while (count) {
  198. /* move on to the next adapter */
  199. index++;
  200. if (index >= HPI_MAX_ADAPTERS)
  201. break;
  202. while (gRESP_HPI_SUBSYS_FIND_ADAPTERS.
  203. s.aw_adapter_list[index] == 0) {
  204. index++;
  205. if (index >= HPI_MAX_ADAPTERS)
  206. break;
  207. }
  208. count--;
  209. }
  210. if (index < HPI_MAX_ADAPTERS) {
  211. phr->u.s.adapter_index = (u16)index;
  212. phr->u.s.aw_adapter_list[0] =
  213. gRESP_HPI_SUBSYS_FIND_ADAPTERS.
  214. s.aw_adapter_list[index];
  215. } else {
  216. phr->u.s.adapter_index = 0;
  217. phr->u.s.aw_adapter_list[0] = 0;
  218. phr->error = HPI_ERROR_BAD_ADAPTER_NUMBER;
  219. }
  220. break;
  221. }
  222. case HPI_SUBSYS_CREATE_ADAPTER:
  223. HPIMSGX__init(phm, phr);
  224. break;
  225. case HPI_SUBSYS_DELETE_ADAPTER:
  226. HPIMSGX__cleanup(phm->adapter_index, h_owner);
  227. {
  228. struct hpi_message hm;
  229. struct hpi_response hr;
  230. /* call to HPI_ADAPTER_CLOSE */
  231. hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
  232. HPI_ADAPTER_CLOSE);
  233. hm.adapter_index = phm->adapter_index;
  234. hw_entry_point(&hm, &hr);
  235. }
  236. hw_entry_point(phm, phr);
  237. gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.
  238. aw_adapter_list[phm->adapter_index]
  239. = 0;
  240. hpi_entry_points[phm->adapter_index] = NULL;
  241. break;
  242. default:
  243. hw_entry_point(phm, phr);
  244. break;
  245. }
  246. }
  247. static void adapter_message(struct hpi_message *phm, struct hpi_response *phr,
  248. void *h_owner)
  249. {
  250. switch (phm->function) {
  251. case HPI_ADAPTER_OPEN:
  252. adapter_open(phm, phr);
  253. break;
  254. case HPI_ADAPTER_CLOSE:
  255. adapter_close(phm, phr);
  256. break;
  257. default:
  258. hw_entry_point(phm, phr);
  259. break;
  260. }
  261. }
  262. static void mixer_message(struct hpi_message *phm, struct hpi_response *phr)
  263. {
  264. switch (phm->function) {
  265. case HPI_MIXER_OPEN:
  266. mixer_open(phm, phr);
  267. break;
  268. case HPI_MIXER_CLOSE:
  269. mixer_close(phm, phr);
  270. break;
  271. default:
  272. hw_entry_point(phm, phr);
  273. break;
  274. }
  275. }
  276. static void outstream_message(struct hpi_message *phm,
  277. struct hpi_response *phr, void *h_owner)
  278. {
  279. if (phm->obj_index >= aDAPTER_INFO[phm->adapter_index].num_outstreams) {
  280. hpi_init_response(phr, HPI_OBJ_OSTREAM, phm->function,
  281. HPI_ERROR_INVALID_OBJ_INDEX);
  282. return;
  283. }
  284. switch (phm->function) {
  285. case HPI_OSTREAM_OPEN:
  286. outstream_open(phm, phr, h_owner);
  287. break;
  288. case HPI_OSTREAM_CLOSE:
  289. outstream_close(phm, phr, h_owner);
  290. break;
  291. default:
  292. hw_entry_point(phm, phr);
  293. break;
  294. }
  295. }
  296. static void instream_message(struct hpi_message *phm,
  297. struct hpi_response *phr, void *h_owner)
  298. {
  299. if (phm->obj_index >= aDAPTER_INFO[phm->adapter_index].num_instreams) {
  300. hpi_init_response(phr, HPI_OBJ_ISTREAM, phm->function,
  301. HPI_ERROR_INVALID_OBJ_INDEX);
  302. return;
  303. }
  304. switch (phm->function) {
  305. case HPI_ISTREAM_OPEN:
  306. instream_open(phm, phr, h_owner);
  307. break;
  308. case HPI_ISTREAM_CLOSE:
  309. instream_close(phm, phr, h_owner);
  310. break;
  311. default:
  312. hw_entry_point(phm, phr);
  313. break;
  314. }
  315. }
  316. /* NOTE: HPI_Message() must be defined in the driver as a wrapper for
  317. * HPI_MessageEx so that functions in hpifunc.c compile.
  318. */
  319. void hpi_send_recv_ex(struct hpi_message *phm, struct hpi_response *phr,
  320. void *h_owner)
  321. {
  322. HPI_DEBUG_MESSAGE(DEBUG, phm);
  323. if (phm->type != HPI_TYPE_MESSAGE) {
  324. hpi_init_response(phr, phm->object, phm->function,
  325. HPI_ERROR_INVALID_TYPE);
  326. return;
  327. }
  328. if (phm->adapter_index >= HPI_MAX_ADAPTERS
  329. && phm->adapter_index != HPIMSGX_ALLADAPTERS) {
  330. hpi_init_response(phr, phm->object, phm->function,
  331. HPI_ERROR_BAD_ADAPTER_NUMBER);
  332. return;
  333. }
  334. switch (phm->object) {
  335. case HPI_OBJ_SUBSYSTEM:
  336. subsys_message(phm, phr, h_owner);
  337. break;
  338. case HPI_OBJ_ADAPTER:
  339. adapter_message(phm, phr, h_owner);
  340. break;
  341. case HPI_OBJ_MIXER:
  342. mixer_message(phm, phr);
  343. break;
  344. case HPI_OBJ_OSTREAM:
  345. outstream_message(phm, phr, h_owner);
  346. break;
  347. case HPI_OBJ_ISTREAM:
  348. instream_message(phm, phr, h_owner);
  349. break;
  350. default:
  351. hw_entry_point(phm, phr);
  352. break;
  353. }
  354. HPI_DEBUG_RESPONSE(phr);
  355. #if 1
  356. if (phr->error >= HPI_ERROR_BACKEND_BASE) {
  357. void *ep = NULL;
  358. char *ep_name;
  359. HPI_DEBUG_MESSAGE(ERROR, phm);
  360. if (phm->adapter_index < HPI_MAX_ADAPTERS)
  361. ep = hpi_entry_points[phm->adapter_index];
  362. /* Don't need this? Have adapter index in debug info
  363. Know at driver load time index->backend mapping */
  364. if (ep == HPI_6000)
  365. ep_name = "HPI_6000";
  366. else if (ep == HPI_6205)
  367. ep_name = "HPI_6205";
  368. else
  369. ep_name = "unknown";
  370. HPI_DEBUG_LOG(ERROR, "HPI %s response - error# %d\n", ep_name,
  371. phr->error);
  372. if (hpi_debug_level >= HPI_DEBUG_LEVEL_VERBOSE)
  373. hpi_debug_data((u16 *)phm,
  374. sizeof(*phm) / sizeof(u16));
  375. }
  376. #endif
  377. }
  378. static void adapter_open(struct hpi_message *phm, struct hpi_response *phr)
  379. {
  380. HPI_DEBUG_LOG(VERBOSE, "adapter_open\n");
  381. memcpy(phr, &rESP_HPI_ADAPTER_OPEN[phm->adapter_index],
  382. sizeof(rESP_HPI_ADAPTER_OPEN[0]));
  383. }
  384. static void adapter_close(struct hpi_message *phm, struct hpi_response *phr)
  385. {
  386. HPI_DEBUG_LOG(VERBOSE, "adapter_close\n");
  387. hpi_init_response(phr, HPI_OBJ_ADAPTER, HPI_ADAPTER_CLOSE, 0);
  388. }
  389. static void mixer_open(struct hpi_message *phm, struct hpi_response *phr)
  390. {
  391. memcpy(phr, &rESP_HPI_MIXER_OPEN[phm->adapter_index],
  392. sizeof(rESP_HPI_MIXER_OPEN[0]));
  393. }
  394. static void mixer_close(struct hpi_message *phm, struct hpi_response *phr)
  395. {
  396. hpi_init_response(phr, HPI_OBJ_MIXER, HPI_MIXER_CLOSE, 0);
  397. }
  398. static void instream_open(struct hpi_message *phm, struct hpi_response *phr,
  399. void *h_owner)
  400. {
  401. struct hpi_message hm;
  402. struct hpi_response hr;
  403. hpi_init_response(phr, HPI_OBJ_ISTREAM, HPI_ISTREAM_OPEN, 0);
  404. hpios_msgxlock_lock(&msgx_lock);
  405. if (instream_user_open[phm->adapter_index][phm->obj_index].open_flag)
  406. phr->error = HPI_ERROR_OBJ_ALREADY_OPEN;
  407. else if (rESP_HPI_ISTREAM_OPEN[phm->adapter_index]
  408. [phm->obj_index].h.error)
  409. memcpy(phr,
  410. &rESP_HPI_ISTREAM_OPEN[phm->adapter_index][phm->
  411. obj_index],
  412. sizeof(rESP_HPI_ISTREAM_OPEN[0][0]));
  413. else {
  414. instream_user_open[phm->adapter_index][phm->
  415. obj_index].open_flag = 1;
  416. hpios_msgxlock_un_lock(&msgx_lock);
  417. /* issue a reset */
  418. hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
  419. HPI_ISTREAM_RESET);
  420. hm.adapter_index = phm->adapter_index;
  421. hm.obj_index = phm->obj_index;
  422. hw_entry_point(&hm, &hr);
  423. hpios_msgxlock_lock(&msgx_lock);
  424. if (hr.error) {
  425. instream_user_open[phm->adapter_index][phm->
  426. obj_index].open_flag = 0;
  427. phr->error = hr.error;
  428. } else {
  429. instream_user_open[phm->adapter_index][phm->
  430. obj_index].open_flag = 1;
  431. instream_user_open[phm->adapter_index][phm->
  432. obj_index].h_owner = h_owner;
  433. memcpy(phr,
  434. &rESP_HPI_ISTREAM_OPEN[phm->adapter_index]
  435. [phm->obj_index],
  436. sizeof(rESP_HPI_ISTREAM_OPEN[0][0]));
  437. }
  438. }
  439. hpios_msgxlock_un_lock(&msgx_lock);
  440. }
  441. static void instream_close(struct hpi_message *phm, struct hpi_response *phr,
  442. void *h_owner)
  443. {
  444. struct hpi_message hm;
  445. struct hpi_response hr;
  446. hpi_init_response(phr, HPI_OBJ_ISTREAM, HPI_ISTREAM_CLOSE, 0);
  447. hpios_msgxlock_lock(&msgx_lock);
  448. if (h_owner ==
  449. instream_user_open[phm->adapter_index][phm->
  450. obj_index].h_owner) {
  451. /* HPI_DEBUG_LOG(INFO,"closing adapter %d "
  452. "instream %d owned by %p\n",
  453. phm->wAdapterIndex, phm->wObjIndex, hOwner); */
  454. instream_user_open[phm->adapter_index][phm->
  455. obj_index].h_owner = NULL;
  456. hpios_msgxlock_un_lock(&msgx_lock);
  457. /* issue a reset */
  458. hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
  459. HPI_ISTREAM_RESET);
  460. hm.adapter_index = phm->adapter_index;
  461. hm.obj_index = phm->obj_index;
  462. hw_entry_point(&hm, &hr);
  463. hpios_msgxlock_lock(&msgx_lock);
  464. if (hr.error) {
  465. instream_user_open[phm->adapter_index][phm->
  466. obj_index].h_owner = h_owner;
  467. phr->error = hr.error;
  468. } else {
  469. instream_user_open[phm->adapter_index][phm->
  470. obj_index].open_flag = 0;
  471. instream_user_open[phm->adapter_index][phm->
  472. obj_index].h_owner = NULL;
  473. }
  474. } else {
  475. HPI_DEBUG_LOG(WARNING,
  476. "%p trying to close %d instream %d owned by %p\n",
  477. h_owner, phm->adapter_index, phm->obj_index,
  478. instream_user_open[phm->adapter_index][phm->
  479. obj_index].h_owner);
  480. phr->error = HPI_ERROR_OBJ_NOT_OPEN;
  481. }
  482. hpios_msgxlock_un_lock(&msgx_lock);
  483. }
  484. static void outstream_open(struct hpi_message *phm, struct hpi_response *phr,
  485. void *h_owner)
  486. {
  487. struct hpi_message hm;
  488. struct hpi_response hr;
  489. hpi_init_response(phr, HPI_OBJ_OSTREAM, HPI_OSTREAM_OPEN, 0);
  490. hpios_msgxlock_lock(&msgx_lock);
  491. if (outstream_user_open[phm->adapter_index][phm->obj_index].open_flag)
  492. phr->error = HPI_ERROR_OBJ_ALREADY_OPEN;
  493. else if (rESP_HPI_OSTREAM_OPEN[phm->adapter_index]
  494. [phm->obj_index].h.error)
  495. memcpy(phr,
  496. &rESP_HPI_OSTREAM_OPEN[phm->adapter_index][phm->
  497. obj_index],
  498. sizeof(rESP_HPI_OSTREAM_OPEN[0][0]));
  499. else {
  500. outstream_user_open[phm->adapter_index][phm->
  501. obj_index].open_flag = 1;
  502. hpios_msgxlock_un_lock(&msgx_lock);
  503. /* issue a reset */
  504. hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
  505. HPI_OSTREAM_RESET);
  506. hm.adapter_index = phm->adapter_index;
  507. hm.obj_index = phm->obj_index;
  508. hw_entry_point(&hm, &hr);
  509. hpios_msgxlock_lock(&msgx_lock);
  510. if (hr.error) {
  511. outstream_user_open[phm->adapter_index][phm->
  512. obj_index].open_flag = 0;
  513. phr->error = hr.error;
  514. } else {
  515. outstream_user_open[phm->adapter_index][phm->
  516. obj_index].open_flag = 1;
  517. outstream_user_open[phm->adapter_index][phm->
  518. obj_index].h_owner = h_owner;
  519. memcpy(phr,
  520. &rESP_HPI_OSTREAM_OPEN[phm->adapter_index]
  521. [phm->obj_index],
  522. sizeof(rESP_HPI_OSTREAM_OPEN[0][0]));
  523. }
  524. }
  525. hpios_msgxlock_un_lock(&msgx_lock);
  526. }
  527. static void outstream_close(struct hpi_message *phm, struct hpi_response *phr,
  528. void *h_owner)
  529. {
  530. struct hpi_message hm;
  531. struct hpi_response hr;
  532. hpi_init_response(phr, HPI_OBJ_OSTREAM, HPI_OSTREAM_CLOSE, 0);
  533. hpios_msgxlock_lock(&msgx_lock);
  534. if (h_owner ==
  535. outstream_user_open[phm->adapter_index][phm->
  536. obj_index].h_owner) {
  537. /* HPI_DEBUG_LOG(INFO,"closing adapter %d "
  538. "outstream %d owned by %p\n",
  539. phm->wAdapterIndex, phm->wObjIndex, hOwner); */
  540. outstream_user_open[phm->adapter_index][phm->
  541. obj_index].h_owner = NULL;
  542. hpios_msgxlock_un_lock(&msgx_lock);
  543. /* issue a reset */
  544. hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
  545. HPI_OSTREAM_RESET);
  546. hm.adapter_index = phm->adapter_index;
  547. hm.obj_index = phm->obj_index;
  548. hw_entry_point(&hm, &hr);
  549. hpios_msgxlock_lock(&msgx_lock);
  550. if (hr.error) {
  551. outstream_user_open[phm->adapter_index][phm->
  552. obj_index].h_owner = h_owner;
  553. phr->error = hr.error;
  554. } else {
  555. outstream_user_open[phm->adapter_index][phm->
  556. obj_index].open_flag = 0;
  557. outstream_user_open[phm->adapter_index][phm->
  558. obj_index].h_owner = NULL;
  559. }
  560. } else {
  561. HPI_DEBUG_LOG(WARNING,
  562. "%p trying to close %d outstream %d owned by %p\n",
  563. h_owner, phm->adapter_index, phm->obj_index,
  564. outstream_user_open[phm->adapter_index][phm->
  565. obj_index].h_owner);
  566. phr->error = HPI_ERROR_OBJ_NOT_OPEN;
  567. }
  568. hpios_msgxlock_un_lock(&msgx_lock);
  569. }
  570. static u16 adapter_prepare(u16 adapter)
  571. {
  572. struct hpi_message hm;
  573. struct hpi_response hr;
  574. /* Open the adapter and streams */
  575. u16 i;
  576. /* call to HPI_ADAPTER_OPEN */
  577. hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
  578. HPI_ADAPTER_OPEN);
  579. hm.adapter_index = adapter;
  580. hw_entry_point(&hm, &hr);
  581. memcpy(&rESP_HPI_ADAPTER_OPEN[adapter], &hr,
  582. sizeof(rESP_HPI_ADAPTER_OPEN[0]));
  583. if (hr.error)
  584. return hr.error;
  585. /* call to HPI_ADAPTER_GET_INFO */
  586. hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
  587. HPI_ADAPTER_GET_INFO);
  588. hm.adapter_index = adapter;
  589. hw_entry_point(&hm, &hr);
  590. if (hr.error)
  591. return hr.error;
  592. aDAPTER_INFO[adapter].num_outstreams = hr.u.a.num_outstreams;
  593. aDAPTER_INFO[adapter].num_instreams = hr.u.a.num_instreams;
  594. aDAPTER_INFO[adapter].type = hr.u.a.adapter_type;
  595. gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.aw_adapter_list[adapter] =
  596. hr.u.a.adapter_type;
  597. gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters++;
  598. if (gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters > HPI_MAX_ADAPTERS)
  599. gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters =
  600. HPI_MAX_ADAPTERS;
  601. /* call to HPI_OSTREAM_OPEN */
  602. for (i = 0; i < aDAPTER_INFO[adapter].num_outstreams; i++) {
  603. hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
  604. HPI_OSTREAM_OPEN);
  605. hm.adapter_index = adapter;
  606. hm.obj_index = i;
  607. hw_entry_point(&hm, &hr);
  608. memcpy(&rESP_HPI_OSTREAM_OPEN[adapter][i], &hr,
  609. sizeof(rESP_HPI_OSTREAM_OPEN[0][0]));
  610. outstream_user_open[adapter][i].open_flag = 0;
  611. outstream_user_open[adapter][i].h_owner = NULL;
  612. }
  613. /* call to HPI_ISTREAM_OPEN */
  614. for (i = 0; i < aDAPTER_INFO[adapter].num_instreams; i++) {
  615. hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
  616. HPI_ISTREAM_OPEN);
  617. hm.adapter_index = adapter;
  618. hm.obj_index = i;
  619. hw_entry_point(&hm, &hr);
  620. memcpy(&rESP_HPI_ISTREAM_OPEN[adapter][i], &hr,
  621. sizeof(rESP_HPI_ISTREAM_OPEN[0][0]));
  622. instream_user_open[adapter][i].open_flag = 0;
  623. instream_user_open[adapter][i].h_owner = NULL;
  624. }
  625. /* call to HPI_MIXER_OPEN */
  626. hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER, HPI_MIXER_OPEN);
  627. hm.adapter_index = adapter;
  628. hw_entry_point(&hm, &hr);
  629. memcpy(&rESP_HPI_MIXER_OPEN[adapter], &hr,
  630. sizeof(rESP_HPI_MIXER_OPEN[0]));
  631. return gRESP_HPI_SUBSYS_FIND_ADAPTERS.h.error;
  632. }
  633. static void HPIMSGX__reset(u16 adapter_index)
  634. {
  635. int i;
  636. u16 adapter;
  637. struct hpi_response hr;
  638. if (adapter_index == HPIMSGX_ALLADAPTERS) {
  639. /* reset all responses to contain errors */
  640. hpi_init_response(&hr, HPI_OBJ_SUBSYSTEM,
  641. HPI_SUBSYS_FIND_ADAPTERS, 0);
  642. memcpy(&gRESP_HPI_SUBSYS_FIND_ADAPTERS, &hr,
  643. sizeof(gRESP_HPI_SUBSYS_FIND_ADAPTERS));
  644. for (adapter = 0; adapter < HPI_MAX_ADAPTERS; adapter++) {
  645. hpi_init_response(&hr, HPI_OBJ_ADAPTER,
  646. HPI_ADAPTER_OPEN, HPI_ERROR_BAD_ADAPTER);
  647. memcpy(&rESP_HPI_ADAPTER_OPEN[adapter], &hr,
  648. sizeof(rESP_HPI_ADAPTER_OPEN[adapter]));
  649. hpi_init_response(&hr, HPI_OBJ_MIXER, HPI_MIXER_OPEN,
  650. HPI_ERROR_INVALID_OBJ);
  651. memcpy(&rESP_HPI_MIXER_OPEN[adapter], &hr,
  652. sizeof(rESP_HPI_MIXER_OPEN[adapter]));
  653. for (i = 0; i < HPI_MAX_STREAMS; i++) {
  654. hpi_init_response(&hr, HPI_OBJ_OSTREAM,
  655. HPI_OSTREAM_OPEN,
  656. HPI_ERROR_INVALID_OBJ);
  657. memcpy(&rESP_HPI_OSTREAM_OPEN[adapter][i],
  658. &hr,
  659. sizeof(rESP_HPI_OSTREAM_OPEN[adapter]
  660. [i]));
  661. hpi_init_response(&hr, HPI_OBJ_ISTREAM,
  662. HPI_ISTREAM_OPEN,
  663. HPI_ERROR_INVALID_OBJ);
  664. memcpy(&rESP_HPI_ISTREAM_OPEN[adapter][i],
  665. &hr,
  666. sizeof(rESP_HPI_ISTREAM_OPEN[adapter]
  667. [i]));
  668. }
  669. }
  670. } else if (adapter_index < HPI_MAX_ADAPTERS) {
  671. rESP_HPI_ADAPTER_OPEN[adapter_index].h.error =
  672. HPI_ERROR_BAD_ADAPTER;
  673. rESP_HPI_MIXER_OPEN[adapter_index].h.error =
  674. HPI_ERROR_INVALID_OBJ;
  675. for (i = 0; i < HPI_MAX_STREAMS; i++) {
  676. rESP_HPI_OSTREAM_OPEN[adapter_index][i].h.error =
  677. HPI_ERROR_INVALID_OBJ;
  678. rESP_HPI_ISTREAM_OPEN[adapter_index][i].h.error =
  679. HPI_ERROR_INVALID_OBJ;
  680. }
  681. if (gRESP_HPI_SUBSYS_FIND_ADAPTERS.
  682. s.aw_adapter_list[adapter_index]) {
  683. gRESP_HPI_SUBSYS_FIND_ADAPTERS.
  684. s.aw_adapter_list[adapter_index] = 0;
  685. gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters--;
  686. }
  687. }
  688. }
  689. static u16 HPIMSGX__init(struct hpi_message *phm,
  690. /* HPI_SUBSYS_CREATE_ADAPTER structure with */
  691. /* resource list or NULL=find all */
  692. struct hpi_response *phr
  693. /* response from HPI_ADAPTER_GET_INFO */
  694. )
  695. {
  696. hpi_handler_func *entry_point_func;
  697. struct hpi_response hr;
  698. if (gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.num_adapters >= HPI_MAX_ADAPTERS)
  699. return HPI_ERROR_BAD_ADAPTER_NUMBER;
  700. /* Init response here so we can pass in previous adapter list */
  701. hpi_init_response(&hr, phm->object, phm->function,
  702. HPI_ERROR_INVALID_OBJ);
  703. memcpy(hr.u.s.aw_adapter_list,
  704. gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.aw_adapter_list,
  705. sizeof(gRESP_HPI_SUBSYS_FIND_ADAPTERS.s.aw_adapter_list));
  706. entry_point_func =
  707. hpi_lookup_entry_point_function(phm->u.s.resource.r.pci);
  708. if (entry_point_func) {
  709. HPI_DEBUG_MESSAGE(DEBUG, phm);
  710. entry_point_func(phm, &hr);
  711. } else {
  712. phr->error = HPI_ERROR_PROCESSING_MESSAGE;
  713. return phr->error;
  714. }
  715. if (hr.error == 0) {
  716. /* the adapter was created succesfully
  717. save the mapping for future use */
  718. hpi_entry_points[hr.u.s.adapter_index] = entry_point_func;
  719. /* prepare adapter (pre-open streams etc.) */
  720. HPI_DEBUG_LOG(DEBUG,
  721. "HPI_SUBSYS_CREATE_ADAPTER successful,"
  722. " preparing adapter\n");
  723. adapter_prepare(hr.u.s.adapter_index);
  724. }
  725. memcpy(phr, &hr, hr.size);
  726. return phr->error;
  727. }
  728. static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner)
  729. {
  730. int i, adapter, adapter_limit;
  731. if (!h_owner)
  732. return;
  733. if (adapter_index == HPIMSGX_ALLADAPTERS) {
  734. adapter = 0;
  735. adapter_limit = HPI_MAX_ADAPTERS;
  736. } else {
  737. adapter = adapter_index;
  738. adapter_limit = adapter + 1;
  739. }
  740. for (; adapter < adapter_limit; adapter++) {
  741. /* printk(KERN_INFO "Cleanup adapter #%d\n",wAdapter); */
  742. for (i = 0; i < HPI_MAX_STREAMS; i++) {
  743. if (h_owner ==
  744. outstream_user_open[adapter][i].h_owner) {
  745. struct hpi_message hm;
  746. struct hpi_response hr;
  747. HPI_DEBUG_LOG(DEBUG,
  748. "close adapter %d ostream %d\n",
  749. adapter, i);
  750. hpi_init_message_response(&hm, &hr,
  751. HPI_OBJ_OSTREAM, HPI_OSTREAM_RESET);
  752. hm.adapter_index = (u16)adapter;
  753. hm.obj_index = (u16)i;
  754. hw_entry_point(&hm, &hr);
  755. hm.function = HPI_OSTREAM_HOSTBUFFER_FREE;
  756. hw_entry_point(&hm, &hr);
  757. hm.function = HPI_OSTREAM_GROUP_RESET;
  758. hw_entry_point(&hm, &hr);
  759. outstream_user_open[adapter][i].open_flag = 0;
  760. outstream_user_open[adapter][i].h_owner =
  761. NULL;
  762. }
  763. if (h_owner == instream_user_open[adapter][i].h_owner) {
  764. struct hpi_message hm;
  765. struct hpi_response hr;
  766. HPI_DEBUG_LOG(DEBUG,
  767. "close adapter %d istream %d\n",
  768. adapter, i);
  769. hpi_init_message_response(&hm, &hr,
  770. HPI_OBJ_ISTREAM, HPI_ISTREAM_RESET);
  771. hm.adapter_index = (u16)adapter;
  772. hm.obj_index = (u16)i;
  773. hw_entry_point(&hm, &hr);
  774. hm.function = HPI_ISTREAM_HOSTBUFFER_FREE;
  775. hw_entry_point(&hm, &hr);
  776. hm.function = HPI_ISTREAM_GROUP_RESET;
  777. hw_entry_point(&hm, &hr);
  778. instream_user_open[adapter][i].open_flag = 0;
  779. instream_user_open[adapter][i].h_owner = NULL;
  780. }
  781. }
  782. }
  783. }