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