Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
[linux-2.6-microblaze.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  * 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  */
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
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
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  */
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  */
146 static void wipe_adapter_list(void)
147 {
148         memset(&adapters, 0, sizeof(adapters));
149 }
150
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
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 */
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  */
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
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 */
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
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 */
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
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
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
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 }