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