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