xref: /linux/sound/pci/asihpi/hpicmn.c (revision 164666fa66669d437bdcc8d5f1744a2aee73be41)
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 }
714