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