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