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