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