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