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
8Extended 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
20static const struct pci_device_id asihpi_pci_tbl[] = {
21#include "hpipcida.h"
22};
23
24static struct hpios_spinlock msgx_lock;
25
26static hpi_handler_func *hpi_entry_points[HPI_MAX_ADAPTERS];
27static int logging_enabled = 1;
28
29static 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
61static 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
72static void adapter_open(struct hpi_message *phm, struct hpi_response *phr);
73static void adapter_close(struct hpi_message *phm, struct hpi_response *phr);
74
75static void mixer_open(struct hpi_message *phm, struct hpi_response *phr);
76static void mixer_close(struct hpi_message *phm, struct hpi_response *phr);
77
78static void outstream_open(struct hpi_message *phm, struct hpi_response *phr,
79	void *h_owner);
80static void outstream_close(struct hpi_message *phm, struct hpi_response *phr,
81	void *h_owner);
82static void instream_open(struct hpi_message *phm, struct hpi_response *phr,
83	void *h_owner);
84static void instream_close(struct hpi_message *phm, struct hpi_response *phr,
85	void *h_owner);
86
87static void HPIMSGX__reset(u16 adapter_index);
88
89static u16 HPIMSGX__init(struct hpi_message *phm, struct hpi_response *phr);
90static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner);
91
92#ifndef DISABLE_PRAGMA_PACK1
93#pragma pack(push, 1)
94#endif
95
96struct hpi_subsys_response {
97	struct hpi_response_header h;
98	struct hpi_subsys_res s;
99};
100
101struct hpi_adapter_response {
102	struct hpi_response_header h;
103	struct hpi_adapter_res a;
104};
105
106struct hpi_mixer_response {
107	struct hpi_response_header h;
108	struct hpi_mixer_res m;
109};
110
111struct hpi_stream_response {
112	struct hpi_response_header h;
113	struct hpi_stream_res d;
114};
115
116struct adapter_info {
117	u16 type;
118	u16 num_instreams;
119	u16 num_outstreams;
120};
121
122struct 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 */
132static struct hpi_adapter_response rESP_HPI_ADAPTER_OPEN[HPI_MAX_ADAPTERS];
133
134static struct hpi_stream_response
135	rESP_HPI_OSTREAM_OPEN[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
136
137static struct hpi_stream_response
138	rESP_HPI_ISTREAM_OPEN[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
139
140static struct hpi_mixer_response rESP_HPI_MIXER_OPEN[HPI_MAX_ADAPTERS];
141
142static struct adapter_info aDAPTER_INFO[HPI_MAX_ADAPTERS];
143
144/* use these to keep track of opens from user mode apps/DLLs */
145static struct asi_open_state
146	outstream_user_open[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
147
148static struct asi_open_state
149	instream_user_open[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
150
151static 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
211static 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
240static 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
255static 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
277static 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 */
302void 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
357static 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
364static 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
370static 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
376static 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
381static 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
431static 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
478static 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
528static 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
576static 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
642static 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
692static 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
730static 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