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