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