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