xref: /openbmc/linux/sound/pci/asihpi/hpicmn.c (revision 7d23b167)
107d7fe7bSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2719f82d3SEliot Blennerhassett /******************************************************************************
3719f82d3SEliot Blennerhassett 
4719f82d3SEliot Blennerhassett     AudioScience HPI driver
5c1464a88SEliot Blennerhassett     Copyright (C) 1997-2014  AudioScience Inc. <support@audioscience.com>
6719f82d3SEliot Blennerhassett 
7719f82d3SEliot Blennerhassett 
8719f82d3SEliot Blennerhassett \file hpicmn.c
9719f82d3SEliot Blennerhassett 
10719f82d3SEliot Blennerhassett  Common functions used by hpixxxx.c modules
11719f82d3SEliot Blennerhassett 
12719f82d3SEliot Blennerhassett (C) Copyright AudioScience Inc. 1998-2003
13719f82d3SEliot Blennerhassett *******************************************************************************/
14719f82d3SEliot Blennerhassett #define SOURCEFILE_NAME "hpicmn.c"
15719f82d3SEliot Blennerhassett 
16719f82d3SEliot Blennerhassett #include "hpi_internal.h"
17719f82d3SEliot Blennerhassett #include "hpidebug.h"
183285ea10SEliot Blennerhassett #include "hpimsginit.h"
193285ea10SEliot Blennerhassett 
20719f82d3SEliot Blennerhassett #include "hpicmn.h"
21719f82d3SEliot Blennerhassett 
22719f82d3SEliot Blennerhassett struct hpi_adapters_list {
23719f82d3SEliot Blennerhassett 	struct hpios_spinlock list_lock;
24719f82d3SEliot Blennerhassett 	struct hpi_adapter_obj adapter[HPI_MAX_ADAPTERS];
25719f82d3SEliot Blennerhassett 	u16 gw_num_adapters;
26719f82d3SEliot Blennerhassett };
27719f82d3SEliot Blennerhassett 
28719f82d3SEliot Blennerhassett static struct hpi_adapters_list adapters;
29719f82d3SEliot Blennerhassett 
30719f82d3SEliot Blennerhassett /**
317d23b167SPierre-Louis Bossart  * hpi_validate_response - Given an HPI Message that was sent out and
327d23b167SPierre-Louis Bossart  * a response that was received, validate that the response has the
337d23b167SPierre-Louis Bossart  * correct fields filled in, i.e ObjectType, Function etc
347d23b167SPierre-Louis Bossart  * @phm: message
357d23b167SPierre-Louis Bossart  * @phr: response
367d23b167SPierre-Louis Bossart  */
hpi_validate_response(struct hpi_message * phm,struct hpi_response * phr)37719f82d3SEliot Blennerhassett u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr)
38719f82d3SEliot Blennerhassett {
393285ea10SEliot Blennerhassett 	if (phr->type != HPI_TYPE_RESPONSE) {
401528fbb5SEliot Blennerhassett 		HPI_DEBUG_LOG(ERROR, "header type %d invalid\n", phr->type);
413285ea10SEliot Blennerhassett 		return HPI_ERROR_INVALID_RESPONSE;
423285ea10SEliot Blennerhassett 	}
43719f82d3SEliot Blennerhassett 
443285ea10SEliot Blennerhassett 	if (phr->object != phm->object) {
451528fbb5SEliot Blennerhassett 		HPI_DEBUG_LOG(ERROR, "header object %d invalid\n",
461528fbb5SEliot Blennerhassett 			phr->object);
473285ea10SEliot Blennerhassett 		return HPI_ERROR_INVALID_RESPONSE;
483285ea10SEliot Blennerhassett 	}
49719f82d3SEliot Blennerhassett 
503285ea10SEliot Blennerhassett 	if (phr->function != phm->function) {
51938c565aSEliot Blennerhassett 		HPI_DEBUG_LOG(ERROR, "header function %d invalid\n",
521528fbb5SEliot Blennerhassett 			phr->function);
533285ea10SEliot Blennerhassett 		return HPI_ERROR_INVALID_RESPONSE;
543285ea10SEliot Blennerhassett 	}
553285ea10SEliot Blennerhassett 
563285ea10SEliot Blennerhassett 	return 0;
57719f82d3SEliot Blennerhassett }
58719f82d3SEliot Blennerhassett 
hpi_add_adapter(struct hpi_adapter_obj * pao)59719f82d3SEliot Blennerhassett u16 hpi_add_adapter(struct hpi_adapter_obj *pao)
60719f82d3SEliot Blennerhassett {
61719f82d3SEliot Blennerhassett 	u16 retval = 0;
627036b92dSEliot Blennerhassett 	/*HPI_ASSERT(pao->type); */
63719f82d3SEliot Blennerhassett 
64719f82d3SEliot Blennerhassett 	hpios_alistlock_lock(&adapters);
65719f82d3SEliot Blennerhassett 
66719f82d3SEliot Blennerhassett 	if (pao->index >= HPI_MAX_ADAPTERS) {
67719f82d3SEliot Blennerhassett 		retval = HPI_ERROR_BAD_ADAPTER_NUMBER;
68719f82d3SEliot Blennerhassett 		goto unlock;
69719f82d3SEliot Blennerhassett 	}
70719f82d3SEliot Blennerhassett 
717036b92dSEliot Blennerhassett 	if (adapters.adapter[pao->index].type) {
72d6f1c1c3SEliot Blennerhassett 		int a;
73d6f1c1c3SEliot Blennerhassett 		for (a = HPI_MAX_ADAPTERS - 1; a >= 0; a--) {
747036b92dSEliot Blennerhassett 			if (!adapters.adapter[a].type) {
75d6f1c1c3SEliot Blennerhassett 				HPI_DEBUG_LOG(WARNING,
76d6f1c1c3SEliot Blennerhassett 					"ASI%X duplicate index %d moved to %d\n",
777036b92dSEliot Blennerhassett 					pao->type, pao->index, a);
78d6f1c1c3SEliot Blennerhassett 				pao->index = a;
79d6f1c1c3SEliot Blennerhassett 				break;
80d6f1c1c3SEliot Blennerhassett 			}
81d6f1c1c3SEliot Blennerhassett 		}
82d6f1c1c3SEliot Blennerhassett 		if (a < 0) {
83d6f1c1c3SEliot Blennerhassett 			retval = HPI_ERROR_DUPLICATE_ADAPTER_NUMBER;
84719f82d3SEliot Blennerhassett 			goto unlock;
85719f82d3SEliot Blennerhassett 		}
86719f82d3SEliot Blennerhassett 	}
87719f82d3SEliot Blennerhassett 	adapters.adapter[pao->index] = *pao;
88719f82d3SEliot Blennerhassett 	hpios_dsplock_init(&adapters.adapter[pao->index]);
89719f82d3SEliot Blennerhassett 	adapters.gw_num_adapters++;
90719f82d3SEliot Blennerhassett 
91719f82d3SEliot Blennerhassett unlock:
923285ea10SEliot Blennerhassett 	hpios_alistlock_unlock(&adapters);
93719f82d3SEliot Blennerhassett 	return retval;
94719f82d3SEliot Blennerhassett }
95719f82d3SEliot Blennerhassett 
hpi_delete_adapter(struct hpi_adapter_obj * pao)96719f82d3SEliot Blennerhassett void hpi_delete_adapter(struct hpi_adapter_obj *pao)
97719f82d3SEliot Blennerhassett {
987036b92dSEliot Blennerhassett 	if (!pao->type) {
993285ea10SEliot Blennerhassett 		HPI_DEBUG_LOG(ERROR, "removing null adapter?\n");
1003285ea10SEliot Blennerhassett 		return;
1013285ea10SEliot Blennerhassett 	}
102719f82d3SEliot Blennerhassett 
103719f82d3SEliot Blennerhassett 	hpios_alistlock_lock(&adapters);
1047036b92dSEliot Blennerhassett 	if (adapters.adapter[pao->index].type)
1053285ea10SEliot Blennerhassett 		adapters.gw_num_adapters--;
1063285ea10SEliot Blennerhassett 	memset(&adapters.adapter[pao->index], 0, sizeof(adapters.adapter[0]));
1073285ea10SEliot Blennerhassett 	hpios_alistlock_unlock(&adapters);
108719f82d3SEliot Blennerhassett }
109719f82d3SEliot Blennerhassett 
110719f82d3SEliot Blennerhassett /**
1117d23b167SPierre-Louis Bossart  * hpi_find_adapter - FindAdapter returns a pointer to the struct
1127d23b167SPierre-Louis Bossart  * hpi_adapter_obj with index wAdapterIndex in an HPI_ADAPTERS_LIST
1137d23b167SPierre-Louis Bossart  * structure.
1147d23b167SPierre-Louis Bossart  * @adapter_index: value in [0, HPI_MAX_ADAPTERS[
115719f82d3SEliot Blennerhassett  */
hpi_find_adapter(u16 adapter_index)116719f82d3SEliot Blennerhassett struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index)
117719f82d3SEliot Blennerhassett {
118719f82d3SEliot Blennerhassett 	struct hpi_adapter_obj *pao = NULL;
119719f82d3SEliot Blennerhassett 
120719f82d3SEliot Blennerhassett 	if (adapter_index >= HPI_MAX_ADAPTERS) {
1211528fbb5SEliot Blennerhassett 		HPI_DEBUG_LOG(VERBOSE, "find_adapter invalid index %d\n",
122719f82d3SEliot Blennerhassett 			adapter_index);
123719f82d3SEliot Blennerhassett 		return NULL;
124719f82d3SEliot Blennerhassett 	}
125719f82d3SEliot Blennerhassett 
126719f82d3SEliot Blennerhassett 	pao = &adapters.adapter[adapter_index];
1277036b92dSEliot Blennerhassett 	if (pao->type != 0) {
128719f82d3SEliot Blennerhassett 		/*
129719f82d3SEliot Blennerhassett 		   HPI_DEBUG_LOG(VERBOSE, "Found adapter index %d\n",
130719f82d3SEliot Blennerhassett 		   wAdapterIndex);
131719f82d3SEliot Blennerhassett 		 */
132719f82d3SEliot Blennerhassett 		return pao;
133719f82d3SEliot Blennerhassett 	} else {
134719f82d3SEliot Blennerhassett 		/*
135719f82d3SEliot Blennerhassett 		   HPI_DEBUG_LOG(VERBOSE, "No adapter index %d\n",
136719f82d3SEliot Blennerhassett 		   wAdapterIndex);
137719f82d3SEliot Blennerhassett 		 */
138719f82d3SEliot Blennerhassett 		return NULL;
139719f82d3SEliot Blennerhassett 	}
140719f82d3SEliot Blennerhassett }
141719f82d3SEliot Blennerhassett 
142719f82d3SEliot Blennerhassett /**
1437d23b167SPierre-Louis Bossart  * wipe_adapter_list - wipe an HPI_ADAPTERS_LIST structure.
144719f82d3SEliot Blennerhassett  *
1457d23b167SPierre-Louis Bossart  */
wipe_adapter_list(void)1463285ea10SEliot Blennerhassett static void wipe_adapter_list(void)
147719f82d3SEliot Blennerhassett {
148719f82d3SEliot Blennerhassett 	memset(&adapters, 0, sizeof(adapters));
149719f82d3SEliot Blennerhassett }
150719f82d3SEliot Blennerhassett 
subsys_get_adapter(struct hpi_message * phm,struct hpi_response * phr)1513285ea10SEliot Blennerhassett static void subsys_get_adapter(struct hpi_message *phm,
1523285ea10SEliot Blennerhassett 	struct hpi_response *phr)
153719f82d3SEliot Blennerhassett {
1543285ea10SEliot Blennerhassett 	int count = phm->obj_index;
1553285ea10SEliot Blennerhassett 	u16 index = 0;
156719f82d3SEliot Blennerhassett 
1573285ea10SEliot Blennerhassett 	/* find the nCount'th nonzero adapter in array */
1583285ea10SEliot Blennerhassett 	for (index = 0; index < HPI_MAX_ADAPTERS; index++) {
1597036b92dSEliot Blennerhassett 		if (adapters.adapter[index].type) {
1604704998eSEliot Blennerhassett 			if (!count)
1613285ea10SEliot Blennerhassett 				break;
1623285ea10SEliot Blennerhassett 			count--;
163719f82d3SEliot Blennerhassett 		}
164719f82d3SEliot Blennerhassett 	}
165719f82d3SEliot Blennerhassett 
1663285ea10SEliot Blennerhassett 	if (index < HPI_MAX_ADAPTERS) {
1673285ea10SEliot Blennerhassett 		phr->u.s.adapter_index = adapters.adapter[index].index;
1687036b92dSEliot Blennerhassett 		phr->u.s.adapter_type = adapters.adapter[index].type;
1693285ea10SEliot Blennerhassett 	} else {
1703285ea10SEliot Blennerhassett 		phr->u.s.adapter_index = 0;
1712f918a64SEliot Blennerhassett 		phr->u.s.adapter_type = 0;
1727036b92dSEliot Blennerhassett 		phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
1733285ea10SEliot Blennerhassett 	}
174719f82d3SEliot Blennerhassett }
175719f82d3SEliot Blennerhassett 
control_cache_alloc_check(struct hpi_control_cache * pC)176719f82d3SEliot Blennerhassett static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC)
177719f82d3SEliot Blennerhassett {
178719f82d3SEliot Blennerhassett 	unsigned int i;
179719f82d3SEliot Blennerhassett 	int cached = 0;
180719f82d3SEliot Blennerhassett 	if (!pC)
181719f82d3SEliot Blennerhassett 		return 0;
182719f82d3SEliot Blennerhassett 
1833285ea10SEliot Blennerhassett 	if (pC->init)
1843285ea10SEliot Blennerhassett 		return pC->init;
1853285ea10SEliot Blennerhassett 
1863285ea10SEliot Blennerhassett 	if (!pC->p_cache)
1873285ea10SEliot Blennerhassett 		return 0;
1883285ea10SEliot Blennerhassett 
1893285ea10SEliot Blennerhassett 	if (pC->control_count && pC->cache_size_in_bytes) {
1903285ea10SEliot Blennerhassett 		char *p_master_cache;
1913285ea10SEliot Blennerhassett 		unsigned int byte_count = 0;
1923285ea10SEliot Blennerhassett 
1933285ea10SEliot Blennerhassett 		p_master_cache = (char *)pC->p_cache;
1943285ea10SEliot Blennerhassett 		HPI_DEBUG_LOG(DEBUG, "check %d controls\n",
195719f82d3SEliot Blennerhassett 			pC->control_count);
196719f82d3SEliot Blennerhassett 		for (i = 0; i < pC->control_count; i++) {
197719f82d3SEliot Blennerhassett 			struct hpi_control_cache_info *info =
198719f82d3SEliot Blennerhassett 				(struct hpi_control_cache_info *)
1993285ea10SEliot Blennerhassett 				&p_master_cache[byte_count];
200c1464a88SEliot Blennerhassett 			u16 control_index = info->control_index;
201c1464a88SEliot Blennerhassett 
202c1464a88SEliot Blennerhassett 			if (control_index >= pC->control_count) {
203c1464a88SEliot Blennerhassett 				HPI_DEBUG_LOG(INFO,
204c1464a88SEliot Blennerhassett 					"adap %d control index %d out of range, cache not ready?\n",
205c1464a88SEliot Blennerhassett 					pC->adap_idx, control_index);
206c1464a88SEliot Blennerhassett 				return 0;
207c1464a88SEliot Blennerhassett 			}
2083285ea10SEliot Blennerhassett 
2093285ea10SEliot Blennerhassett 			if (!info->size_in32bit_words) {
2104704998eSEliot Blennerhassett 				if (!i) {
211ffdb5787SEliot Blennerhassett 					HPI_DEBUG_LOG(INFO,
212ffdb5787SEliot Blennerhassett 						"adap %d cache not ready?\n",
213ffdb5787SEliot Blennerhassett 						pC->adap_idx);
214ffdb5787SEliot Blennerhassett 					return 0;
215ffdb5787SEliot Blennerhassett 				}
2161528fbb5SEliot Blennerhassett 				/* The cache is invalid.
2171528fbb5SEliot Blennerhassett 				 * Minimum valid entry size is
2181528fbb5SEliot Blennerhassett 				 * sizeof(struct hpi_control_cache_info)
2191528fbb5SEliot Blennerhassett 				 */
2203285ea10SEliot Blennerhassett 				HPI_DEBUG_LOG(ERROR,
221ffdb5787SEliot Blennerhassett 					"adap %d zero size cache entry %d\n",
222ffdb5787SEliot Blennerhassett 					pC->adap_idx, i);
2233285ea10SEliot Blennerhassett 				break;
2243285ea10SEliot Blennerhassett 			}
225719f82d3SEliot Blennerhassett 
226719f82d3SEliot Blennerhassett 			if (info->control_type) {
227c1464a88SEliot Blennerhassett 				pC->p_info[control_index] = info;
228719f82d3SEliot Blennerhassett 				cached++;
22942258dabSEliot Blennerhassett 			} else {	/* dummy cache entry */
230c1464a88SEliot Blennerhassett 				pC->p_info[control_index] = NULL;
23142258dabSEliot Blennerhassett 			}
232719f82d3SEliot Blennerhassett 
2333285ea10SEliot Blennerhassett 			byte_count += info->size_in32bit_words * 4;
234719f82d3SEliot Blennerhassett 
235719f82d3SEliot Blennerhassett 			HPI_DEBUG_LOG(VERBOSE,
2363285ea10SEliot Blennerhassett 				"cached %d, pinfo %p index %d type %d size %d\n",
2373285ea10SEliot Blennerhassett 				cached, pC->p_info[info->control_index],
2383285ea10SEliot Blennerhassett 				info->control_index, info->control_type,
2393285ea10SEliot Blennerhassett 				info->size_in32bit_words);
2403285ea10SEliot Blennerhassett 
2411528fbb5SEliot Blennerhassett 			/* quit loop early if whole cache has been scanned.
2421528fbb5SEliot Blennerhassett 			 * dwControlCount is the maximum possible entries
2431528fbb5SEliot Blennerhassett 			 * but some may be absent from the cache
2441528fbb5SEliot Blennerhassett 			 */
2453285ea10SEliot Blennerhassett 			if (byte_count >= pC->cache_size_in_bytes)
2463285ea10SEliot Blennerhassett 				break;
2473285ea10SEliot Blennerhassett 			/* have seen last control index */
2483285ea10SEliot Blennerhassett 			if (info->control_index == pC->control_count - 1)
2493285ea10SEliot Blennerhassett 				break;
250719f82d3SEliot Blennerhassett 		}
2513285ea10SEliot Blennerhassett 
2523285ea10SEliot Blennerhassett 		if (byte_count != pC->cache_size_in_bytes)
2533285ea10SEliot Blennerhassett 			HPI_DEBUG_LOG(WARNING,
2541528fbb5SEliot Blennerhassett 				"adap %d bytecount %d != cache size %d\n",
255ffdb5787SEliot Blennerhassett 				pC->adap_idx, byte_count,
2563285ea10SEliot Blennerhassett 				pC->cache_size_in_bytes);
2573285ea10SEliot Blennerhassett 		else
2583285ea10SEliot Blennerhassett 			HPI_DEBUG_LOG(DEBUG,
2591528fbb5SEliot Blennerhassett 				"adap %d cache good, bytecount == cache size = %d\n",
260ffdb5787SEliot Blennerhassett 				pC->adap_idx, byte_count);
2613285ea10SEliot Blennerhassett 
2621528fbb5SEliot Blennerhassett 		pC->init = (u16)cached;
263719f82d3SEliot Blennerhassett 	}
264719f82d3SEliot Blennerhassett 	return pC->init;
265719f82d3SEliot Blennerhassett }
266719f82d3SEliot Blennerhassett 
267719f82d3SEliot Blennerhassett /** Find a control.
268719f82d3SEliot Blennerhassett */
find_control(u16 control_index,struct hpi_control_cache * p_cache,struct hpi_control_cache_info ** pI)2693285ea10SEliot Blennerhassett static short find_control(u16 control_index,
2703285ea10SEliot Blennerhassett 	struct hpi_control_cache *p_cache, struct hpi_control_cache_info **pI)
271719f82d3SEliot Blennerhassett {
272719f82d3SEliot Blennerhassett 	if (!control_cache_alloc_check(p_cache)) {
273719f82d3SEliot Blennerhassett 		HPI_DEBUG_LOG(VERBOSE,
2743285ea10SEliot Blennerhassett 			"control_cache_alloc_check() failed %d\n",
2753285ea10SEliot Blennerhassett 			control_index);
276719f82d3SEliot Blennerhassett 		return 0;
277719f82d3SEliot Blennerhassett 	}
278719f82d3SEliot Blennerhassett 
2793285ea10SEliot Blennerhassett 	*pI = p_cache->p_info[control_index];
280719f82d3SEliot Blennerhassett 	if (!*pI) {
2813285ea10SEliot Blennerhassett 		HPI_DEBUG_LOG(VERBOSE, "Uncached Control %d\n",
2823285ea10SEliot Blennerhassett 			control_index);
283719f82d3SEliot Blennerhassett 		return 0;
284719f82d3SEliot Blennerhassett 	} else {
285719f82d3SEliot Blennerhassett 		HPI_DEBUG_LOG(VERBOSE, "find_control() type %d\n",
286719f82d3SEliot Blennerhassett 			(*pI)->control_type);
287719f82d3SEliot Blennerhassett 	}
288719f82d3SEliot Blennerhassett 	return 1;
289719f82d3SEliot Blennerhassett }
290719f82d3SEliot Blennerhassett 
291719f82d3SEliot Blennerhassett /* allow unified treatment of several string fields within struct */
292719f82d3SEliot Blennerhassett #define HPICMN_PAD_OFS_AND_SIZE(m)  {\
293719f82d3SEliot Blennerhassett 	offsetof(struct hpi_control_cache_pad, m), \
294719f82d3SEliot Blennerhassett 	sizeof(((struct hpi_control_cache_pad *)(NULL))->m) }
295719f82d3SEliot Blennerhassett 
296719f82d3SEliot Blennerhassett struct pad_ofs_size {
297719f82d3SEliot Blennerhassett 	unsigned int offset;
298719f82d3SEliot Blennerhassett 	unsigned int field_size;
299719f82d3SEliot Blennerhassett };
300719f82d3SEliot Blennerhassett 
30142258dabSEliot Blennerhassett static const struct pad_ofs_size pad_desc[] = {
302719f82d3SEliot Blennerhassett 	HPICMN_PAD_OFS_AND_SIZE(c_channel),	/* HPI_PAD_CHANNEL_NAME */
303719f82d3SEliot Blennerhassett 	HPICMN_PAD_OFS_AND_SIZE(c_artist),	/* HPI_PAD_ARTIST */
304719f82d3SEliot Blennerhassett 	HPICMN_PAD_OFS_AND_SIZE(c_title),	/* HPI_PAD_TITLE */
305719f82d3SEliot Blennerhassett 	HPICMN_PAD_OFS_AND_SIZE(c_comment),	/* HPI_PAD_COMMENT */
306719f82d3SEliot Blennerhassett };
307719f82d3SEliot Blennerhassett 
308719f82d3SEliot Blennerhassett /** CheckControlCache checks the cache and fills the struct hpi_response
309719f82d3SEliot Blennerhassett  * accordingly. It returns one if a cache hit occurred, zero otherwise.
310719f82d3SEliot Blennerhassett  */
hpi_check_control_cache_single(struct hpi_control_cache_single * pC,struct hpi_message * phm,struct hpi_response * phr)311c1464a88SEliot Blennerhassett short hpi_check_control_cache_single(struct hpi_control_cache_single *pC,
312719f82d3SEliot Blennerhassett 	struct hpi_message *phm, struct hpi_response *phr)
313719f82d3SEliot Blennerhassett {
3143d0591eeSEliot Blennerhassett 	size_t response_size;
315c1464a88SEliot Blennerhassett 	short found = 1;
316719f82d3SEliot Blennerhassett 
317c6c2c9abSEliot Blennerhassett 	/* set the default response size */
318c6c2c9abSEliot Blennerhassett 	response_size =
319c6c2c9abSEliot Blennerhassett 		sizeof(struct hpi_response_header) +
320c6c2c9abSEliot Blennerhassett 		sizeof(struct hpi_control_res);
321c6c2c9abSEliot Blennerhassett 
322c1464a88SEliot Blennerhassett 	switch (pC->u.i.control_type) {
323719f82d3SEliot Blennerhassett 
324719f82d3SEliot Blennerhassett 	case HPI_CONTROL_METER:
325719f82d3SEliot Blennerhassett 		if (phm->u.c.attribute == HPI_METER_PEAK) {
3263285ea10SEliot Blennerhassett 			phr->u.c.an_log_value[0] = pC->u.meter.an_log_peak[0];
3273285ea10SEliot Blennerhassett 			phr->u.c.an_log_value[1] = pC->u.meter.an_log_peak[1];
328719f82d3SEliot Blennerhassett 		} else if (phm->u.c.attribute == HPI_METER_RMS) {
3293285ea10SEliot Blennerhassett 			if (pC->u.meter.an_logRMS[0] ==
3303285ea10SEliot Blennerhassett 				HPI_CACHE_INVALID_SHORT) {
3313285ea10SEliot Blennerhassett 				phr->error =
3323285ea10SEliot Blennerhassett 					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
3333285ea10SEliot Blennerhassett 				phr->u.c.an_log_value[0] = HPI_METER_MINIMUM;
3343285ea10SEliot Blennerhassett 				phr->u.c.an_log_value[1] = HPI_METER_MINIMUM;
3353285ea10SEliot Blennerhassett 			} else {
3363285ea10SEliot Blennerhassett 				phr->u.c.an_log_value[0] =
3373285ea10SEliot Blennerhassett 					pC->u.meter.an_logRMS[0];
3383285ea10SEliot Blennerhassett 				phr->u.c.an_log_value[1] =
3393285ea10SEliot Blennerhassett 					pC->u.meter.an_logRMS[1];
3403285ea10SEliot Blennerhassett 			}
341719f82d3SEliot Blennerhassett 		} else
342719f82d3SEliot Blennerhassett 			found = 0;
343719f82d3SEliot Blennerhassett 		break;
344719f82d3SEliot Blennerhassett 	case HPI_CONTROL_VOLUME:
345719f82d3SEliot Blennerhassett 		if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
3463285ea10SEliot Blennerhassett 			phr->u.c.an_log_value[0] = pC->u.vol.an_log[0];
3473285ea10SEliot Blennerhassett 			phr->u.c.an_log_value[1] = pC->u.vol.an_log[1];
348fc3a3990SEliot Blennerhassett 		} else if (phm->u.c.attribute == HPI_VOLUME_MUTE) {
349fc3a3990SEliot Blennerhassett 			if (pC->u.vol.flags & HPI_VOLUME_FLAG_HAS_MUTE) {
350fc3a3990SEliot Blennerhassett 				if (pC->u.vol.flags & HPI_VOLUME_FLAG_MUTED)
351fc3a3990SEliot Blennerhassett 					phr->u.c.param1 =
352fc3a3990SEliot Blennerhassett 						HPI_BITMASK_ALL_CHANNELS;
353fc3a3990SEliot Blennerhassett 				else
354fc3a3990SEliot Blennerhassett 					phr->u.c.param1 = 0;
355fc3a3990SEliot Blennerhassett 			} else {
356fc3a3990SEliot Blennerhassett 				phr->error =
357fc3a3990SEliot Blennerhassett 					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
358fc3a3990SEliot Blennerhassett 				phr->u.c.param1 = 0;
359fc3a3990SEliot Blennerhassett 			}
360fc3a3990SEliot Blennerhassett 		} else {
361719f82d3SEliot Blennerhassett 			found = 0;
362fc3a3990SEliot Blennerhassett 		}
363719f82d3SEliot Blennerhassett 		break;
364719f82d3SEliot Blennerhassett 	case HPI_CONTROL_MULTIPLEXER:
365719f82d3SEliot Blennerhassett 		if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
3663285ea10SEliot Blennerhassett 			phr->u.c.param1 = pC->u.mux.source_node_type;
3673285ea10SEliot Blennerhassett 			phr->u.c.param2 = pC->u.mux.source_node_index;
368719f82d3SEliot Blennerhassett 		} else {
369719f82d3SEliot Blennerhassett 			found = 0;
370719f82d3SEliot Blennerhassett 		}
371719f82d3SEliot Blennerhassett 		break;
372719f82d3SEliot Blennerhassett 	case HPI_CONTROL_CHANNEL_MODE:
373719f82d3SEliot Blennerhassett 		if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
3743285ea10SEliot Blennerhassett 			phr->u.c.param1 = pC->u.mode.mode;
375719f82d3SEliot Blennerhassett 		else
376719f82d3SEliot Blennerhassett 			found = 0;
377719f82d3SEliot Blennerhassett 		break;
378719f82d3SEliot Blennerhassett 	case HPI_CONTROL_LEVEL:
379719f82d3SEliot Blennerhassett 		if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
3803285ea10SEliot Blennerhassett 			phr->u.c.an_log_value[0] = pC->u.level.an_log[0];
3813285ea10SEliot Blennerhassett 			phr->u.c.an_log_value[1] = pC->u.level.an_log[1];
382719f82d3SEliot Blennerhassett 		} else
383719f82d3SEliot Blennerhassett 			found = 0;
384719f82d3SEliot Blennerhassett 		break;
385719f82d3SEliot Blennerhassett 	case HPI_CONTROL_TUNER:
386719f82d3SEliot Blennerhassett 		if (phm->u.c.attribute == HPI_TUNER_FREQ)
3873285ea10SEliot Blennerhassett 			phr->u.c.param1 = pC->u.tuner.freq_ink_hz;
388719f82d3SEliot Blennerhassett 		else if (phm->u.c.attribute == HPI_TUNER_BAND)
3893285ea10SEliot Blennerhassett 			phr->u.c.param1 = pC->u.tuner.band;
3903285ea10SEliot Blennerhassett 		else if (phm->u.c.attribute == HPI_TUNER_LEVEL_AVG)
3913285ea10SEliot Blennerhassett 			if (pC->u.tuner.s_level_avg ==
3923285ea10SEliot Blennerhassett 				HPI_CACHE_INVALID_SHORT) {
3933285ea10SEliot Blennerhassett 				phr->u.cu.tuner.s_level = 0;
39436ed8bddSEliot Blennerhassett 				phr->error =
39536ed8bddSEliot Blennerhassett 					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
39636ed8bddSEliot Blennerhassett 			} else
3973285ea10SEliot Blennerhassett 				phr->u.cu.tuner.s_level =
3983285ea10SEliot Blennerhassett 					pC->u.tuner.s_level_avg;
399719f82d3SEliot Blennerhassett 		else
400719f82d3SEliot Blennerhassett 			found = 0;
401719f82d3SEliot Blennerhassett 		break;
402719f82d3SEliot Blennerhassett 	case HPI_CONTROL_AESEBU_RECEIVER:
403719f82d3SEliot Blennerhassett 		if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS)
404719f82d3SEliot Blennerhassett 			phr->u.c.param1 = pC->u.aes3rx.error_status;
405719f82d3SEliot Blennerhassett 		else if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
4063285ea10SEliot Blennerhassett 			phr->u.c.param1 = pC->u.aes3rx.format;
407719f82d3SEliot Blennerhassett 		else
408719f82d3SEliot Blennerhassett 			found = 0;
409719f82d3SEliot Blennerhassett 		break;
410719f82d3SEliot Blennerhassett 	case HPI_CONTROL_AESEBU_TRANSMITTER:
411719f82d3SEliot Blennerhassett 		if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
412719f82d3SEliot Blennerhassett 			phr->u.c.param1 = pC->u.aes3tx.format;
413719f82d3SEliot Blennerhassett 		else
414719f82d3SEliot Blennerhassett 			found = 0;
415719f82d3SEliot Blennerhassett 		break;
416719f82d3SEliot Blennerhassett 	case HPI_CONTROL_TONEDETECTOR:
417719f82d3SEliot Blennerhassett 		if (phm->u.c.attribute == HPI_TONEDETECTOR_STATE)
418719f82d3SEliot Blennerhassett 			phr->u.c.param1 = pC->u.tone.state;
419719f82d3SEliot Blennerhassett 		else
420719f82d3SEliot Blennerhassett 			found = 0;
421719f82d3SEliot Blennerhassett 		break;
422719f82d3SEliot Blennerhassett 	case HPI_CONTROL_SILENCEDETECTOR:
423719f82d3SEliot Blennerhassett 		if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) {
424719f82d3SEliot Blennerhassett 			phr->u.c.param1 = pC->u.silence.state;
425719f82d3SEliot Blennerhassett 		} else
426719f82d3SEliot Blennerhassett 			found = 0;
427719f82d3SEliot Blennerhassett 		break;
428719f82d3SEliot Blennerhassett 	case HPI_CONTROL_MICROPHONE:
429719f82d3SEliot Blennerhassett 		if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
4303285ea10SEliot Blennerhassett 			phr->u.c.param1 = pC->u.microphone.phantom_state;
431719f82d3SEliot Blennerhassett 		else
432719f82d3SEliot Blennerhassett 			found = 0;
433719f82d3SEliot Blennerhassett 		break;
434719f82d3SEliot Blennerhassett 	case HPI_CONTROL_SAMPLECLOCK:
435719f82d3SEliot Blennerhassett 		if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
436719f82d3SEliot Blennerhassett 			phr->u.c.param1 = pC->u.clk.source;
437719f82d3SEliot Blennerhassett 		else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) {
438719f82d3SEliot Blennerhassett 			if (pC->u.clk.source_index ==
4393285ea10SEliot Blennerhassett 				HPI_CACHE_INVALID_UINT16) {
440719f82d3SEliot Blennerhassett 				phr->u.c.param1 = 0;
44136ed8bddSEliot Blennerhassett 				phr->error =
44236ed8bddSEliot Blennerhassett 					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
443719f82d3SEliot Blennerhassett 			} else
444719f82d3SEliot Blennerhassett 				phr->u.c.param1 = pC->u.clk.source_index;
445719f82d3SEliot Blennerhassett 		} else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
446719f82d3SEliot Blennerhassett 			phr->u.c.param1 = pC->u.clk.sample_rate;
447719f82d3SEliot Blennerhassett 		else
448719f82d3SEliot Blennerhassett 			found = 0;
449719f82d3SEliot Blennerhassett 		break;
4503285ea10SEliot Blennerhassett 	case HPI_CONTROL_PAD:{
4513285ea10SEliot Blennerhassett 			struct hpi_control_cache_pad *p_pad;
452c1464a88SEliot Blennerhassett 			p_pad = (struct hpi_control_cache_pad *)pC;
453719f82d3SEliot Blennerhassett 
454719f82d3SEliot Blennerhassett 			if (!(p_pad->field_valid_flags & (1 <<
455719f82d3SEliot Blennerhassett 						HPI_CTL_ATTR_INDEX(phm->u.c.
456719f82d3SEliot Blennerhassett 							attribute)))) {
4573285ea10SEliot Blennerhassett 				phr->error =
4583285ea10SEliot Blennerhassett 					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
459719f82d3SEliot Blennerhassett 				break;
460719f82d3SEliot Blennerhassett 			}
461719f82d3SEliot Blennerhassett 
462719f82d3SEliot Blennerhassett 			if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID)
463719f82d3SEliot Blennerhassett 				phr->u.c.param1 = p_pad->pI;
464719f82d3SEliot Blennerhassett 			else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE)
465719f82d3SEliot Blennerhassett 				phr->u.c.param1 = p_pad->pTY;
466719f82d3SEliot Blennerhassett 			else {
467719f82d3SEliot Blennerhassett 				unsigned int index =
4683285ea10SEliot Blennerhassett 					HPI_CTL_ATTR_INDEX(phm->u.c.
4693285ea10SEliot Blennerhassett 					attribute) - 1;
470719f82d3SEliot Blennerhassett 				unsigned int offset = phm->u.c.param1;
471719f82d3SEliot Blennerhassett 				unsigned int pad_string_len, field_size;
472719f82d3SEliot Blennerhassett 				char *pad_string;
473719f82d3SEliot Blennerhassett 				unsigned int tocopy;
474719f82d3SEliot Blennerhassett 
475719f82d3SEliot Blennerhassett 				if (index > ARRAY_SIZE(pad_desc) - 1) {
476719f82d3SEliot Blennerhassett 					phr->error =
477719f82d3SEliot Blennerhassett 						HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
478719f82d3SEliot Blennerhassett 					break;
479719f82d3SEliot Blennerhassett 				}
480719f82d3SEliot Blennerhassett 
4813285ea10SEliot Blennerhassett 				pad_string =
4823285ea10SEliot Blennerhassett 					((char *)p_pad) +
4833285ea10SEliot Blennerhassett 					pad_desc[index].offset;
484719f82d3SEliot Blennerhassett 				field_size = pad_desc[index].field_size;
485719f82d3SEliot Blennerhassett 				/* Ensure null terminator */
486719f82d3SEliot Blennerhassett 				pad_string[field_size - 1] = 0;
487719f82d3SEliot Blennerhassett 
488719f82d3SEliot Blennerhassett 				pad_string_len = strlen(pad_string) + 1;
489719f82d3SEliot Blennerhassett 
490719f82d3SEliot Blennerhassett 				if (offset > pad_string_len) {
4913285ea10SEliot Blennerhassett 					phr->error =
4923285ea10SEliot Blennerhassett 						HPI_ERROR_INVALID_CONTROL_VALUE;
493719f82d3SEliot Blennerhassett 					break;
494719f82d3SEliot Blennerhassett 				}
495719f82d3SEliot Blennerhassett 
496719f82d3SEliot Blennerhassett 				tocopy = pad_string_len - offset;
497719f82d3SEliot Blennerhassett 				if (tocopy > sizeof(phr->u.cu.chars8.sz_data))
4983285ea10SEliot Blennerhassett 					tocopy = sizeof(phr->u.cu.chars8.
4993285ea10SEliot Blennerhassett 						sz_data);
500719f82d3SEliot Blennerhassett 
5013285ea10SEliot Blennerhassett 				memcpy(phr->u.cu.chars8.sz_data,
5023285ea10SEliot Blennerhassett 					&pad_string[offset], tocopy);
503719f82d3SEliot Blennerhassett 
504719f82d3SEliot Blennerhassett 				phr->u.cu.chars8.remaining_chars =
505719f82d3SEliot Blennerhassett 					pad_string_len - offset - tocopy;
506719f82d3SEliot Blennerhassett 			}
5073285ea10SEliot Blennerhassett 		}
508719f82d3SEliot Blennerhassett 		break;
509719f82d3SEliot Blennerhassett 	default:
510719f82d3SEliot Blennerhassett 		found = 0;
511719f82d3SEliot Blennerhassett 		break;
512719f82d3SEliot Blennerhassett 	}
513719f82d3SEliot Blennerhassett 
5143285ea10SEliot Blennerhassett 	HPI_DEBUG_LOG(VERBOSE, "%s Adap %d, Ctl %d, Type %d, Attr %d\n",
5153285ea10SEliot Blennerhassett 		found ? "Cached" : "Uncached", phm->adapter_index,
516c1464a88SEliot Blennerhassett 		pC->u.i.control_index, pC->u.i.control_type,
517c1464a88SEliot Blennerhassett 		phm->u.c.attribute);
518719f82d3SEliot Blennerhassett 
5198637bc94SEliot Blennerhassett 	if (found) {
5203d0591eeSEliot Blennerhassett 		phr->size = (u16)response_size;
5218637bc94SEliot Blennerhassett 		phr->type = HPI_TYPE_RESPONSE;
5228637bc94SEliot Blennerhassett 		phr->object = phm->object;
5238637bc94SEliot Blennerhassett 		phr->function = phm->function;
5248637bc94SEliot Blennerhassett 	}
525719f82d3SEliot Blennerhassett 
526719f82d3SEliot Blennerhassett 	return found;
527719f82d3SEliot Blennerhassett }
528719f82d3SEliot Blennerhassett 
hpi_check_control_cache(struct hpi_control_cache * p_cache,struct hpi_message * phm,struct hpi_response * phr)529c1464a88SEliot Blennerhassett short hpi_check_control_cache(struct hpi_control_cache *p_cache,
530c1464a88SEliot Blennerhassett 	struct hpi_message *phm, struct hpi_response *phr)
531c1464a88SEliot Blennerhassett {
532c1464a88SEliot Blennerhassett 	struct hpi_control_cache_info *pI;
533c1464a88SEliot Blennerhassett 
534c1464a88SEliot Blennerhassett 	if (!find_control(phm->obj_index, p_cache, &pI)) {
535c1464a88SEliot Blennerhassett 		HPI_DEBUG_LOG(VERBOSE,
536c1464a88SEliot Blennerhassett 			"HPICMN find_control() failed for adap %d\n",
537c1464a88SEliot Blennerhassett 			phm->adapter_index);
538c1464a88SEliot Blennerhassett 		return 0;
539c1464a88SEliot Blennerhassett 	}
540c1464a88SEliot Blennerhassett 
541c1464a88SEliot Blennerhassett 	phr->error = 0;
542c1464a88SEliot Blennerhassett 	phr->specific_error = 0;
543c1464a88SEliot Blennerhassett 	phr->version = 0;
544c1464a88SEliot Blennerhassett 
545c1464a88SEliot Blennerhassett 	return hpi_check_control_cache_single((struct hpi_control_cache_single
546c1464a88SEliot Blennerhassett 			*)pI, phm, phr);
547c1464a88SEliot Blennerhassett }
548c1464a88SEliot Blennerhassett 
549719f82d3SEliot Blennerhassett /** Updates the cache with Set values.
550719f82d3SEliot Blennerhassett 
551719f82d3SEliot Blennerhassett Only update if no error.
552719f82d3SEliot Blennerhassett Volume and Level return the limited values in the response, so use these
553719f82d3SEliot Blennerhassett Multiplexer does so use sent values
554719f82d3SEliot Blennerhassett */
hpi_cmn_control_cache_sync_to_msg_single(struct hpi_control_cache_single * pC,struct hpi_message * phm,struct hpi_response * phr)555c1464a88SEliot Blennerhassett void hpi_cmn_control_cache_sync_to_msg_single(struct hpi_control_cache_single
556c1464a88SEliot Blennerhassett 	*pC, struct hpi_message *phm, struct hpi_response *phr)
557719f82d3SEliot Blennerhassett {
558c1464a88SEliot Blennerhassett 	switch (pC->u.i.control_type) {
559719f82d3SEliot Blennerhassett 	case HPI_CONTROL_VOLUME:
560719f82d3SEliot Blennerhassett 		if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
5613285ea10SEliot Blennerhassett 			pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
5623285ea10SEliot Blennerhassett 			pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
563fc3a3990SEliot Blennerhassett 		} else if (phm->u.c.attribute == HPI_VOLUME_MUTE) {
564fc3a3990SEliot Blennerhassett 			if (phm->u.c.param1)
565fc3a3990SEliot Blennerhassett 				pC->u.vol.flags |= HPI_VOLUME_FLAG_MUTED;
566fc3a3990SEliot Blennerhassett 			else
567fc3a3990SEliot Blennerhassett 				pC->u.vol.flags &= ~HPI_VOLUME_FLAG_MUTED;
568719f82d3SEliot Blennerhassett 		}
569719f82d3SEliot Blennerhassett 		break;
570719f82d3SEliot Blennerhassett 	case HPI_CONTROL_MULTIPLEXER:
571719f82d3SEliot Blennerhassett 		/* mux does not return its setting on Set command. */
572719f82d3SEliot Blennerhassett 		if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
5733285ea10SEliot Blennerhassett 			pC->u.mux.source_node_type = (u16)phm->u.c.param1;
5743285ea10SEliot Blennerhassett 			pC->u.mux.source_node_index = (u16)phm->u.c.param2;
575719f82d3SEliot Blennerhassett 		}
576719f82d3SEliot Blennerhassett 		break;
577719f82d3SEliot Blennerhassett 	case HPI_CONTROL_CHANNEL_MODE:
578719f82d3SEliot Blennerhassett 		/* mode does not return its setting on Set command. */
579719f82d3SEliot Blennerhassett 		if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
5803285ea10SEliot Blennerhassett 			pC->u.mode.mode = (u16)phm->u.c.param1;
581719f82d3SEliot Blennerhassett 		break;
582719f82d3SEliot Blennerhassett 	case HPI_CONTROL_LEVEL:
583719f82d3SEliot Blennerhassett 		if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
5843285ea10SEliot Blennerhassett 			pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
5853285ea10SEliot Blennerhassett 			pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
586719f82d3SEliot Blennerhassett 		}
587719f82d3SEliot Blennerhassett 		break;
588719f82d3SEliot Blennerhassett 	case HPI_CONTROL_MICROPHONE:
589719f82d3SEliot Blennerhassett 		if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
5903285ea10SEliot Blennerhassett 			pC->u.microphone.phantom_state = (u16)phm->u.c.param1;
591719f82d3SEliot Blennerhassett 		break;
592719f82d3SEliot Blennerhassett 	case HPI_CONTROL_AESEBU_TRANSMITTER:
593719f82d3SEliot Blennerhassett 		if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
594719f82d3SEliot Blennerhassett 			pC->u.aes3tx.format = phm->u.c.param1;
595719f82d3SEliot Blennerhassett 		break;
596719f82d3SEliot Blennerhassett 	case HPI_CONTROL_AESEBU_RECEIVER:
597719f82d3SEliot Blennerhassett 		if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
5983285ea10SEliot Blennerhassett 			pC->u.aes3rx.format = phm->u.c.param1;
599719f82d3SEliot Blennerhassett 		break;
600719f82d3SEliot Blennerhassett 	case HPI_CONTROL_SAMPLECLOCK:
601719f82d3SEliot Blennerhassett 		if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
602719f82d3SEliot Blennerhassett 			pC->u.clk.source = (u16)phm->u.c.param1;
603719f82d3SEliot Blennerhassett 		else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX)
604719f82d3SEliot Blennerhassett 			pC->u.clk.source_index = (u16)phm->u.c.param1;
605719f82d3SEliot Blennerhassett 		else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
606719f82d3SEliot Blennerhassett 			pC->u.clk.sample_rate = phm->u.c.param1;
607719f82d3SEliot Blennerhassett 		break;
608719f82d3SEliot Blennerhassett 	default:
609719f82d3SEliot Blennerhassett 		break;
610719f82d3SEliot Blennerhassett 	}
611719f82d3SEliot Blennerhassett }
612719f82d3SEliot Blennerhassett 
hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache * p_cache,struct hpi_message * phm,struct hpi_response * phr)613c1464a88SEliot Blennerhassett void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *p_cache,
614c1464a88SEliot Blennerhassett 	struct hpi_message *phm, struct hpi_response *phr)
615c1464a88SEliot Blennerhassett {
616c1464a88SEliot Blennerhassett 	struct hpi_control_cache_single *pC;
617c1464a88SEliot Blennerhassett 	struct hpi_control_cache_info *pI;
618c1464a88SEliot Blennerhassett 
619c1464a88SEliot Blennerhassett 	if (phr->error)
620c1464a88SEliot Blennerhassett 		return;
621c1464a88SEliot Blennerhassett 
622c1464a88SEliot Blennerhassett 	if (!find_control(phm->obj_index, p_cache, &pI)) {
623c1464a88SEliot Blennerhassett 		HPI_DEBUG_LOG(VERBOSE,
624c1464a88SEliot Blennerhassett 			"HPICMN find_control() failed for adap %d\n",
625c1464a88SEliot Blennerhassett 			phm->adapter_index);
626c1464a88SEliot Blennerhassett 		return;
627c1464a88SEliot Blennerhassett 	}
628c1464a88SEliot Blennerhassett 
629c1464a88SEliot Blennerhassett 	/* pC is the default cached control strucure.
630c1464a88SEliot Blennerhassett 	   May be cast to something else in the following switch statement.
631c1464a88SEliot Blennerhassett 	 */
632c1464a88SEliot Blennerhassett 	pC = (struct hpi_control_cache_single *)pI;
633c1464a88SEliot Blennerhassett 
634c1464a88SEliot Blennerhassett 	hpi_cmn_control_cache_sync_to_msg_single(pC, phm, phr);
635c1464a88SEliot Blennerhassett }
636c1464a88SEliot Blennerhassett 
63742258dabSEliot Blennerhassett /** Allocate control cache.
63842258dabSEliot Blennerhassett 
63942258dabSEliot Blennerhassett \return Cache pointer, or NULL if allocation fails.
64042258dabSEliot Blennerhassett */
hpi_alloc_control_cache(const u32 control_count,const u32 size_in_bytes,u8 * p_dsp_control_buffer)6414704998eSEliot Blennerhassett struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count,
6424704998eSEliot Blennerhassett 	const u32 size_in_bytes, u8 *p_dsp_control_buffer)
643719f82d3SEliot Blennerhassett {
644719f82d3SEliot Blennerhassett 	struct hpi_control_cache *p_cache =
645719f82d3SEliot Blennerhassett 		kmalloc(sizeof(*p_cache), GFP_KERNEL);
646fd0977d0SJesper Juhl 	if (!p_cache)
647fd0977d0SJesper Juhl 		return NULL;
6484704998eSEliot Blennerhassett 
649c1464a88SEliot Blennerhassett 	p_cache->p_info =
650c1464a88SEliot Blennerhassett 		kcalloc(control_count, sizeof(*p_cache->p_info), GFP_KERNEL);
651fd0977d0SJesper Juhl 	if (!p_cache->p_info) {
652fd0977d0SJesper Juhl 		kfree(p_cache);
653fd0977d0SJesper Juhl 		return NULL;
654fd0977d0SJesper Juhl 	}
655c1464a88SEliot Blennerhassett 
656719f82d3SEliot Blennerhassett 	p_cache->cache_size_in_bytes = size_in_bytes;
6574704998eSEliot Blennerhassett 	p_cache->control_count = control_count;
6584704998eSEliot Blennerhassett 	p_cache->p_cache = p_dsp_control_buffer;
659719f82d3SEliot Blennerhassett 	p_cache->init = 0;
660719f82d3SEliot Blennerhassett 	return p_cache;
661719f82d3SEliot Blennerhassett }
662719f82d3SEliot Blennerhassett 
hpi_free_control_cache(struct hpi_control_cache * p_cache)663719f82d3SEliot Blennerhassett void hpi_free_control_cache(struct hpi_control_cache *p_cache)
664719f82d3SEliot Blennerhassett {
6653285ea10SEliot Blennerhassett 	if (p_cache) {
666719f82d3SEliot Blennerhassett 		kfree(p_cache->p_info);
667719f82d3SEliot Blennerhassett 		kfree(p_cache);
668719f82d3SEliot Blennerhassett 	}
669719f82d3SEliot Blennerhassett }
670719f82d3SEliot Blennerhassett 
subsys_message(struct hpi_message * phm,struct hpi_response * phr)671719f82d3SEliot Blennerhassett static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
672719f82d3SEliot Blennerhassett {
6733285ea10SEliot Blennerhassett 	hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function, 0);
674719f82d3SEliot Blennerhassett 
675719f82d3SEliot Blennerhassett 	switch (phm->function) {
676719f82d3SEliot Blennerhassett 	case HPI_SUBSYS_OPEN:
677719f82d3SEliot Blennerhassett 	case HPI_SUBSYS_CLOSE:
678719f82d3SEliot Blennerhassett 	case HPI_SUBSYS_DRIVER_UNLOAD:
679719f82d3SEliot Blennerhassett 		break;
680719f82d3SEliot Blennerhassett 	case HPI_SUBSYS_DRIVER_LOAD:
681719f82d3SEliot Blennerhassett 		wipe_adapter_list();
682719f82d3SEliot Blennerhassett 		hpios_alistlock_init(&adapters);
683719f82d3SEliot Blennerhassett 		break;
6843285ea10SEliot Blennerhassett 	case HPI_SUBSYS_GET_ADAPTER:
6853285ea10SEliot Blennerhassett 		subsys_get_adapter(phm, phr);
6863285ea10SEliot Blennerhassett 		break;
6873285ea10SEliot Blennerhassett 	case HPI_SUBSYS_GET_NUM_ADAPTERS:
6883285ea10SEliot Blennerhassett 		phr->u.s.num_adapters = adapters.gw_num_adapters;
689719f82d3SEliot Blennerhassett 		break;
690719f82d3SEliot Blennerhassett 	case HPI_SUBSYS_CREATE_ADAPTER:
691719f82d3SEliot Blennerhassett 		break;
692719f82d3SEliot Blennerhassett 	default:
693719f82d3SEliot Blennerhassett 		phr->error = HPI_ERROR_INVALID_FUNC;
694719f82d3SEliot Blennerhassett 		break;
695719f82d3SEliot Blennerhassett 	}
696719f82d3SEliot Blennerhassett }
697719f82d3SEliot Blennerhassett 
HPI_COMMON(struct hpi_message * phm,struct hpi_response * phr)698719f82d3SEliot Blennerhassett void HPI_COMMON(struct hpi_message *phm, struct hpi_response *phr)
699719f82d3SEliot Blennerhassett {
700719f82d3SEliot Blennerhassett 	switch (phm->type) {
70182b5774fSEliot Blennerhassett 	case HPI_TYPE_REQUEST:
702719f82d3SEliot Blennerhassett 		switch (phm->object) {
703719f82d3SEliot Blennerhassett 		case HPI_OBJ_SUBSYSTEM:
704719f82d3SEliot Blennerhassett 			subsys_message(phm, phr);
705719f82d3SEliot Blennerhassett 			break;
706719f82d3SEliot Blennerhassett 		}
707719f82d3SEliot Blennerhassett 		break;
708719f82d3SEliot Blennerhassett 
709719f82d3SEliot Blennerhassett 	default:
710719f82d3SEliot Blennerhassett 		phr->error = HPI_ERROR_INVALID_TYPE;
711719f82d3SEliot Blennerhassett 		break;
712719f82d3SEliot Blennerhassett 	}
713719f82d3SEliot Blennerhassett }
714