Linux-libre 5.3.12-gnu
[librecmc/linux-libre.git] / sound / pci / asihpi / hpimsgx.c
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 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 }