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