xref: /openbmc/linux/sound/pci/asihpi/hpimsgx.c (revision 5bc91f5b3c732bdb3b9e7cc8bd27969d25015bcd)
1719f82d3SEliot Blennerhassett /******************************************************************************
2719f82d3SEliot Blennerhassett 
3719f82d3SEliot Blennerhassett     AudioScience HPI driver
4*5bc91f5bSEliot Blennerhassett     Copyright (C) 1997-2014  AudioScience Inc. <support@audioscience.com>
5719f82d3SEliot Blennerhassett 
6719f82d3SEliot Blennerhassett     This program is free software; you can redistribute it and/or modify
7719f82d3SEliot Blennerhassett     it under the terms of version 2 of the GNU General Public License as
8719f82d3SEliot Blennerhassett     published by the Free Software Foundation;
9719f82d3SEliot Blennerhassett 
10719f82d3SEliot Blennerhassett     This program is distributed in the hope that it will be useful,
11719f82d3SEliot Blennerhassett     but WITHOUT ANY WARRANTY; without even the implied warranty of
12719f82d3SEliot Blennerhassett     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13719f82d3SEliot Blennerhassett     GNU General Public License for more details.
14719f82d3SEliot Blennerhassett 
15719f82d3SEliot Blennerhassett     You should have received a copy of the GNU General Public License
16719f82d3SEliot Blennerhassett     along with this program; if not, write to the Free Software
17719f82d3SEliot Blennerhassett     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18719f82d3SEliot Blennerhassett 
19938c565aSEliot Blennerhassett Extended Message Function With Response Caching
20719f82d3SEliot Blennerhassett 
21719f82d3SEliot Blennerhassett (C) Copyright AudioScience Inc. 2002
22719f82d3SEliot Blennerhassett *****************************************************************************/
23719f82d3SEliot Blennerhassett #define SOURCEFILE_NAME "hpimsgx.c"
24719f82d3SEliot Blennerhassett #include "hpi_internal.h"
25f6baaec2SEliot Blennerhassett #include "hpi_version.h"
26719f82d3SEliot Blennerhassett #include "hpimsginit.h"
273285ea10SEliot Blennerhassett #include "hpicmn.h"
28719f82d3SEliot Blennerhassett #include "hpimsgx.h"
29719f82d3SEliot Blennerhassett #include "hpidebug.h"
30719f82d3SEliot Blennerhassett 
31719f82d3SEliot Blennerhassett static struct pci_device_id asihpi_pci_tbl[] = {
32719f82d3SEliot Blennerhassett #include "hpipcida.h"
33719f82d3SEliot Blennerhassett };
34719f82d3SEliot Blennerhassett 
35719f82d3SEliot Blennerhassett static struct hpios_spinlock msgx_lock;
36719f82d3SEliot Blennerhassett 
37719f82d3SEliot Blennerhassett static hpi_handler_func *hpi_entry_points[HPI_MAX_ADAPTERS];
38*5bc91f5bSEliot Blennerhassett static int logging_enabled = 1;
39719f82d3SEliot Blennerhassett 
40719f82d3SEliot Blennerhassett static hpi_handler_func *hpi_lookup_entry_point_function(const struct hpi_pci
41719f82d3SEliot Blennerhassett 	*pci_info)
42719f82d3SEliot Blennerhassett {
43719f82d3SEliot Blennerhassett 
44719f82d3SEliot Blennerhassett 	int i;
45719f82d3SEliot Blennerhassett 
46719f82d3SEliot Blennerhassett 	for (i = 0; asihpi_pci_tbl[i].vendor != 0; i++) {
47719f82d3SEliot Blennerhassett 		if (asihpi_pci_tbl[i].vendor != PCI_ANY_ID
483285ea10SEliot Blennerhassett 			&& asihpi_pci_tbl[i].vendor !=
493285ea10SEliot Blennerhassett 			pci_info->pci_dev->vendor)
50719f82d3SEliot Blennerhassett 			continue;
51719f82d3SEliot Blennerhassett 		if (asihpi_pci_tbl[i].device != PCI_ANY_ID
523285ea10SEliot Blennerhassett 			&& asihpi_pci_tbl[i].device !=
533285ea10SEliot Blennerhassett 			pci_info->pci_dev->device)
54719f82d3SEliot Blennerhassett 			continue;
55719f82d3SEliot Blennerhassett 		if (asihpi_pci_tbl[i].subvendor != PCI_ANY_ID
56719f82d3SEliot Blennerhassett 			&& asihpi_pci_tbl[i].subvendor !=
573285ea10SEliot Blennerhassett 			pci_info->pci_dev->subsystem_vendor)
58719f82d3SEliot Blennerhassett 			continue;
59719f82d3SEliot Blennerhassett 		if (asihpi_pci_tbl[i].subdevice != PCI_ANY_ID
60719f82d3SEliot Blennerhassett 			&& asihpi_pci_tbl[i].subdevice !=
613285ea10SEliot Blennerhassett 			pci_info->pci_dev->subsystem_device)
62719f82d3SEliot Blennerhassett 			continue;
63719f82d3SEliot Blennerhassett 
643285ea10SEliot Blennerhassett 		/* HPI_DEBUG_LOG(DEBUG, " %x,%lx\n", i,
653285ea10SEliot Blennerhassett 		   asihpi_pci_tbl[i].driver_data); */
66719f82d3SEliot Blennerhassett 		return (hpi_handler_func *) asihpi_pci_tbl[i].driver_data;
67719f82d3SEliot Blennerhassett 	}
68719f82d3SEliot Blennerhassett 
69719f82d3SEliot Blennerhassett 	return NULL;
70719f82d3SEliot Blennerhassett }
71719f82d3SEliot Blennerhassett 
72719f82d3SEliot Blennerhassett static inline void hw_entry_point(struct hpi_message *phm,
73719f82d3SEliot Blennerhassett 	struct hpi_response *phr)
74719f82d3SEliot Blennerhassett {
753285ea10SEliot Blennerhassett 	if ((phm->adapter_index < HPI_MAX_ADAPTERS)
763285ea10SEliot Blennerhassett 		&& hpi_entry_points[phm->adapter_index])
773285ea10SEliot Blennerhassett 		hpi_entry_points[phm->adapter_index] (phm, phr);
783285ea10SEliot Blennerhassett 	else
79719f82d3SEliot Blennerhassett 		hpi_init_response(phr, phm->object, phm->function,
80719f82d3SEliot Blennerhassett 			HPI_ERROR_PROCESSING_MESSAGE);
81719f82d3SEliot Blennerhassett }
82719f82d3SEliot Blennerhassett 
83719f82d3SEliot Blennerhassett static void adapter_open(struct hpi_message *phm, struct hpi_response *phr);
84719f82d3SEliot Blennerhassett static void adapter_close(struct hpi_message *phm, struct hpi_response *phr);
85719f82d3SEliot Blennerhassett 
86719f82d3SEliot Blennerhassett static void mixer_open(struct hpi_message *phm, struct hpi_response *phr);
87719f82d3SEliot Blennerhassett static void mixer_close(struct hpi_message *phm, struct hpi_response *phr);
88719f82d3SEliot Blennerhassett 
89719f82d3SEliot Blennerhassett static void outstream_open(struct hpi_message *phm, struct hpi_response *phr,
90719f82d3SEliot Blennerhassett 	void *h_owner);
91719f82d3SEliot Blennerhassett static void outstream_close(struct hpi_message *phm, struct hpi_response *phr,
92719f82d3SEliot Blennerhassett 	void *h_owner);
93719f82d3SEliot Blennerhassett static void instream_open(struct hpi_message *phm, struct hpi_response *phr,
94719f82d3SEliot Blennerhassett 	void *h_owner);
95719f82d3SEliot Blennerhassett static void instream_close(struct hpi_message *phm, struct hpi_response *phr,
96719f82d3SEliot Blennerhassett 	void *h_owner);
97719f82d3SEliot Blennerhassett 
98719f82d3SEliot Blennerhassett static void HPIMSGX__reset(u16 adapter_index);
993285ea10SEliot Blennerhassett 
100719f82d3SEliot Blennerhassett static u16 HPIMSGX__init(struct hpi_message *phm, struct hpi_response *phr);
101719f82d3SEliot Blennerhassett static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner);
102719f82d3SEliot Blennerhassett 
103719f82d3SEliot Blennerhassett #ifndef DISABLE_PRAGMA_PACK1
104719f82d3SEliot Blennerhassett #pragma pack(push, 1)
105719f82d3SEliot Blennerhassett #endif
106719f82d3SEliot Blennerhassett 
107719f82d3SEliot Blennerhassett struct hpi_subsys_response {
108719f82d3SEliot Blennerhassett 	struct hpi_response_header h;
109719f82d3SEliot Blennerhassett 	struct hpi_subsys_res s;
110719f82d3SEliot Blennerhassett };
111719f82d3SEliot Blennerhassett 
112719f82d3SEliot Blennerhassett struct hpi_adapter_response {
113719f82d3SEliot Blennerhassett 	struct hpi_response_header h;
114719f82d3SEliot Blennerhassett 	struct hpi_adapter_res a;
115719f82d3SEliot Blennerhassett };
116719f82d3SEliot Blennerhassett 
117719f82d3SEliot Blennerhassett struct hpi_mixer_response {
118719f82d3SEliot Blennerhassett 	struct hpi_response_header h;
119719f82d3SEliot Blennerhassett 	struct hpi_mixer_res m;
120719f82d3SEliot Blennerhassett };
121719f82d3SEliot Blennerhassett 
122719f82d3SEliot Blennerhassett struct hpi_stream_response {
123719f82d3SEliot Blennerhassett 	struct hpi_response_header h;
124719f82d3SEliot Blennerhassett 	struct hpi_stream_res d;
125719f82d3SEliot Blennerhassett };
126719f82d3SEliot Blennerhassett 
127719f82d3SEliot Blennerhassett struct adapter_info {
128719f82d3SEliot Blennerhassett 	u16 type;
129719f82d3SEliot Blennerhassett 	u16 num_instreams;
130719f82d3SEliot Blennerhassett 	u16 num_outstreams;
131719f82d3SEliot Blennerhassett };
132719f82d3SEliot Blennerhassett 
133719f82d3SEliot Blennerhassett struct asi_open_state {
134719f82d3SEliot Blennerhassett 	int open_flag;
135719f82d3SEliot Blennerhassett 	void *h_owner;
136719f82d3SEliot Blennerhassett };
137719f82d3SEliot Blennerhassett 
138719f82d3SEliot Blennerhassett #ifndef DISABLE_PRAGMA_PACK1
139719f82d3SEliot Blennerhassett #pragma pack(pop)
140719f82d3SEliot Blennerhassett #endif
141719f82d3SEliot Blennerhassett 
142719f82d3SEliot Blennerhassett /* Globals */
143719f82d3SEliot Blennerhassett static struct hpi_adapter_response rESP_HPI_ADAPTER_OPEN[HPI_MAX_ADAPTERS];
144719f82d3SEliot Blennerhassett 
145719f82d3SEliot Blennerhassett static struct hpi_stream_response
146719f82d3SEliot Blennerhassett 	rESP_HPI_OSTREAM_OPEN[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
147719f82d3SEliot Blennerhassett 
148719f82d3SEliot Blennerhassett static struct hpi_stream_response
149719f82d3SEliot Blennerhassett 	rESP_HPI_ISTREAM_OPEN[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
150719f82d3SEliot Blennerhassett 
151719f82d3SEliot Blennerhassett static struct hpi_mixer_response rESP_HPI_MIXER_OPEN[HPI_MAX_ADAPTERS];
152719f82d3SEliot Blennerhassett 
153719f82d3SEliot Blennerhassett static struct adapter_info aDAPTER_INFO[HPI_MAX_ADAPTERS];
154719f82d3SEliot Blennerhassett 
155719f82d3SEliot Blennerhassett /* use these to keep track of opens from user mode apps/DLLs */
156719f82d3SEliot Blennerhassett static struct asi_open_state
157719f82d3SEliot Blennerhassett 	outstream_user_open[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
158719f82d3SEliot Blennerhassett 
159719f82d3SEliot Blennerhassett static struct asi_open_state
160719f82d3SEliot Blennerhassett 	instream_user_open[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
161719f82d3SEliot Blennerhassett 
162719f82d3SEliot Blennerhassett static void subsys_message(struct hpi_message *phm, struct hpi_response *phr,
163719f82d3SEliot Blennerhassett 	void *h_owner)
164719f82d3SEliot Blennerhassett {
1653285ea10SEliot Blennerhassett 	if (phm->adapter_index != HPI_ADAPTER_INDEX_INVALID)
1663285ea10SEliot Blennerhassett 		HPI_DEBUG_LOG(WARNING,
1673285ea10SEliot Blennerhassett 			"suspicious adapter index %d in subsys message 0x%x.\n",
1683285ea10SEliot Blennerhassett 			phm->adapter_index, phm->function);
1693285ea10SEliot Blennerhassett 
170719f82d3SEliot Blennerhassett 	switch (phm->function) {
171719f82d3SEliot Blennerhassett 	case HPI_SUBSYS_GET_VERSION:
172719f82d3SEliot Blennerhassett 		hpi_init_response(phr, HPI_OBJ_SUBSYSTEM,
173719f82d3SEliot Blennerhassett 			HPI_SUBSYS_GET_VERSION, 0);
174719f82d3SEliot Blennerhassett 		phr->u.s.version = HPI_VER >> 8;	/* return major.minor */
175719f82d3SEliot Blennerhassett 		phr->u.s.data = HPI_VER;	/* return major.minor.release */
176719f82d3SEliot Blennerhassett 		break;
177719f82d3SEliot Blennerhassett 	case HPI_SUBSYS_OPEN:
178719f82d3SEliot Blennerhassett 		/*do not propagate the message down the chain */
179719f82d3SEliot Blennerhassett 		hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_OPEN, 0);
180719f82d3SEliot Blennerhassett 		break;
181719f82d3SEliot Blennerhassett 	case HPI_SUBSYS_CLOSE:
182719f82d3SEliot Blennerhassett 		/*do not propagate the message down the chain */
183719f82d3SEliot Blennerhassett 		hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_CLOSE,
184719f82d3SEliot Blennerhassett 			0);
185719f82d3SEliot Blennerhassett 		HPIMSGX__cleanup(HPIMSGX_ALLADAPTERS, h_owner);
186719f82d3SEliot Blennerhassett 		break;
187719f82d3SEliot Blennerhassett 	case HPI_SUBSYS_DRIVER_LOAD:
188719f82d3SEliot Blennerhassett 		/* Initialize this module's internal state */
189719f82d3SEliot Blennerhassett 		hpios_msgxlock_init(&msgx_lock);
190719f82d3SEliot Blennerhassett 		memset(&hpi_entry_points, 0, sizeof(hpi_entry_points));
191719f82d3SEliot Blennerhassett 		/* Init subsys_findadapters response to no-adapters */
192719f82d3SEliot Blennerhassett 		HPIMSGX__reset(HPIMSGX_ALLADAPTERS);
193719f82d3SEliot Blennerhassett 		hpi_init_response(phr, HPI_OBJ_SUBSYSTEM,
194719f82d3SEliot Blennerhassett 			HPI_SUBSYS_DRIVER_LOAD, 0);
195719f82d3SEliot Blennerhassett 		/* individual HPIs dont implement driver load */
196719f82d3SEliot Blennerhassett 		HPI_COMMON(phm, phr);
197719f82d3SEliot Blennerhassett 		break;
198719f82d3SEliot Blennerhassett 	case HPI_SUBSYS_DRIVER_UNLOAD:
199719f82d3SEliot Blennerhassett 		HPI_COMMON(phm, phr);
200719f82d3SEliot Blennerhassett 		HPIMSGX__cleanup(HPIMSGX_ALLADAPTERS, h_owner);
201719f82d3SEliot Blennerhassett 		hpi_init_response(phr, HPI_OBJ_SUBSYSTEM,
202719f82d3SEliot Blennerhassett 			HPI_SUBSYS_DRIVER_UNLOAD, 0);
203719f82d3SEliot Blennerhassett 		return;
204719f82d3SEliot Blennerhassett 
2053285ea10SEliot Blennerhassett 	case HPI_SUBSYS_GET_NUM_ADAPTERS:
2063285ea10SEliot Blennerhassett 	case HPI_SUBSYS_GET_ADAPTER:
207719f82d3SEliot Blennerhassett 		HPI_COMMON(phm, phr);
208719f82d3SEliot Blennerhassett 		break;
209719f82d3SEliot Blennerhassett 
210719f82d3SEliot Blennerhassett 	case HPI_SUBSYS_CREATE_ADAPTER:
211719f82d3SEliot Blennerhassett 		HPIMSGX__init(phm, phr);
212719f82d3SEliot Blennerhassett 		break;
2133285ea10SEliot Blennerhassett 
214719f82d3SEliot Blennerhassett 	default:
2151d595d2aSEliot Blennerhassett 		/* Must explicitly handle every subsys message in this switch */
2163285ea10SEliot Blennerhassett 		hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function,
2173285ea10SEliot Blennerhassett 			HPI_ERROR_INVALID_FUNC);
218719f82d3SEliot Blennerhassett 		break;
219719f82d3SEliot Blennerhassett 	}
220719f82d3SEliot Blennerhassett }
221719f82d3SEliot Blennerhassett 
222719f82d3SEliot Blennerhassett static void adapter_message(struct hpi_message *phm, struct hpi_response *phr,
223719f82d3SEliot Blennerhassett 	void *h_owner)
224719f82d3SEliot Blennerhassett {
225719f82d3SEliot Blennerhassett 	switch (phm->function) {
226719f82d3SEliot Blennerhassett 	case HPI_ADAPTER_OPEN:
227719f82d3SEliot Blennerhassett 		adapter_open(phm, phr);
228719f82d3SEliot Blennerhassett 		break;
229719f82d3SEliot Blennerhassett 	case HPI_ADAPTER_CLOSE:
230719f82d3SEliot Blennerhassett 		adapter_close(phm, phr);
231719f82d3SEliot Blennerhassett 		break;
2326d0b898eSEliot Blennerhassett 	case HPI_ADAPTER_DELETE:
2336d0b898eSEliot Blennerhassett 		HPIMSGX__cleanup(phm->adapter_index, h_owner);
2346d0b898eSEliot Blennerhassett 		{
2356d0b898eSEliot Blennerhassett 			struct hpi_message hm;
2366d0b898eSEliot Blennerhassett 			struct hpi_response hr;
2376d0b898eSEliot Blennerhassett 			hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
2386d0b898eSEliot Blennerhassett 				HPI_ADAPTER_CLOSE);
2396d0b898eSEliot Blennerhassett 			hm.adapter_index = phm->adapter_index;
2406d0b898eSEliot Blennerhassett 			hw_entry_point(&hm, &hr);
2416d0b898eSEliot Blennerhassett 		}
2426d0b898eSEliot Blennerhassett 		hw_entry_point(phm, phr);
2436d0b898eSEliot Blennerhassett 		break;
2446d0b898eSEliot Blennerhassett 
245719f82d3SEliot Blennerhassett 	default:
246719f82d3SEliot Blennerhassett 		hw_entry_point(phm, phr);
247719f82d3SEliot Blennerhassett 		break;
248719f82d3SEliot Blennerhassett 	}
249719f82d3SEliot Blennerhassett }
250719f82d3SEliot Blennerhassett 
251719f82d3SEliot Blennerhassett static void mixer_message(struct hpi_message *phm, struct hpi_response *phr)
252719f82d3SEliot Blennerhassett {
253719f82d3SEliot Blennerhassett 	switch (phm->function) {
254719f82d3SEliot Blennerhassett 	case HPI_MIXER_OPEN:
255719f82d3SEliot Blennerhassett 		mixer_open(phm, phr);
256719f82d3SEliot Blennerhassett 		break;
257719f82d3SEliot Blennerhassett 	case HPI_MIXER_CLOSE:
258719f82d3SEliot Blennerhassett 		mixer_close(phm, phr);
259719f82d3SEliot Blennerhassett 		break;
260719f82d3SEliot Blennerhassett 	default:
261719f82d3SEliot Blennerhassett 		hw_entry_point(phm, phr);
262719f82d3SEliot Blennerhassett 		break;
263719f82d3SEliot Blennerhassett 	}
264719f82d3SEliot Blennerhassett }
265719f82d3SEliot Blennerhassett 
266719f82d3SEliot Blennerhassett static void outstream_message(struct hpi_message *phm,
267719f82d3SEliot Blennerhassett 	struct hpi_response *phr, void *h_owner)
268719f82d3SEliot Blennerhassett {
269719f82d3SEliot Blennerhassett 	if (phm->obj_index >= aDAPTER_INFO[phm->adapter_index].num_outstreams) {
270719f82d3SEliot Blennerhassett 		hpi_init_response(phr, HPI_OBJ_OSTREAM, phm->function,
271719f82d3SEliot Blennerhassett 			HPI_ERROR_INVALID_OBJ_INDEX);
272719f82d3SEliot Blennerhassett 		return;
273719f82d3SEliot Blennerhassett 	}
274719f82d3SEliot Blennerhassett 
275719f82d3SEliot Blennerhassett 	switch (phm->function) {
276719f82d3SEliot Blennerhassett 	case HPI_OSTREAM_OPEN:
277719f82d3SEliot Blennerhassett 		outstream_open(phm, phr, h_owner);
278719f82d3SEliot Blennerhassett 		break;
279719f82d3SEliot Blennerhassett 	case HPI_OSTREAM_CLOSE:
280719f82d3SEliot Blennerhassett 		outstream_close(phm, phr, h_owner);
281719f82d3SEliot Blennerhassett 		break;
282719f82d3SEliot Blennerhassett 	default:
283719f82d3SEliot Blennerhassett 		hw_entry_point(phm, phr);
284719f82d3SEliot Blennerhassett 		break;
285719f82d3SEliot Blennerhassett 	}
286719f82d3SEliot Blennerhassett }
287719f82d3SEliot Blennerhassett 
288719f82d3SEliot Blennerhassett static void instream_message(struct hpi_message *phm,
289719f82d3SEliot Blennerhassett 	struct hpi_response *phr, void *h_owner)
290719f82d3SEliot Blennerhassett {
291719f82d3SEliot Blennerhassett 	if (phm->obj_index >= aDAPTER_INFO[phm->adapter_index].num_instreams) {
292719f82d3SEliot Blennerhassett 		hpi_init_response(phr, HPI_OBJ_ISTREAM, phm->function,
293719f82d3SEliot Blennerhassett 			HPI_ERROR_INVALID_OBJ_INDEX);
294719f82d3SEliot Blennerhassett 		return;
295719f82d3SEliot Blennerhassett 	}
296719f82d3SEliot Blennerhassett 
297719f82d3SEliot Blennerhassett 	switch (phm->function) {
298719f82d3SEliot Blennerhassett 	case HPI_ISTREAM_OPEN:
299719f82d3SEliot Blennerhassett 		instream_open(phm, phr, h_owner);
300719f82d3SEliot Blennerhassett 		break;
301719f82d3SEliot Blennerhassett 	case HPI_ISTREAM_CLOSE:
302719f82d3SEliot Blennerhassett 		instream_close(phm, phr, h_owner);
303719f82d3SEliot Blennerhassett 		break;
304719f82d3SEliot Blennerhassett 	default:
305719f82d3SEliot Blennerhassett 		hw_entry_point(phm, phr);
306719f82d3SEliot Blennerhassett 		break;
307719f82d3SEliot Blennerhassett 	}
308719f82d3SEliot Blennerhassett }
309719f82d3SEliot Blennerhassett 
310719f82d3SEliot Blennerhassett /* NOTE: HPI_Message() must be defined in the driver as a wrapper for
311719f82d3SEliot Blennerhassett  * HPI_MessageEx so that functions in hpifunc.c compile.
312719f82d3SEliot Blennerhassett  */
313719f82d3SEliot Blennerhassett void hpi_send_recv_ex(struct hpi_message *phm, struct hpi_response *phr,
314719f82d3SEliot Blennerhassett 	void *h_owner)
315719f82d3SEliot Blennerhassett {
316*5bc91f5bSEliot Blennerhassett 
317*5bc91f5bSEliot Blennerhassett 	if (logging_enabled)
318719f82d3SEliot Blennerhassett 		HPI_DEBUG_MESSAGE(DEBUG, phm);
319719f82d3SEliot Blennerhassett 
32082b5774fSEliot Blennerhassett 	if (phm->type != HPI_TYPE_REQUEST) {
321719f82d3SEliot Blennerhassett 		hpi_init_response(phr, phm->object, phm->function,
322719f82d3SEliot Blennerhassett 			HPI_ERROR_INVALID_TYPE);
323719f82d3SEliot Blennerhassett 		return;
324719f82d3SEliot Blennerhassett 	}
325719f82d3SEliot Blennerhassett 
326719f82d3SEliot Blennerhassett 	if (phm->adapter_index >= HPI_MAX_ADAPTERS
327719f82d3SEliot Blennerhassett 		&& phm->adapter_index != HPIMSGX_ALLADAPTERS) {
328719f82d3SEliot Blennerhassett 		hpi_init_response(phr, phm->object, phm->function,
329719f82d3SEliot Blennerhassett 			HPI_ERROR_BAD_ADAPTER_NUMBER);
330719f82d3SEliot Blennerhassett 		return;
331719f82d3SEliot Blennerhassett 	}
332719f82d3SEliot Blennerhassett 
333719f82d3SEliot Blennerhassett 	switch (phm->object) {
334719f82d3SEliot Blennerhassett 	case HPI_OBJ_SUBSYSTEM:
335719f82d3SEliot Blennerhassett 		subsys_message(phm, phr, h_owner);
336719f82d3SEliot Blennerhassett 		break;
337719f82d3SEliot Blennerhassett 
338719f82d3SEliot Blennerhassett 	case HPI_OBJ_ADAPTER:
339719f82d3SEliot Blennerhassett 		adapter_message(phm, phr, h_owner);
340719f82d3SEliot Blennerhassett 		break;
341719f82d3SEliot Blennerhassett 
342719f82d3SEliot Blennerhassett 	case HPI_OBJ_MIXER:
343719f82d3SEliot Blennerhassett 		mixer_message(phm, phr);
344719f82d3SEliot Blennerhassett 		break;
345719f82d3SEliot Blennerhassett 
346719f82d3SEliot Blennerhassett 	case HPI_OBJ_OSTREAM:
347719f82d3SEliot Blennerhassett 		outstream_message(phm, phr, h_owner);
348719f82d3SEliot Blennerhassett 		break;
349719f82d3SEliot Blennerhassett 
350719f82d3SEliot Blennerhassett 	case HPI_OBJ_ISTREAM:
351719f82d3SEliot Blennerhassett 		instream_message(phm, phr, h_owner);
352719f82d3SEliot Blennerhassett 		break;
353719f82d3SEliot Blennerhassett 
354719f82d3SEliot Blennerhassett 	default:
355719f82d3SEliot Blennerhassett 		hw_entry_point(phm, phr);
356719f82d3SEliot Blennerhassett 		break;
357719f82d3SEliot Blennerhassett 	}
358*5bc91f5bSEliot Blennerhassett 
359*5bc91f5bSEliot Blennerhassett 	if (logging_enabled)
360719f82d3SEliot Blennerhassett 		HPI_DEBUG_RESPONSE(phr);
361719f82d3SEliot Blennerhassett 
362*5bc91f5bSEliot Blennerhassett 	if (phr->error >= HPI_ERROR_DSP_COMMUNICATION) {
363*5bc91f5bSEliot Blennerhassett 		hpi_debug_level_set(HPI_DEBUG_LEVEL_ERROR);
364*5bc91f5bSEliot Blennerhassett 		logging_enabled = 0;
365*5bc91f5bSEliot Blennerhassett 	}
366719f82d3SEliot Blennerhassett }
367719f82d3SEliot Blennerhassett 
368719f82d3SEliot Blennerhassett static void adapter_open(struct hpi_message *phm, struct hpi_response *phr)
369719f82d3SEliot Blennerhassett {
370719f82d3SEliot Blennerhassett 	HPI_DEBUG_LOG(VERBOSE, "adapter_open\n");
371719f82d3SEliot Blennerhassett 	memcpy(phr, &rESP_HPI_ADAPTER_OPEN[phm->adapter_index],
372719f82d3SEliot Blennerhassett 		sizeof(rESP_HPI_ADAPTER_OPEN[0]));
373719f82d3SEliot Blennerhassett }
374719f82d3SEliot Blennerhassett 
375719f82d3SEliot Blennerhassett static void adapter_close(struct hpi_message *phm, struct hpi_response *phr)
376719f82d3SEliot Blennerhassett {
377719f82d3SEliot Blennerhassett 	HPI_DEBUG_LOG(VERBOSE, "adapter_close\n");
378719f82d3SEliot Blennerhassett 	hpi_init_response(phr, HPI_OBJ_ADAPTER, HPI_ADAPTER_CLOSE, 0);
379719f82d3SEliot Blennerhassett }
380719f82d3SEliot Blennerhassett 
381719f82d3SEliot Blennerhassett static void mixer_open(struct hpi_message *phm, struct hpi_response *phr)
382719f82d3SEliot Blennerhassett {
383719f82d3SEliot Blennerhassett 	memcpy(phr, &rESP_HPI_MIXER_OPEN[phm->adapter_index],
384719f82d3SEliot Blennerhassett 		sizeof(rESP_HPI_MIXER_OPEN[0]));
385719f82d3SEliot Blennerhassett }
386719f82d3SEliot Blennerhassett 
387719f82d3SEliot Blennerhassett static void mixer_close(struct hpi_message *phm, struct hpi_response *phr)
388719f82d3SEliot Blennerhassett {
389719f82d3SEliot Blennerhassett 	hpi_init_response(phr, HPI_OBJ_MIXER, HPI_MIXER_CLOSE, 0);
390719f82d3SEliot Blennerhassett }
391719f82d3SEliot Blennerhassett 
392719f82d3SEliot Blennerhassett static void instream_open(struct hpi_message *phm, struct hpi_response *phr,
393719f82d3SEliot Blennerhassett 	void *h_owner)
394719f82d3SEliot Blennerhassett {
395719f82d3SEliot Blennerhassett 
396719f82d3SEliot Blennerhassett 	struct hpi_message hm;
397719f82d3SEliot Blennerhassett 	struct hpi_response hr;
398719f82d3SEliot Blennerhassett 
399719f82d3SEliot Blennerhassett 	hpi_init_response(phr, HPI_OBJ_ISTREAM, HPI_ISTREAM_OPEN, 0);
400719f82d3SEliot Blennerhassett 
401719f82d3SEliot Blennerhassett 	hpios_msgxlock_lock(&msgx_lock);
402719f82d3SEliot Blennerhassett 
403719f82d3SEliot Blennerhassett 	if (instream_user_open[phm->adapter_index][phm->obj_index].open_flag)
404719f82d3SEliot Blennerhassett 		phr->error = HPI_ERROR_OBJ_ALREADY_OPEN;
405719f82d3SEliot Blennerhassett 	else if (rESP_HPI_ISTREAM_OPEN[phm->adapter_index]
406719f82d3SEliot Blennerhassett 		[phm->obj_index].h.error)
407719f82d3SEliot Blennerhassett 		memcpy(phr,
408719f82d3SEliot Blennerhassett 			&rESP_HPI_ISTREAM_OPEN[phm->adapter_index][phm->
409719f82d3SEliot Blennerhassett 				obj_index],
410719f82d3SEliot Blennerhassett 			sizeof(rESP_HPI_ISTREAM_OPEN[0][0]));
411719f82d3SEliot Blennerhassett 	else {
412719f82d3SEliot Blennerhassett 		instream_user_open[phm->adapter_index][phm->
413719f82d3SEliot Blennerhassett 			obj_index].open_flag = 1;
4143285ea10SEliot Blennerhassett 		hpios_msgxlock_unlock(&msgx_lock);
415719f82d3SEliot Blennerhassett 
416719f82d3SEliot Blennerhassett 		/* issue a reset */
417719f82d3SEliot Blennerhassett 		hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
418719f82d3SEliot Blennerhassett 			HPI_ISTREAM_RESET);
419719f82d3SEliot Blennerhassett 		hm.adapter_index = phm->adapter_index;
420719f82d3SEliot Blennerhassett 		hm.obj_index = phm->obj_index;
421719f82d3SEliot Blennerhassett 		hw_entry_point(&hm, &hr);
422719f82d3SEliot Blennerhassett 
423719f82d3SEliot Blennerhassett 		hpios_msgxlock_lock(&msgx_lock);
424719f82d3SEliot Blennerhassett 		if (hr.error) {
425719f82d3SEliot Blennerhassett 			instream_user_open[phm->adapter_index][phm->
426719f82d3SEliot Blennerhassett 				obj_index].open_flag = 0;
427719f82d3SEliot Blennerhassett 			phr->error = hr.error;
428719f82d3SEliot Blennerhassett 		} else {
429719f82d3SEliot Blennerhassett 			instream_user_open[phm->adapter_index][phm->
430719f82d3SEliot Blennerhassett 				obj_index].open_flag = 1;
431719f82d3SEliot Blennerhassett 			instream_user_open[phm->adapter_index][phm->
432719f82d3SEliot Blennerhassett 				obj_index].h_owner = h_owner;
433719f82d3SEliot Blennerhassett 			memcpy(phr,
434719f82d3SEliot Blennerhassett 				&rESP_HPI_ISTREAM_OPEN[phm->adapter_index]
435719f82d3SEliot Blennerhassett 				[phm->obj_index],
436719f82d3SEliot Blennerhassett 				sizeof(rESP_HPI_ISTREAM_OPEN[0][0]));
437719f82d3SEliot Blennerhassett 		}
438719f82d3SEliot Blennerhassett 	}
4393285ea10SEliot Blennerhassett 	hpios_msgxlock_unlock(&msgx_lock);
440719f82d3SEliot Blennerhassett }
441719f82d3SEliot Blennerhassett 
442719f82d3SEliot Blennerhassett static void instream_close(struct hpi_message *phm, struct hpi_response *phr,
443719f82d3SEliot Blennerhassett 	void *h_owner)
444719f82d3SEliot Blennerhassett {
445719f82d3SEliot Blennerhassett 
446719f82d3SEliot Blennerhassett 	struct hpi_message hm;
447719f82d3SEliot Blennerhassett 	struct hpi_response hr;
448719f82d3SEliot Blennerhassett 
449719f82d3SEliot Blennerhassett 	hpi_init_response(phr, HPI_OBJ_ISTREAM, HPI_ISTREAM_CLOSE, 0);
450719f82d3SEliot Blennerhassett 
451719f82d3SEliot Blennerhassett 	hpios_msgxlock_lock(&msgx_lock);
452719f82d3SEliot Blennerhassett 	if (h_owner ==
453719f82d3SEliot Blennerhassett 		instream_user_open[phm->adapter_index][phm->
454719f82d3SEliot Blennerhassett 			obj_index].h_owner) {
455719f82d3SEliot Blennerhassett 		/* HPI_DEBUG_LOG(INFO,"closing adapter %d "
456719f82d3SEliot Blennerhassett 		   "instream %d owned by %p\n",
457719f82d3SEliot Blennerhassett 		   phm->wAdapterIndex, phm->wObjIndex, hOwner); */
458719f82d3SEliot Blennerhassett 		instream_user_open[phm->adapter_index][phm->
459719f82d3SEliot Blennerhassett 			obj_index].h_owner = NULL;
4603285ea10SEliot Blennerhassett 		hpios_msgxlock_unlock(&msgx_lock);
461719f82d3SEliot Blennerhassett 		/* issue a reset */
462719f82d3SEliot Blennerhassett 		hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
463719f82d3SEliot Blennerhassett 			HPI_ISTREAM_RESET);
464719f82d3SEliot Blennerhassett 		hm.adapter_index = phm->adapter_index;
465719f82d3SEliot Blennerhassett 		hm.obj_index = phm->obj_index;
466719f82d3SEliot Blennerhassett 		hw_entry_point(&hm, &hr);
467719f82d3SEliot Blennerhassett 		hpios_msgxlock_lock(&msgx_lock);
468719f82d3SEliot Blennerhassett 		if (hr.error) {
469719f82d3SEliot Blennerhassett 			instream_user_open[phm->adapter_index][phm->
470719f82d3SEliot Blennerhassett 				obj_index].h_owner = h_owner;
471719f82d3SEliot Blennerhassett 			phr->error = hr.error;
472719f82d3SEliot Blennerhassett 		} else {
473719f82d3SEliot Blennerhassett 			instream_user_open[phm->adapter_index][phm->
474719f82d3SEliot Blennerhassett 				obj_index].open_flag = 0;
475719f82d3SEliot Blennerhassett 			instream_user_open[phm->adapter_index][phm->
476719f82d3SEliot Blennerhassett 				obj_index].h_owner = NULL;
477719f82d3SEliot Blennerhassett 		}
478719f82d3SEliot Blennerhassett 	} else {
479719f82d3SEliot Blennerhassett 		HPI_DEBUG_LOG(WARNING,
480719f82d3SEliot Blennerhassett 			"%p trying to close %d instream %d owned by %p\n",
481719f82d3SEliot Blennerhassett 			h_owner, phm->adapter_index, phm->obj_index,
482719f82d3SEliot Blennerhassett 			instream_user_open[phm->adapter_index][phm->
483719f82d3SEliot Blennerhassett 				obj_index].h_owner);
484719f82d3SEliot Blennerhassett 		phr->error = HPI_ERROR_OBJ_NOT_OPEN;
485719f82d3SEliot Blennerhassett 	}
4863285ea10SEliot Blennerhassett 	hpios_msgxlock_unlock(&msgx_lock);
487719f82d3SEliot Blennerhassett }
488719f82d3SEliot Blennerhassett 
489719f82d3SEliot Blennerhassett static void outstream_open(struct hpi_message *phm, struct hpi_response *phr,
490719f82d3SEliot Blennerhassett 	void *h_owner)
491719f82d3SEliot Blennerhassett {
492719f82d3SEliot Blennerhassett 
493719f82d3SEliot Blennerhassett 	struct hpi_message hm;
494719f82d3SEliot Blennerhassett 	struct hpi_response hr;
495719f82d3SEliot Blennerhassett 
496719f82d3SEliot Blennerhassett 	hpi_init_response(phr, HPI_OBJ_OSTREAM, HPI_OSTREAM_OPEN, 0);
497719f82d3SEliot Blennerhassett 
498719f82d3SEliot Blennerhassett 	hpios_msgxlock_lock(&msgx_lock);
499719f82d3SEliot Blennerhassett 
500719f82d3SEliot Blennerhassett 	if (outstream_user_open[phm->adapter_index][phm->obj_index].open_flag)
501719f82d3SEliot Blennerhassett 		phr->error = HPI_ERROR_OBJ_ALREADY_OPEN;
502719f82d3SEliot Blennerhassett 	else if (rESP_HPI_OSTREAM_OPEN[phm->adapter_index]
503719f82d3SEliot Blennerhassett 		[phm->obj_index].h.error)
504719f82d3SEliot Blennerhassett 		memcpy(phr,
505719f82d3SEliot Blennerhassett 			&rESP_HPI_OSTREAM_OPEN[phm->adapter_index][phm->
506719f82d3SEliot Blennerhassett 				obj_index],
507719f82d3SEliot Blennerhassett 			sizeof(rESP_HPI_OSTREAM_OPEN[0][0]));
508719f82d3SEliot Blennerhassett 	else {
509719f82d3SEliot Blennerhassett 		outstream_user_open[phm->adapter_index][phm->
510719f82d3SEliot Blennerhassett 			obj_index].open_flag = 1;
5113285ea10SEliot Blennerhassett 		hpios_msgxlock_unlock(&msgx_lock);
512719f82d3SEliot Blennerhassett 
513719f82d3SEliot Blennerhassett 		/* issue a reset */
514719f82d3SEliot Blennerhassett 		hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
515719f82d3SEliot Blennerhassett 			HPI_OSTREAM_RESET);
516719f82d3SEliot Blennerhassett 		hm.adapter_index = phm->adapter_index;
517719f82d3SEliot Blennerhassett 		hm.obj_index = phm->obj_index;
518719f82d3SEliot Blennerhassett 		hw_entry_point(&hm, &hr);
519719f82d3SEliot Blennerhassett 
520719f82d3SEliot Blennerhassett 		hpios_msgxlock_lock(&msgx_lock);
521719f82d3SEliot Blennerhassett 		if (hr.error) {
522719f82d3SEliot Blennerhassett 			outstream_user_open[phm->adapter_index][phm->
523719f82d3SEliot Blennerhassett 				obj_index].open_flag = 0;
524719f82d3SEliot Blennerhassett 			phr->error = hr.error;
525719f82d3SEliot Blennerhassett 		} else {
526719f82d3SEliot Blennerhassett 			outstream_user_open[phm->adapter_index][phm->
527719f82d3SEliot Blennerhassett 				obj_index].open_flag = 1;
528719f82d3SEliot Blennerhassett 			outstream_user_open[phm->adapter_index][phm->
529719f82d3SEliot Blennerhassett 				obj_index].h_owner = h_owner;
530719f82d3SEliot Blennerhassett 			memcpy(phr,
531719f82d3SEliot Blennerhassett 				&rESP_HPI_OSTREAM_OPEN[phm->adapter_index]
532719f82d3SEliot Blennerhassett 				[phm->obj_index],
533719f82d3SEliot Blennerhassett 				sizeof(rESP_HPI_OSTREAM_OPEN[0][0]));
534719f82d3SEliot Blennerhassett 		}
535719f82d3SEliot Blennerhassett 	}
5363285ea10SEliot Blennerhassett 	hpios_msgxlock_unlock(&msgx_lock);
537719f82d3SEliot Blennerhassett }
538719f82d3SEliot Blennerhassett 
539719f82d3SEliot Blennerhassett static void outstream_close(struct hpi_message *phm, struct hpi_response *phr,
540719f82d3SEliot Blennerhassett 	void *h_owner)
541719f82d3SEliot Blennerhassett {
542719f82d3SEliot Blennerhassett 
543719f82d3SEliot Blennerhassett 	struct hpi_message hm;
544719f82d3SEliot Blennerhassett 	struct hpi_response hr;
545719f82d3SEliot Blennerhassett 
546719f82d3SEliot Blennerhassett 	hpi_init_response(phr, HPI_OBJ_OSTREAM, HPI_OSTREAM_CLOSE, 0);
547719f82d3SEliot Blennerhassett 
548719f82d3SEliot Blennerhassett 	hpios_msgxlock_lock(&msgx_lock);
549719f82d3SEliot Blennerhassett 
550719f82d3SEliot Blennerhassett 	if (h_owner ==
551719f82d3SEliot Blennerhassett 		outstream_user_open[phm->adapter_index][phm->
552719f82d3SEliot Blennerhassett 			obj_index].h_owner) {
553719f82d3SEliot Blennerhassett 		/* HPI_DEBUG_LOG(INFO,"closing adapter %d "
554719f82d3SEliot Blennerhassett 		   "outstream %d owned by %p\n",
555719f82d3SEliot Blennerhassett 		   phm->wAdapterIndex, phm->wObjIndex, hOwner); */
556719f82d3SEliot Blennerhassett 		outstream_user_open[phm->adapter_index][phm->
557719f82d3SEliot Blennerhassett 			obj_index].h_owner = NULL;
5583285ea10SEliot Blennerhassett 		hpios_msgxlock_unlock(&msgx_lock);
559719f82d3SEliot Blennerhassett 		/* issue a reset */
560719f82d3SEliot Blennerhassett 		hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
561719f82d3SEliot Blennerhassett 			HPI_OSTREAM_RESET);
562719f82d3SEliot Blennerhassett 		hm.adapter_index = phm->adapter_index;
563719f82d3SEliot Blennerhassett 		hm.obj_index = phm->obj_index;
564719f82d3SEliot Blennerhassett 		hw_entry_point(&hm, &hr);
565719f82d3SEliot Blennerhassett 		hpios_msgxlock_lock(&msgx_lock);
566719f82d3SEliot Blennerhassett 		if (hr.error) {
567719f82d3SEliot Blennerhassett 			outstream_user_open[phm->adapter_index][phm->
568719f82d3SEliot Blennerhassett 				obj_index].h_owner = h_owner;
569719f82d3SEliot Blennerhassett 			phr->error = hr.error;
570719f82d3SEliot Blennerhassett 		} else {
571719f82d3SEliot Blennerhassett 			outstream_user_open[phm->adapter_index][phm->
572719f82d3SEliot Blennerhassett 				obj_index].open_flag = 0;
573719f82d3SEliot Blennerhassett 			outstream_user_open[phm->adapter_index][phm->
574719f82d3SEliot Blennerhassett 				obj_index].h_owner = NULL;
575719f82d3SEliot Blennerhassett 		}
576719f82d3SEliot Blennerhassett 	} else {
577719f82d3SEliot Blennerhassett 		HPI_DEBUG_LOG(WARNING,
578719f82d3SEliot Blennerhassett 			"%p trying to close %d outstream %d owned by %p\n",
579719f82d3SEliot Blennerhassett 			h_owner, phm->adapter_index, phm->obj_index,
580719f82d3SEliot Blennerhassett 			outstream_user_open[phm->adapter_index][phm->
581719f82d3SEliot Blennerhassett 				obj_index].h_owner);
582719f82d3SEliot Blennerhassett 		phr->error = HPI_ERROR_OBJ_NOT_OPEN;
583719f82d3SEliot Blennerhassett 	}
5843285ea10SEliot Blennerhassett 	hpios_msgxlock_unlock(&msgx_lock);
585719f82d3SEliot Blennerhassett }
586719f82d3SEliot Blennerhassett 
587719f82d3SEliot Blennerhassett static u16 adapter_prepare(u16 adapter)
588719f82d3SEliot Blennerhassett {
589719f82d3SEliot Blennerhassett 	struct hpi_message hm;
590719f82d3SEliot Blennerhassett 	struct hpi_response hr;
591719f82d3SEliot Blennerhassett 
592719f82d3SEliot Blennerhassett 	/* Open the adapter and streams */
593719f82d3SEliot Blennerhassett 	u16 i;
594719f82d3SEliot Blennerhassett 
595719f82d3SEliot Blennerhassett 	/* call to HPI_ADAPTER_OPEN */
596719f82d3SEliot Blennerhassett 	hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
597719f82d3SEliot Blennerhassett 		HPI_ADAPTER_OPEN);
598719f82d3SEliot Blennerhassett 	hm.adapter_index = adapter;
599719f82d3SEliot Blennerhassett 	hw_entry_point(&hm, &hr);
600719f82d3SEliot Blennerhassett 	memcpy(&rESP_HPI_ADAPTER_OPEN[adapter], &hr,
601719f82d3SEliot Blennerhassett 		sizeof(rESP_HPI_ADAPTER_OPEN[0]));
602719f82d3SEliot Blennerhassett 	if (hr.error)
603719f82d3SEliot Blennerhassett 		return hr.error;
604719f82d3SEliot Blennerhassett 
605719f82d3SEliot Blennerhassett 	/* call to HPI_ADAPTER_GET_INFO */
606719f82d3SEliot Blennerhassett 	hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
607719f82d3SEliot Blennerhassett 		HPI_ADAPTER_GET_INFO);
608719f82d3SEliot Blennerhassett 	hm.adapter_index = adapter;
609719f82d3SEliot Blennerhassett 	hw_entry_point(&hm, &hr);
610719f82d3SEliot Blennerhassett 	if (hr.error)
611719f82d3SEliot Blennerhassett 		return hr.error;
612719f82d3SEliot Blennerhassett 
6133285ea10SEliot Blennerhassett 	aDAPTER_INFO[adapter].num_outstreams = hr.u.ax.info.num_outstreams;
6143285ea10SEliot Blennerhassett 	aDAPTER_INFO[adapter].num_instreams = hr.u.ax.info.num_instreams;
6153285ea10SEliot Blennerhassett 	aDAPTER_INFO[adapter].type = hr.u.ax.info.adapter_type;
616719f82d3SEliot Blennerhassett 
617719f82d3SEliot Blennerhassett 	/* call to HPI_OSTREAM_OPEN */
618719f82d3SEliot Blennerhassett 	for (i = 0; i < aDAPTER_INFO[adapter].num_outstreams; i++) {
619719f82d3SEliot Blennerhassett 		hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
620719f82d3SEliot Blennerhassett 			HPI_OSTREAM_OPEN);
621719f82d3SEliot Blennerhassett 		hm.adapter_index = adapter;
622719f82d3SEliot Blennerhassett 		hm.obj_index = i;
623719f82d3SEliot Blennerhassett 		hw_entry_point(&hm, &hr);
624719f82d3SEliot Blennerhassett 		memcpy(&rESP_HPI_OSTREAM_OPEN[adapter][i], &hr,
625719f82d3SEliot Blennerhassett 			sizeof(rESP_HPI_OSTREAM_OPEN[0][0]));
626719f82d3SEliot Blennerhassett 		outstream_user_open[adapter][i].open_flag = 0;
627719f82d3SEliot Blennerhassett 		outstream_user_open[adapter][i].h_owner = NULL;
628719f82d3SEliot Blennerhassett 	}
629719f82d3SEliot Blennerhassett 
630719f82d3SEliot Blennerhassett 	/* call to HPI_ISTREAM_OPEN */
631719f82d3SEliot Blennerhassett 	for (i = 0; i < aDAPTER_INFO[adapter].num_instreams; i++) {
632719f82d3SEliot Blennerhassett 		hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
633719f82d3SEliot Blennerhassett 			HPI_ISTREAM_OPEN);
634719f82d3SEliot Blennerhassett 		hm.adapter_index = adapter;
635719f82d3SEliot Blennerhassett 		hm.obj_index = i;
636719f82d3SEliot Blennerhassett 		hw_entry_point(&hm, &hr);
637719f82d3SEliot Blennerhassett 		memcpy(&rESP_HPI_ISTREAM_OPEN[adapter][i], &hr,
638719f82d3SEliot Blennerhassett 			sizeof(rESP_HPI_ISTREAM_OPEN[0][0]));
639719f82d3SEliot Blennerhassett 		instream_user_open[adapter][i].open_flag = 0;
640719f82d3SEliot Blennerhassett 		instream_user_open[adapter][i].h_owner = NULL;
641719f82d3SEliot Blennerhassett 	}
642719f82d3SEliot Blennerhassett 
643719f82d3SEliot Blennerhassett 	/* call to HPI_MIXER_OPEN */
644719f82d3SEliot Blennerhassett 	hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER, HPI_MIXER_OPEN);
645719f82d3SEliot Blennerhassett 	hm.adapter_index = adapter;
646719f82d3SEliot Blennerhassett 	hw_entry_point(&hm, &hr);
647719f82d3SEliot Blennerhassett 	memcpy(&rESP_HPI_MIXER_OPEN[adapter], &hr,
648719f82d3SEliot Blennerhassett 		sizeof(rESP_HPI_MIXER_OPEN[0]));
649719f82d3SEliot Blennerhassett 
6503285ea10SEliot Blennerhassett 	return 0;
651719f82d3SEliot Blennerhassett }
652719f82d3SEliot Blennerhassett 
653719f82d3SEliot Blennerhassett static void HPIMSGX__reset(u16 adapter_index)
654719f82d3SEliot Blennerhassett {
655719f82d3SEliot Blennerhassett 	int i;
656719f82d3SEliot Blennerhassett 	u16 adapter;
657719f82d3SEliot Blennerhassett 	struct hpi_response hr;
658719f82d3SEliot Blennerhassett 
659719f82d3SEliot Blennerhassett 	if (adapter_index == HPIMSGX_ALLADAPTERS) {
660719f82d3SEliot Blennerhassett 		for (adapter = 0; adapter < HPI_MAX_ADAPTERS; adapter++) {
661719f82d3SEliot Blennerhassett 
662719f82d3SEliot Blennerhassett 			hpi_init_response(&hr, HPI_OBJ_ADAPTER,
663719f82d3SEliot Blennerhassett 				HPI_ADAPTER_OPEN, HPI_ERROR_BAD_ADAPTER);
664719f82d3SEliot Blennerhassett 			memcpy(&rESP_HPI_ADAPTER_OPEN[adapter], &hr,
665719f82d3SEliot Blennerhassett 				sizeof(rESP_HPI_ADAPTER_OPEN[adapter]));
666719f82d3SEliot Blennerhassett 
667719f82d3SEliot Blennerhassett 			hpi_init_response(&hr, HPI_OBJ_MIXER, HPI_MIXER_OPEN,
668719f82d3SEliot Blennerhassett 				HPI_ERROR_INVALID_OBJ);
669719f82d3SEliot Blennerhassett 			memcpy(&rESP_HPI_MIXER_OPEN[adapter], &hr,
670719f82d3SEliot Blennerhassett 				sizeof(rESP_HPI_MIXER_OPEN[adapter]));
671719f82d3SEliot Blennerhassett 
672719f82d3SEliot Blennerhassett 			for (i = 0; i < HPI_MAX_STREAMS; i++) {
673719f82d3SEliot Blennerhassett 				hpi_init_response(&hr, HPI_OBJ_OSTREAM,
674719f82d3SEliot Blennerhassett 					HPI_OSTREAM_OPEN,
675719f82d3SEliot Blennerhassett 					HPI_ERROR_INVALID_OBJ);
676719f82d3SEliot Blennerhassett 				memcpy(&rESP_HPI_OSTREAM_OPEN[adapter][i],
677719f82d3SEliot Blennerhassett 					&hr,
678719f82d3SEliot Blennerhassett 					sizeof(rESP_HPI_OSTREAM_OPEN[adapter]
679719f82d3SEliot Blennerhassett 						[i]));
680719f82d3SEliot Blennerhassett 				hpi_init_response(&hr, HPI_OBJ_ISTREAM,
681719f82d3SEliot Blennerhassett 					HPI_ISTREAM_OPEN,
682719f82d3SEliot Blennerhassett 					HPI_ERROR_INVALID_OBJ);
683719f82d3SEliot Blennerhassett 				memcpy(&rESP_HPI_ISTREAM_OPEN[adapter][i],
684719f82d3SEliot Blennerhassett 					&hr,
685719f82d3SEliot Blennerhassett 					sizeof(rESP_HPI_ISTREAM_OPEN[adapter]
686719f82d3SEliot Blennerhassett 						[i]));
687719f82d3SEliot Blennerhassett 			}
688719f82d3SEliot Blennerhassett 		}
689719f82d3SEliot Blennerhassett 	} else if (adapter_index < HPI_MAX_ADAPTERS) {
690719f82d3SEliot Blennerhassett 		rESP_HPI_ADAPTER_OPEN[adapter_index].h.error =
691719f82d3SEliot Blennerhassett 			HPI_ERROR_BAD_ADAPTER;
692719f82d3SEliot Blennerhassett 		rESP_HPI_MIXER_OPEN[adapter_index].h.error =
693719f82d3SEliot Blennerhassett 			HPI_ERROR_INVALID_OBJ;
694719f82d3SEliot Blennerhassett 		for (i = 0; i < HPI_MAX_STREAMS; i++) {
695719f82d3SEliot Blennerhassett 			rESP_HPI_OSTREAM_OPEN[adapter_index][i].h.error =
696719f82d3SEliot Blennerhassett 				HPI_ERROR_INVALID_OBJ;
697719f82d3SEliot Blennerhassett 			rESP_HPI_ISTREAM_OPEN[adapter_index][i].h.error =
698719f82d3SEliot Blennerhassett 				HPI_ERROR_INVALID_OBJ;
699719f82d3SEliot Blennerhassett 		}
700719f82d3SEliot Blennerhassett 	}
701719f82d3SEliot Blennerhassett }
702719f82d3SEliot Blennerhassett 
703719f82d3SEliot Blennerhassett static u16 HPIMSGX__init(struct hpi_message *phm,
704719f82d3SEliot Blennerhassett 	/* HPI_SUBSYS_CREATE_ADAPTER structure with */
705719f82d3SEliot Blennerhassett 	/* resource list or NULL=find all */
706719f82d3SEliot Blennerhassett 	struct hpi_response *phr
707719f82d3SEliot Blennerhassett 	/* response from HPI_ADAPTER_GET_INFO */
708719f82d3SEliot Blennerhassett 	)
709719f82d3SEliot Blennerhassett {
710719f82d3SEliot Blennerhassett 	hpi_handler_func *entry_point_func;
711719f82d3SEliot Blennerhassett 	struct hpi_response hr;
712719f82d3SEliot Blennerhassett 
713719f82d3SEliot Blennerhassett 	/* Init response here so we can pass in previous adapter list */
714719f82d3SEliot Blennerhassett 	hpi_init_response(&hr, phm->object, phm->function,
715719f82d3SEliot Blennerhassett 		HPI_ERROR_INVALID_OBJ);
716719f82d3SEliot Blennerhassett 
717719f82d3SEliot Blennerhassett 	entry_point_func =
718719f82d3SEliot Blennerhassett 		hpi_lookup_entry_point_function(phm->u.s.resource.r.pci);
719719f82d3SEliot Blennerhassett 
720719f82d3SEliot Blennerhassett 	if (entry_point_func) {
721719f82d3SEliot Blennerhassett 		HPI_DEBUG_MESSAGE(DEBUG, phm);
722719f82d3SEliot Blennerhassett 		entry_point_func(phm, &hr);
723719f82d3SEliot Blennerhassett 	} else {
724719f82d3SEliot Blennerhassett 		phr->error = HPI_ERROR_PROCESSING_MESSAGE;
725719f82d3SEliot Blennerhassett 		return phr->error;
726719f82d3SEliot Blennerhassett 	}
727719f82d3SEliot Blennerhassett 	if (hr.error == 0) {
72825985edcSLucas De Marchi 		/* the adapter was created successfully
729719f82d3SEliot Blennerhassett 		   save the mapping for future use */
730719f82d3SEliot Blennerhassett 		hpi_entry_points[hr.u.s.adapter_index] = entry_point_func;
731719f82d3SEliot Blennerhassett 		/* prepare adapter (pre-open streams etc.) */
732719f82d3SEliot Blennerhassett 		HPI_DEBUG_LOG(DEBUG,
733719f82d3SEliot Blennerhassett 			"HPI_SUBSYS_CREATE_ADAPTER successful,"
734719f82d3SEliot Blennerhassett 			" preparing adapter\n");
735719f82d3SEliot Blennerhassett 		adapter_prepare(hr.u.s.adapter_index);
736719f82d3SEliot Blennerhassett 	}
737719f82d3SEliot Blennerhassett 	memcpy(phr, &hr, hr.size);
738719f82d3SEliot Blennerhassett 	return phr->error;
739719f82d3SEliot Blennerhassett }
740719f82d3SEliot Blennerhassett 
741719f82d3SEliot Blennerhassett static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner)
742719f82d3SEliot Blennerhassett {
743719f82d3SEliot Blennerhassett 	int i, adapter, adapter_limit;
744719f82d3SEliot Blennerhassett 
745719f82d3SEliot Blennerhassett 	if (!h_owner)
746719f82d3SEliot Blennerhassett 		return;
747719f82d3SEliot Blennerhassett 
748719f82d3SEliot Blennerhassett 	if (adapter_index == HPIMSGX_ALLADAPTERS) {
749719f82d3SEliot Blennerhassett 		adapter = 0;
750719f82d3SEliot Blennerhassett 		adapter_limit = HPI_MAX_ADAPTERS;
751719f82d3SEliot Blennerhassett 	} else {
752719f82d3SEliot Blennerhassett 		adapter = adapter_index;
753719f82d3SEliot Blennerhassett 		adapter_limit = adapter + 1;
754719f82d3SEliot Blennerhassett 	}
755719f82d3SEliot Blennerhassett 
756719f82d3SEliot Blennerhassett 	for (; adapter < adapter_limit; adapter++) {
757719f82d3SEliot Blennerhassett 		/*      printk(KERN_INFO "Cleanup adapter #%d\n",wAdapter); */
758719f82d3SEliot Blennerhassett 		for (i = 0; i < HPI_MAX_STREAMS; i++) {
759719f82d3SEliot Blennerhassett 			if (h_owner ==
760719f82d3SEliot Blennerhassett 				outstream_user_open[adapter][i].h_owner) {
761719f82d3SEliot Blennerhassett 				struct hpi_message hm;
762719f82d3SEliot Blennerhassett 				struct hpi_response hr;
763719f82d3SEliot Blennerhassett 
764719f82d3SEliot Blennerhassett 				HPI_DEBUG_LOG(DEBUG,
7653285ea10SEliot Blennerhassett 					"Close adapter %d ostream %d\n",
766719f82d3SEliot Blennerhassett 					adapter, i);
767719f82d3SEliot Blennerhassett 
768719f82d3SEliot Blennerhassett 				hpi_init_message_response(&hm, &hr,
769719f82d3SEliot Blennerhassett 					HPI_OBJ_OSTREAM, HPI_OSTREAM_RESET);
770719f82d3SEliot Blennerhassett 				hm.adapter_index = (u16)adapter;
771719f82d3SEliot Blennerhassett 				hm.obj_index = (u16)i;
772719f82d3SEliot Blennerhassett 				hw_entry_point(&hm, &hr);
773719f82d3SEliot Blennerhassett 
774719f82d3SEliot Blennerhassett 				hm.function = HPI_OSTREAM_HOSTBUFFER_FREE;
775719f82d3SEliot Blennerhassett 				hw_entry_point(&hm, &hr);
776719f82d3SEliot Blennerhassett 
777719f82d3SEliot Blennerhassett 				hm.function = HPI_OSTREAM_GROUP_RESET;
778719f82d3SEliot Blennerhassett 				hw_entry_point(&hm, &hr);
779719f82d3SEliot Blennerhassett 
780719f82d3SEliot Blennerhassett 				outstream_user_open[adapter][i].open_flag = 0;
781719f82d3SEliot Blennerhassett 				outstream_user_open[adapter][i].h_owner =
782719f82d3SEliot Blennerhassett 					NULL;
783719f82d3SEliot Blennerhassett 			}
784719f82d3SEliot Blennerhassett 			if (h_owner == instream_user_open[adapter][i].h_owner) {
785719f82d3SEliot Blennerhassett 				struct hpi_message hm;
786719f82d3SEliot Blennerhassett 				struct hpi_response hr;
787719f82d3SEliot Blennerhassett 
788719f82d3SEliot Blennerhassett 				HPI_DEBUG_LOG(DEBUG,
7893285ea10SEliot Blennerhassett 					"Close adapter %d istream %d\n",
790719f82d3SEliot Blennerhassett 					adapter, i);
791719f82d3SEliot Blennerhassett 
792719f82d3SEliot Blennerhassett 				hpi_init_message_response(&hm, &hr,
793719f82d3SEliot Blennerhassett 					HPI_OBJ_ISTREAM, HPI_ISTREAM_RESET);
794719f82d3SEliot Blennerhassett 				hm.adapter_index = (u16)adapter;
795719f82d3SEliot Blennerhassett 				hm.obj_index = (u16)i;
796719f82d3SEliot Blennerhassett 				hw_entry_point(&hm, &hr);
797719f82d3SEliot Blennerhassett 
798719f82d3SEliot Blennerhassett 				hm.function = HPI_ISTREAM_HOSTBUFFER_FREE;
799719f82d3SEliot Blennerhassett 				hw_entry_point(&hm, &hr);
800719f82d3SEliot Blennerhassett 
801719f82d3SEliot Blennerhassett 				hm.function = HPI_ISTREAM_GROUP_RESET;
802719f82d3SEliot Blennerhassett 				hw_entry_point(&hm, &hr);
803719f82d3SEliot Blennerhassett 
804719f82d3SEliot Blennerhassett 				instream_user_open[adapter][i].open_flag = 0;
805719f82d3SEliot Blennerhassett 				instream_user_open[adapter][i].h_owner = NULL;
806719f82d3SEliot Blennerhassett 			}
807719f82d3SEliot Blennerhassett 		}
808719f82d3SEliot Blennerhassett 	}
809719f82d3SEliot Blennerhassett }
810