blob: 736f45337fc70c18c2507eb40d00796f40c569cf [file] [log] [blame]
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02001/******************************************************************************
2
3 AudioScience HPI driver
Eliot Blennerhassett5bc91f52014-11-20 16:22:54 +13004 Copyright (C) 1997-2014 AudioScience Inc. <support@audioscience.com>
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +02005
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
Eliot Blennerhassett938c5652011-07-22 15:52:50 +120019Extended Message Function With Response Caching
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +020020
21(C) Copyright AudioScience Inc. 2002
22*****************************************************************************/
23#define SOURCEFILE_NAME "hpimsgx.c"
24#include "hpi_internal.h"
Eliot Blennerhassettf6baaec2011-12-22 13:38:31 +130025#include "hpi_version.h"
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +020026#include "hpimsginit.h"
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +130027#include "hpicmn.h"
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +020028#include "hpimsgx.h"
29#include "hpidebug.h"
30
31static struct pci_device_id asihpi_pci_tbl[] = {
32#include "hpipcida.h"
33};
34
35static struct hpios_spinlock msgx_lock;
36
37static hpi_handler_func *hpi_entry_points[HPI_MAX_ADAPTERS];
Eliot Blennerhassett5bc91f52014-11-20 16:22:54 +130038static int logging_enabled = 1;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +020039
40static 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
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +130048 && asihpi_pci_tbl[i].vendor !=
49 pci_info->pci_dev->vendor)
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +020050 continue;
51 if (asihpi_pci_tbl[i].device != PCI_ANY_ID
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +130052 && asihpi_pci_tbl[i].device !=
53 pci_info->pci_dev->device)
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +020054 continue;
55 if (asihpi_pci_tbl[i].subvendor != PCI_ANY_ID
56 && asihpi_pci_tbl[i].subvendor !=
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +130057 pci_info->pci_dev->subsystem_vendor)
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +020058 continue;
59 if (asihpi_pci_tbl[i].subdevice != PCI_ANY_ID
60 && asihpi_pci_tbl[i].subdevice !=
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +130061 pci_info->pci_dev->subsystem_device)
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +020062 continue;
63
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +130064 /* HPI_DEBUG_LOG(DEBUG, " %x,%lx\n", i,
65 asihpi_pci_tbl[i].driver_data); */
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +020066 return (hpi_handler_func *) asihpi_pci_tbl[i].driver_data;
67 }
68
69 return NULL;
70}
71
72static inline void hw_entry_point(struct hpi_message *phm,
73 struct hpi_response *phr)
74{
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +130075 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);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +020081}
82
83static void adapter_open(struct hpi_message *phm, struct hpi_response *phr);
84static void adapter_close(struct hpi_message *phm, struct hpi_response *phr);
85
86static void mixer_open(struct hpi_message *phm, struct hpi_response *phr);
87static void mixer_close(struct hpi_message *phm, struct hpi_response *phr);
88
89static void outstream_open(struct hpi_message *phm, struct hpi_response *phr,
90 void *h_owner);
91static void outstream_close(struct hpi_message *phm, struct hpi_response *phr,
92 void *h_owner);
93static void instream_open(struct hpi_message *phm, struct hpi_response *phr,
94 void *h_owner);
95static void instream_close(struct hpi_message *phm, struct hpi_response *phr,
96 void *h_owner);
97
98static void HPIMSGX__reset(u16 adapter_index);
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +130099
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200100static u16 HPIMSGX__init(struct hpi_message *phm, struct hpi_response *phr);
101static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner);
102
103#ifndef DISABLE_PRAGMA_PACK1
104#pragma pack(push, 1)
105#endif
106
107struct hpi_subsys_response {
108 struct hpi_response_header h;
109 struct hpi_subsys_res s;
110};
111
112struct hpi_adapter_response {
113 struct hpi_response_header h;
114 struct hpi_adapter_res a;
115};
116
117struct hpi_mixer_response {
118 struct hpi_response_header h;
119 struct hpi_mixer_res m;
120};
121
122struct hpi_stream_response {
123 struct hpi_response_header h;
124 struct hpi_stream_res d;
125};
126
127struct adapter_info {
128 u16 type;
129 u16 num_instreams;
130 u16 num_outstreams;
131};
132
133struct 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 */
143static struct hpi_adapter_response rESP_HPI_ADAPTER_OPEN[HPI_MAX_ADAPTERS];
144
145static struct hpi_stream_response
146 rESP_HPI_OSTREAM_OPEN[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
147
148static struct hpi_stream_response
149 rESP_HPI_ISTREAM_OPEN[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
150
151static struct hpi_mixer_response rESP_HPI_MIXER_OPEN[HPI_MAX_ADAPTERS];
152
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200153static struct adapter_info aDAPTER_INFO[HPI_MAX_ADAPTERS];
154
155/* use these to keep track of opens from user mode apps/DLLs */
156static struct asi_open_state
157 outstream_user_open[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
158
159static struct asi_open_state
160 instream_user_open[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
161
162static void subsys_message(struct hpi_message *phm, struct hpi_response *phr,
163 void *h_owner)
164{
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300165 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
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200170 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));
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200191 /* 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);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200201 hpi_init_response(phr, HPI_OBJ_SUBSYSTEM,
202 HPI_SUBSYS_DRIVER_UNLOAD, 0);
203 return;
204
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300205 case HPI_SUBSYS_GET_NUM_ADAPTERS:
206 case HPI_SUBSYS_GET_ADAPTER:
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200207 HPI_COMMON(phm, phr);
208 break;
209
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200210 case HPI_SUBSYS_CREATE_ADAPTER:
211 HPIMSGX__init(phm, phr);
212 break;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300213
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200214 default:
Eliot Blennerhassett1d595d22011-02-10 17:26:08 +1300215 /* Must explicitly handle every subsys message in this switch */
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300216 hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function,
217 HPI_ERROR_INVALID_FUNC);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200218 break;
219 }
220}
221
222static 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;
Eliot Blennerhassett6d0b8982011-04-05 20:55:47 +1200232 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
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200245 default:
246 hw_entry_point(phm, phr);
247 break;
248 }
249}
250
251static 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
266static 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
288static 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 */
313void hpi_send_recv_ex(struct hpi_message *phm, struct hpi_response *phr,
314 void *h_owner)
315{
Eliot Blennerhassett5bc91f52014-11-20 16:22:54 +1300316
317 if (logging_enabled)
318 HPI_DEBUG_MESSAGE(DEBUG, phm);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200319
Eliot Blennerhassett82b57742011-07-22 15:52:36 +1200320 if (phm->type != HPI_TYPE_REQUEST) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200321 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 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200358
Eliot Blennerhassett5bc91f52014-11-20 16:22:54 +1300359 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 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200366}
367
368static 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
375static 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
381static 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
387static 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
392static 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;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300414 hpios_msgxlock_unlock(&msgx_lock);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200415
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 }
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300439 hpios_msgxlock_unlock(&msgx_lock);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200440}
441
442static 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;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300460 hpios_msgxlock_unlock(&msgx_lock);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200461 /* 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 }
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300486 hpios_msgxlock_unlock(&msgx_lock);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200487}
488
489static 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;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300511 hpios_msgxlock_unlock(&msgx_lock);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200512
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 }
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300536 hpios_msgxlock_unlock(&msgx_lock);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200537}
538
539static 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;
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300558 hpios_msgxlock_unlock(&msgx_lock);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200559 /* 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 }
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300584 hpios_msgxlock_unlock(&msgx_lock);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200585}
586
587static 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
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300613 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;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200616
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
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300650 return 0;
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200651}
652
653static 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) {
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200660 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 }
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200700 }
701}
702
703static 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
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200713 /* 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);
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200716
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) {
Lucas De Marchi25985ed2011-03-30 22:57:33 -0300728 /* the adapter was created successfully
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200729 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
741static 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,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300765 "Close adapter %d ostream %d\n",
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200766 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,
Eliot Blennerhassett3285ea12011-02-10 17:25:58 +1300789 "Close adapter %d istream %d\n",
Eliot Blennerhassett719f82d2010-04-21 18:17:39 +0200790 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}