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