]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/blob - sound/pci/asihpi/hpicmn.c
Merge remote-tracking branches 'asoc/topic/dpcm', 'asoc/topic/es8328', 'asoc/topic...
[mirror_ubuntu-zesty-kernel.git] / sound / pci / asihpi / hpicmn.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 \file hpicmn.c
20
21 Common functions used by hpixxxx.c modules
22
23 (C) Copyright AudioScience Inc. 1998-2003
24 *******************************************************************************/
25 #define SOURCEFILE_NAME "hpicmn.c"
26
27 #include "hpi_internal.h"
28 #include "hpidebug.h"
29 #include "hpimsginit.h"
30
31 #include "hpicmn.h"
32
33 struct hpi_adapters_list {
34 struct hpios_spinlock list_lock;
35 struct hpi_adapter_obj adapter[HPI_MAX_ADAPTERS];
36 u16 gw_num_adapters;
37 };
38
39 static struct hpi_adapters_list adapters;
40
41 /**
42 * Given an HPI Message that was sent out and a response that was received,
43 * validate that the response has the correct fields filled in,
44 * i.e ObjectType, Function etc
45 **/
46 u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr)
47 {
48 if (phr->type != HPI_TYPE_RESPONSE) {
49 HPI_DEBUG_LOG(ERROR, "header type %d invalid\n", phr->type);
50 return HPI_ERROR_INVALID_RESPONSE;
51 }
52
53 if (phr->object != phm->object) {
54 HPI_DEBUG_LOG(ERROR, "header object %d invalid\n",
55 phr->object);
56 return HPI_ERROR_INVALID_RESPONSE;
57 }
58
59 if (phr->function != phm->function) {
60 HPI_DEBUG_LOG(ERROR, "header function %d invalid\n",
61 phr->function);
62 return HPI_ERROR_INVALID_RESPONSE;
63 }
64
65 return 0;
66 }
67
68 u16 hpi_add_adapter(struct hpi_adapter_obj *pao)
69 {
70 u16 retval = 0;
71 /*HPI_ASSERT(pao->type); */
72
73 hpios_alistlock_lock(&adapters);
74
75 if (pao->index >= HPI_MAX_ADAPTERS) {
76 retval = HPI_ERROR_BAD_ADAPTER_NUMBER;
77 goto unlock;
78 }
79
80 if (adapters.adapter[pao->index].type) {
81 int a;
82 for (a = HPI_MAX_ADAPTERS - 1; a >= 0; a--) {
83 if (!adapters.adapter[a].type) {
84 HPI_DEBUG_LOG(WARNING,
85 "ASI%X duplicate index %d moved to %d\n",
86 pao->type, pao->index, a);
87 pao->index = a;
88 break;
89 }
90 }
91 if (a < 0) {
92 retval = HPI_ERROR_DUPLICATE_ADAPTER_NUMBER;
93 goto unlock;
94 }
95 }
96 adapters.adapter[pao->index] = *pao;
97 hpios_dsplock_init(&adapters.adapter[pao->index]);
98 adapters.gw_num_adapters++;
99
100 unlock:
101 hpios_alistlock_unlock(&adapters);
102 return retval;
103 }
104
105 void hpi_delete_adapter(struct hpi_adapter_obj *pao)
106 {
107 if (!pao->type) {
108 HPI_DEBUG_LOG(ERROR, "removing null adapter?\n");
109 return;
110 }
111
112 hpios_alistlock_lock(&adapters);
113 if (adapters.adapter[pao->index].type)
114 adapters.gw_num_adapters--;
115 memset(&adapters.adapter[pao->index], 0, sizeof(adapters.adapter[0]));
116 hpios_alistlock_unlock(&adapters);
117 }
118
119 /**
120 * FindAdapter returns a pointer to the struct hpi_adapter_obj with
121 * index wAdapterIndex in an HPI_ADAPTERS_LIST structure.
122 *
123 */
124 struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index)
125 {
126 struct hpi_adapter_obj *pao = NULL;
127
128 if (adapter_index >= HPI_MAX_ADAPTERS) {
129 HPI_DEBUG_LOG(VERBOSE, "find_adapter invalid index %d\n",
130 adapter_index);
131 return NULL;
132 }
133
134 pao = &adapters.adapter[adapter_index];
135 if (pao->type != 0) {
136 /*
137 HPI_DEBUG_LOG(VERBOSE, "Found adapter index %d\n",
138 wAdapterIndex);
139 */
140 return pao;
141 } else {
142 /*
143 HPI_DEBUG_LOG(VERBOSE, "No adapter index %d\n",
144 wAdapterIndex);
145 */
146 return NULL;
147 }
148 }
149
150 /**
151 *
152 * wipe an HPI_ADAPTERS_LIST structure.
153 *
154 **/
155 static void wipe_adapter_list(void)
156 {
157 memset(&adapters, 0, sizeof(adapters));
158 }
159
160 static void subsys_get_adapter(struct hpi_message *phm,
161 struct hpi_response *phr)
162 {
163 int count = phm->obj_index;
164 u16 index = 0;
165
166 /* find the nCount'th nonzero adapter in array */
167 for (index = 0; index < HPI_MAX_ADAPTERS; index++) {
168 if (adapters.adapter[index].type) {
169 if (!count)
170 break;
171 count--;
172 }
173 }
174
175 if (index < HPI_MAX_ADAPTERS) {
176 phr->u.s.adapter_index = adapters.adapter[index].index;
177 phr->u.s.adapter_type = adapters.adapter[index].type;
178 } else {
179 phr->u.s.adapter_index = 0;
180 phr->u.s.adapter_type = 0;
181 phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
182 }
183 }
184
185 static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC)
186 {
187 unsigned int i;
188 int cached = 0;
189 if (!pC)
190 return 0;
191
192 if (pC->init)
193 return pC->init;
194
195 if (!pC->p_cache)
196 return 0;
197
198 if (pC->control_count && pC->cache_size_in_bytes) {
199 char *p_master_cache;
200 unsigned int byte_count = 0;
201
202 p_master_cache = (char *)pC->p_cache;
203 HPI_DEBUG_LOG(DEBUG, "check %d controls\n",
204 pC->control_count);
205 for (i = 0; i < pC->control_count; i++) {
206 struct hpi_control_cache_info *info =
207 (struct hpi_control_cache_info *)
208 &p_master_cache[byte_count];
209 u16 control_index = info->control_index;
210
211 if (control_index >= pC->control_count) {
212 HPI_DEBUG_LOG(INFO,
213 "adap %d control index %d out of range, cache not ready?\n",
214 pC->adap_idx, control_index);
215 return 0;
216 }
217
218 if (!info->size_in32bit_words) {
219 if (!i) {
220 HPI_DEBUG_LOG(INFO,
221 "adap %d cache not ready?\n",
222 pC->adap_idx);
223 return 0;
224 }
225 /* The cache is invalid.
226 * Minimum valid entry size is
227 * sizeof(struct hpi_control_cache_info)
228 */
229 HPI_DEBUG_LOG(ERROR,
230 "adap %d zero size cache entry %d\n",
231 pC->adap_idx, i);
232 break;
233 }
234
235 if (info->control_type) {
236 pC->p_info[control_index] = info;
237 cached++;
238 } else { /* dummy cache entry */
239 pC->p_info[control_index] = NULL;
240 }
241
242 byte_count += info->size_in32bit_words * 4;
243
244 HPI_DEBUG_LOG(VERBOSE,
245 "cached %d, pinfo %p index %d type %d size %d\n",
246 cached, pC->p_info[info->control_index],
247 info->control_index, info->control_type,
248 info->size_in32bit_words);
249
250 /* quit loop early if whole cache has been scanned.
251 * dwControlCount is the maximum possible entries
252 * but some may be absent from the cache
253 */
254 if (byte_count >= pC->cache_size_in_bytes)
255 break;
256 /* have seen last control index */
257 if (info->control_index == pC->control_count - 1)
258 break;
259 }
260
261 if (byte_count != pC->cache_size_in_bytes)
262 HPI_DEBUG_LOG(WARNING,
263 "adap %d bytecount %d != cache size %d\n",
264 pC->adap_idx, byte_count,
265 pC->cache_size_in_bytes);
266 else
267 HPI_DEBUG_LOG(DEBUG,
268 "adap %d cache good, bytecount == cache size = %d\n",
269 pC->adap_idx, byte_count);
270
271 pC->init = (u16)cached;
272 }
273 return pC->init;
274 }
275
276 /** Find a control.
277 */
278 static short find_control(u16 control_index,
279 struct hpi_control_cache *p_cache, struct hpi_control_cache_info **pI)
280 {
281 if (!control_cache_alloc_check(p_cache)) {
282 HPI_DEBUG_LOG(VERBOSE,
283 "control_cache_alloc_check() failed %d\n",
284 control_index);
285 return 0;
286 }
287
288 *pI = p_cache->p_info[control_index];
289 if (!*pI) {
290 HPI_DEBUG_LOG(VERBOSE, "Uncached Control %d\n",
291 control_index);
292 return 0;
293 } else {
294 HPI_DEBUG_LOG(VERBOSE, "find_control() type %d\n",
295 (*pI)->control_type);
296 }
297 return 1;
298 }
299
300 /* allow unified treatment of several string fields within struct */
301 #define HPICMN_PAD_OFS_AND_SIZE(m) {\
302 offsetof(struct hpi_control_cache_pad, m), \
303 sizeof(((struct hpi_control_cache_pad *)(NULL))->m) }
304
305 struct pad_ofs_size {
306 unsigned int offset;
307 unsigned int field_size;
308 };
309
310 static const struct pad_ofs_size pad_desc[] = {
311 HPICMN_PAD_OFS_AND_SIZE(c_channel), /* HPI_PAD_CHANNEL_NAME */
312 HPICMN_PAD_OFS_AND_SIZE(c_artist), /* HPI_PAD_ARTIST */
313 HPICMN_PAD_OFS_AND_SIZE(c_title), /* HPI_PAD_TITLE */
314 HPICMN_PAD_OFS_AND_SIZE(c_comment), /* HPI_PAD_COMMENT */
315 };
316
317 /** CheckControlCache checks the cache and fills the struct hpi_response
318 * accordingly. It returns one if a cache hit occurred, zero otherwise.
319 */
320 short hpi_check_control_cache_single(struct hpi_control_cache_single *pC,
321 struct hpi_message *phm, struct hpi_response *phr)
322 {
323 size_t response_size;
324 short found = 1;
325
326 /* set the default response size */
327 response_size =
328 sizeof(struct hpi_response_header) +
329 sizeof(struct hpi_control_res);
330
331 switch (pC->u.i.control_type) {
332
333 case HPI_CONTROL_METER:
334 if (phm->u.c.attribute == HPI_METER_PEAK) {
335 phr->u.c.an_log_value[0] = pC->u.meter.an_log_peak[0];
336 phr->u.c.an_log_value[1] = pC->u.meter.an_log_peak[1];
337 } else if (phm->u.c.attribute == HPI_METER_RMS) {
338 if (pC->u.meter.an_logRMS[0] ==
339 HPI_CACHE_INVALID_SHORT) {
340 phr->error =
341 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
342 phr->u.c.an_log_value[0] = HPI_METER_MINIMUM;
343 phr->u.c.an_log_value[1] = HPI_METER_MINIMUM;
344 } else {
345 phr->u.c.an_log_value[0] =
346 pC->u.meter.an_logRMS[0];
347 phr->u.c.an_log_value[1] =
348 pC->u.meter.an_logRMS[1];
349 }
350 } else
351 found = 0;
352 break;
353 case HPI_CONTROL_VOLUME:
354 if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
355 phr->u.c.an_log_value[0] = pC->u.vol.an_log[0];
356 phr->u.c.an_log_value[1] = pC->u.vol.an_log[1];
357 } else if (phm->u.c.attribute == HPI_VOLUME_MUTE) {
358 if (pC->u.vol.flags & HPI_VOLUME_FLAG_HAS_MUTE) {
359 if (pC->u.vol.flags & HPI_VOLUME_FLAG_MUTED)
360 phr->u.c.param1 =
361 HPI_BITMASK_ALL_CHANNELS;
362 else
363 phr->u.c.param1 = 0;
364 } else {
365 phr->error =
366 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
367 phr->u.c.param1 = 0;
368 }
369 } else {
370 found = 0;
371 }
372 break;
373 case HPI_CONTROL_MULTIPLEXER:
374 if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
375 phr->u.c.param1 = pC->u.mux.source_node_type;
376 phr->u.c.param2 = pC->u.mux.source_node_index;
377 } else {
378 found = 0;
379 }
380 break;
381 case HPI_CONTROL_CHANNEL_MODE:
382 if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
383 phr->u.c.param1 = pC->u.mode.mode;
384 else
385 found = 0;
386 break;
387 case HPI_CONTROL_LEVEL:
388 if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
389 phr->u.c.an_log_value[0] = pC->u.level.an_log[0];
390 phr->u.c.an_log_value[1] = pC->u.level.an_log[1];
391 } else
392 found = 0;
393 break;
394 case HPI_CONTROL_TUNER:
395 if (phm->u.c.attribute == HPI_TUNER_FREQ)
396 phr->u.c.param1 = pC->u.tuner.freq_ink_hz;
397 else if (phm->u.c.attribute == HPI_TUNER_BAND)
398 phr->u.c.param1 = pC->u.tuner.band;
399 else if (phm->u.c.attribute == HPI_TUNER_LEVEL_AVG)
400 if (pC->u.tuner.s_level_avg ==
401 HPI_CACHE_INVALID_SHORT) {
402 phr->u.cu.tuner.s_level = 0;
403 phr->error =
404 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
405 } else
406 phr->u.cu.tuner.s_level =
407 pC->u.tuner.s_level_avg;
408 else
409 found = 0;
410 break;
411 case HPI_CONTROL_AESEBU_RECEIVER:
412 if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS)
413 phr->u.c.param1 = pC->u.aes3rx.error_status;
414 else if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
415 phr->u.c.param1 = pC->u.aes3rx.format;
416 else
417 found = 0;
418 break;
419 case HPI_CONTROL_AESEBU_TRANSMITTER:
420 if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
421 phr->u.c.param1 = pC->u.aes3tx.format;
422 else
423 found = 0;
424 break;
425 case HPI_CONTROL_TONEDETECTOR:
426 if (phm->u.c.attribute == HPI_TONEDETECTOR_STATE)
427 phr->u.c.param1 = pC->u.tone.state;
428 else
429 found = 0;
430 break;
431 case HPI_CONTROL_SILENCEDETECTOR:
432 if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) {
433 phr->u.c.param1 = pC->u.silence.state;
434 } else
435 found = 0;
436 break;
437 case HPI_CONTROL_MICROPHONE:
438 if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
439 phr->u.c.param1 = pC->u.microphone.phantom_state;
440 else
441 found = 0;
442 break;
443 case HPI_CONTROL_SAMPLECLOCK:
444 if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
445 phr->u.c.param1 = pC->u.clk.source;
446 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) {
447 if (pC->u.clk.source_index ==
448 HPI_CACHE_INVALID_UINT16) {
449 phr->u.c.param1 = 0;
450 phr->error =
451 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
452 } else
453 phr->u.c.param1 = pC->u.clk.source_index;
454 } else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
455 phr->u.c.param1 = pC->u.clk.sample_rate;
456 else
457 found = 0;
458 break;
459 case HPI_CONTROL_PAD:{
460 struct hpi_control_cache_pad *p_pad;
461 p_pad = (struct hpi_control_cache_pad *)pC;
462
463 if (!(p_pad->field_valid_flags & (1 <<
464 HPI_CTL_ATTR_INDEX(phm->u.c.
465 attribute)))) {
466 phr->error =
467 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
468 break;
469 }
470
471 if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID)
472 phr->u.c.param1 = p_pad->pI;
473 else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE)
474 phr->u.c.param1 = p_pad->pTY;
475 else {
476 unsigned int index =
477 HPI_CTL_ATTR_INDEX(phm->u.c.
478 attribute) - 1;
479 unsigned int offset = phm->u.c.param1;
480 unsigned int pad_string_len, field_size;
481 char *pad_string;
482 unsigned int tocopy;
483
484 if (index > ARRAY_SIZE(pad_desc) - 1) {
485 phr->error =
486 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
487 break;
488 }
489
490 pad_string =
491 ((char *)p_pad) +
492 pad_desc[index].offset;
493 field_size = pad_desc[index].field_size;
494 /* Ensure null terminator */
495 pad_string[field_size - 1] = 0;
496
497 pad_string_len = strlen(pad_string) + 1;
498
499 if (offset > pad_string_len) {
500 phr->error =
501 HPI_ERROR_INVALID_CONTROL_VALUE;
502 break;
503 }
504
505 tocopy = pad_string_len - offset;
506 if (tocopy > sizeof(phr->u.cu.chars8.sz_data))
507 tocopy = sizeof(phr->u.cu.chars8.
508 sz_data);
509
510 memcpy(phr->u.cu.chars8.sz_data,
511 &pad_string[offset], tocopy);
512
513 phr->u.cu.chars8.remaining_chars =
514 pad_string_len - offset - tocopy;
515 }
516 }
517 break;
518 default:
519 found = 0;
520 break;
521 }
522
523 HPI_DEBUG_LOG(VERBOSE, "%s Adap %d, Ctl %d, Type %d, Attr %d\n",
524 found ? "Cached" : "Uncached", phm->adapter_index,
525 pC->u.i.control_index, pC->u.i.control_type,
526 phm->u.c.attribute);
527
528 if (found) {
529 phr->size = (u16)response_size;
530 phr->type = HPI_TYPE_RESPONSE;
531 phr->object = phm->object;
532 phr->function = phm->function;
533 }
534
535 return found;
536 }
537
538 short hpi_check_control_cache(struct hpi_control_cache *p_cache,
539 struct hpi_message *phm, struct hpi_response *phr)
540 {
541 struct hpi_control_cache_info *pI;
542
543 if (!find_control(phm->obj_index, p_cache, &pI)) {
544 HPI_DEBUG_LOG(VERBOSE,
545 "HPICMN find_control() failed for adap %d\n",
546 phm->adapter_index);
547 return 0;
548 }
549
550 phr->error = 0;
551 phr->specific_error = 0;
552 phr->version = 0;
553
554 return hpi_check_control_cache_single((struct hpi_control_cache_single
555 *)pI, phm, phr);
556 }
557
558 /** Updates the cache with Set values.
559
560 Only update if no error.
561 Volume and Level return the limited values in the response, so use these
562 Multiplexer does so use sent values
563 */
564 void hpi_cmn_control_cache_sync_to_msg_single(struct hpi_control_cache_single
565 *pC, struct hpi_message *phm, struct hpi_response *phr)
566 {
567 switch (pC->u.i.control_type) {
568 case HPI_CONTROL_VOLUME:
569 if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
570 pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
571 pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
572 } else if (phm->u.c.attribute == HPI_VOLUME_MUTE) {
573 if (phm->u.c.param1)
574 pC->u.vol.flags |= HPI_VOLUME_FLAG_MUTED;
575 else
576 pC->u.vol.flags &= ~HPI_VOLUME_FLAG_MUTED;
577 }
578 break;
579 case HPI_CONTROL_MULTIPLEXER:
580 /* mux does not return its setting on Set command. */
581 if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
582 pC->u.mux.source_node_type = (u16)phm->u.c.param1;
583 pC->u.mux.source_node_index = (u16)phm->u.c.param2;
584 }
585 break;
586 case HPI_CONTROL_CHANNEL_MODE:
587 /* mode does not return its setting on Set command. */
588 if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
589 pC->u.mode.mode = (u16)phm->u.c.param1;
590 break;
591 case HPI_CONTROL_LEVEL:
592 if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
593 pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
594 pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
595 }
596 break;
597 case HPI_CONTROL_MICROPHONE:
598 if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
599 pC->u.microphone.phantom_state = (u16)phm->u.c.param1;
600 break;
601 case HPI_CONTROL_AESEBU_TRANSMITTER:
602 if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
603 pC->u.aes3tx.format = phm->u.c.param1;
604 break;
605 case HPI_CONTROL_AESEBU_RECEIVER:
606 if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
607 pC->u.aes3rx.format = phm->u.c.param1;
608 break;
609 case HPI_CONTROL_SAMPLECLOCK:
610 if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
611 pC->u.clk.source = (u16)phm->u.c.param1;
612 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX)
613 pC->u.clk.source_index = (u16)phm->u.c.param1;
614 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
615 pC->u.clk.sample_rate = phm->u.c.param1;
616 break;
617 default:
618 break;
619 }
620 }
621
622 void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *p_cache,
623 struct hpi_message *phm, struct hpi_response *phr)
624 {
625 struct hpi_control_cache_single *pC;
626 struct hpi_control_cache_info *pI;
627
628 if (phr->error)
629 return;
630
631 if (!find_control(phm->obj_index, p_cache, &pI)) {
632 HPI_DEBUG_LOG(VERBOSE,
633 "HPICMN find_control() failed for adap %d\n",
634 phm->adapter_index);
635 return;
636 }
637
638 /* pC is the default cached control strucure.
639 May be cast to something else in the following switch statement.
640 */
641 pC = (struct hpi_control_cache_single *)pI;
642
643 hpi_cmn_control_cache_sync_to_msg_single(pC, phm, phr);
644 }
645
646 /** Allocate control cache.
647
648 \return Cache pointer, or NULL if allocation fails.
649 */
650 struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count,
651 const u32 size_in_bytes, u8 *p_dsp_control_buffer)
652 {
653 struct hpi_control_cache *p_cache =
654 kmalloc(sizeof(*p_cache), GFP_KERNEL);
655 if (!p_cache)
656 return NULL;
657
658 p_cache->p_info =
659 kcalloc(control_count, sizeof(*p_cache->p_info), GFP_KERNEL);
660 if (!p_cache->p_info) {
661 kfree(p_cache);
662 return NULL;
663 }
664
665 p_cache->cache_size_in_bytes = size_in_bytes;
666 p_cache->control_count = control_count;
667 p_cache->p_cache = p_dsp_control_buffer;
668 p_cache->init = 0;
669 return p_cache;
670 }
671
672 void hpi_free_control_cache(struct hpi_control_cache *p_cache)
673 {
674 if (p_cache) {
675 kfree(p_cache->p_info);
676 kfree(p_cache);
677 }
678 }
679
680 static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
681 {
682 hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function, 0);
683
684 switch (phm->function) {
685 case HPI_SUBSYS_OPEN:
686 case HPI_SUBSYS_CLOSE:
687 case HPI_SUBSYS_DRIVER_UNLOAD:
688 break;
689 case HPI_SUBSYS_DRIVER_LOAD:
690 wipe_adapter_list();
691 hpios_alistlock_init(&adapters);
692 break;
693 case HPI_SUBSYS_GET_ADAPTER:
694 subsys_get_adapter(phm, phr);
695 break;
696 case HPI_SUBSYS_GET_NUM_ADAPTERS:
697 phr->u.s.num_adapters = adapters.gw_num_adapters;
698 break;
699 case HPI_SUBSYS_CREATE_ADAPTER:
700 break;
701 default:
702 phr->error = HPI_ERROR_INVALID_FUNC;
703 break;
704 }
705 }
706
707 void HPI_COMMON(struct hpi_message *phm, struct hpi_response *phr)
708 {
709 switch (phm->type) {
710 case HPI_TYPE_REQUEST:
711 switch (phm->object) {
712 case HPI_OBJ_SUBSYSTEM:
713 subsys_message(phm, phr);
714 break;
715 }
716 break;
717
718 default:
719 phr->error = HPI_ERROR_INVALID_TYPE;
720 break;
721 }
722 }