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