xref: /openbmc/linux/sound/pci/asihpi/hpicmn.c (revision baa7eb025ab14f3cba2e35c0a8648f9c9f01d24f)
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 "hpicmn.h"
30 
31 struct hpi_adapters_list {
32 	struct hpios_spinlock list_lock;
33 	struct hpi_adapter_obj adapter[HPI_MAX_ADAPTERS];
34 	u16 gw_num_adapters;
35 };
36 
37 static struct hpi_adapters_list adapters;
38 
39 /**
40 * Given an HPI Message that was sent out and a response that was received,
41 * validate that the response has the correct fields filled in,
42 * i.e ObjectType, Function etc
43 **/
44 u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr)
45 {
46 	u16 error = 0;
47 
48 	if ((phr->type != HPI_TYPE_RESPONSE)
49 		|| (phr->object != phm->object)
50 		|| (phr->function != phm->function))
51 		error = HPI_ERROR_INVALID_RESPONSE;
52 
53 	return error;
54 }
55 
56 u16 hpi_add_adapter(struct hpi_adapter_obj *pao)
57 {
58 	u16 retval = 0;
59 	/*HPI_ASSERT(pao->wAdapterType); */
60 
61 	hpios_alistlock_lock(&adapters);
62 
63 	if (pao->index >= HPI_MAX_ADAPTERS) {
64 		retval = HPI_ERROR_BAD_ADAPTER_NUMBER;
65 		goto unlock;
66 	}
67 
68 	if (adapters.adapter[pao->index].adapter_type) {
69 		{
70 			retval = HPI_DUPLICATE_ADAPTER_NUMBER;
71 			goto unlock;
72 		}
73 	}
74 	adapters.adapter[pao->index] = *pao;
75 	hpios_dsplock_init(&adapters.adapter[pao->index]);
76 	adapters.gw_num_adapters++;
77 
78 unlock:
79 	hpios_alistlock_un_lock(&adapters);
80 	return retval;
81 }
82 
83 void hpi_delete_adapter(struct hpi_adapter_obj *pao)
84 {
85 	memset(pao, 0, sizeof(struct hpi_adapter_obj));
86 
87 	hpios_alistlock_lock(&adapters);
88 	adapters.gw_num_adapters--;	/* dec the number of adapters */
89 	hpios_alistlock_un_lock(&adapters);
90 }
91 
92 /**
93 * FindAdapter returns a pointer to the struct hpi_adapter_obj with
94 * index wAdapterIndex in an HPI_ADAPTERS_LIST structure.
95 *
96 */
97 struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index)
98 {
99 	struct hpi_adapter_obj *pao = NULL;
100 
101 	if (adapter_index >= HPI_MAX_ADAPTERS) {
102 		HPI_DEBUG_LOG(VERBOSE, "find_adapter invalid index %d ",
103 			adapter_index);
104 		return NULL;
105 	}
106 
107 	pao = &adapters.adapter[adapter_index];
108 	if (pao->adapter_type != 0) {
109 		/*
110 		   HPI_DEBUG_LOG(VERBOSE, "Found adapter index %d\n",
111 		   wAdapterIndex);
112 		 */
113 		return pao;
114 	} else {
115 		/*
116 		   HPI_DEBUG_LOG(VERBOSE, "No adapter index %d\n",
117 		   wAdapterIndex);
118 		 */
119 		return NULL;
120 	}
121 }
122 
123 /**
124 *
125 * wipe an HPI_ADAPTERS_LIST structure.
126 *
127 **/
128 static void wipe_adapter_list(void
129 	)
130 {
131 	memset(&adapters, 0, sizeof(adapters));
132 }
133 
134 /**
135 * SubSysGetAdapters fills awAdapterList in an struct hpi_response structure
136 * with all adapters in the given HPI_ADAPTERS_LIST.
137 *
138 */
139 static void subsys_get_adapters(struct hpi_response *phr)
140 {
141 	/* fill in the response adapter array with the position */
142 	/* identified by the adapter number/index of the adapters in */
143 	/* this HPI */
144 	/* i.e. if we have an A120 with it's jumper set to */
145 	/* Adapter Number 2 then put an Adapter type A120 in the */
146 	/* array in position 1 */
147 	/* NOTE: AdapterNumber is 1..N, Index is 0..N-1 */
148 
149 	/* input:  NONE */
150 	/* output: wNumAdapters */
151 	/*                 awAdapter[] */
152 	/* */
153 
154 	short i;
155 	struct hpi_adapter_obj *pao = NULL;
156 
157 	HPI_DEBUG_LOG(VERBOSE, "subsys_get_adapters\n");
158 
159 	/* for each adapter, place it's type in the position of the array */
160 	/* corresponding to it's adapter number */
161 	for (i = 0; i < adapters.gw_num_adapters; i++) {
162 		pao = &adapters.adapter[i];
163 		if (phr->u.s.aw_adapter_list[pao->index] != 0) {
164 			phr->error = HPI_DUPLICATE_ADAPTER_NUMBER;
165 			phr->specific_error = pao->index;
166 			return;
167 		}
168 		phr->u.s.aw_adapter_list[pao->index] = pao->adapter_type;
169 	}
170 
171 	phr->u.s.num_adapters = adapters.gw_num_adapters;
172 	phr->error = 0;	/* the function completed OK; */
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 	if ((!pC->init) && (pC->p_cache != NULL) && (pC->control_count)
182 		&& (pC->cache_size_in_bytes)
183 		) {
184 		u32 *p_master_cache;
185 		pC->init = 1;
186 
187 		p_master_cache = (u32 *)pC->p_cache;
188 		HPI_DEBUG_LOG(VERBOSE, "check %d controls\n",
189 			pC->control_count);
190 		for (i = 0; i < pC->control_count; i++) {
191 			struct hpi_control_cache_info *info =
192 				(struct hpi_control_cache_info *)
193 				p_master_cache;
194 
195 			if (info->control_type) {
196 				pC->p_info[i] = info;
197 				cached++;
198 			} else
199 				pC->p_info[i] = NULL;
200 
201 			if (info->size_in32bit_words)
202 				p_master_cache += info->size_in32bit_words;
203 			else
204 				p_master_cache +=
205 					sizeof(struct
206 					hpi_control_cache_single) /
207 					sizeof(u32);
208 
209 			HPI_DEBUG_LOG(VERBOSE,
210 				"cached %d, pinfo %p index %d type %d\n",
211 				cached, pC->p_info[i], info->control_index,
212 				info->control_type);
213 		}
214 		/*
215 		   We didn't find anything to cache, so try again later !
216 		 */
217 		if (!cached)
218 			pC->init = 0;
219 	}
220 	return pC->init;
221 }
222 
223 /** Find a control.
224 */
225 static short find_control(struct hpi_message *phm,
226 	struct hpi_control_cache *p_cache, struct hpi_control_cache_info **pI,
227 	u16 *pw_control_index)
228 {
229 	*pw_control_index = phm->obj_index;
230 
231 	if (!control_cache_alloc_check(p_cache)) {
232 		HPI_DEBUG_LOG(VERBOSE,
233 			"control_cache_alloc_check() failed. adap%d ci%d\n",
234 			phm->adapter_index, *pw_control_index);
235 		return 0;
236 	}
237 
238 	*pI = p_cache->p_info[*pw_control_index];
239 	if (!*pI) {
240 		HPI_DEBUG_LOG(VERBOSE, "uncached adap %d, control %d\n",
241 			phm->adapter_index, *pw_control_index);
242 		return 0;
243 	} else {
244 		HPI_DEBUG_LOG(VERBOSE, "find_control() type %d\n",
245 			(*pI)->control_type);
246 	}
247 	return 1;
248 }
249 
250 /** Used by the kernel driver to figure out if a buffer needs mapping.
251  */
252 short hpi_check_buffer_mapping(struct hpi_control_cache *p_cache,
253 	struct hpi_message *phm, void **p, unsigned int *pN)
254 {
255 	*pN = 0;
256 	*p = NULL;
257 	if ((phm->function == HPI_CONTROL_GET_STATE)
258 		&& (phm->object == HPI_OBJ_CONTROLEX)
259 		) {
260 		u16 control_index;
261 		struct hpi_control_cache_info *pI;
262 
263 		if (!find_control(phm, p_cache, &pI, &control_index))
264 			return 0;
265 	}
266 	return 0;
267 }
268 
269 /* allow unified treatment of several string fields within struct */
270 #define HPICMN_PAD_OFS_AND_SIZE(m)  {\
271 	offsetof(struct hpi_control_cache_pad, m), \
272 	sizeof(((struct hpi_control_cache_pad *)(NULL))->m) }
273 
274 struct pad_ofs_size {
275 	unsigned int offset;
276 	unsigned int field_size;
277 };
278 
279 static struct pad_ofs_size pad_desc[] = {
280 	HPICMN_PAD_OFS_AND_SIZE(c_channel),	/* HPI_PAD_CHANNEL_NAME */
281 	HPICMN_PAD_OFS_AND_SIZE(c_artist),	/* HPI_PAD_ARTIST */
282 	HPICMN_PAD_OFS_AND_SIZE(c_title),	/* HPI_PAD_TITLE */
283 	HPICMN_PAD_OFS_AND_SIZE(c_comment),	/* HPI_PAD_COMMENT */
284 };
285 
286 /** CheckControlCache checks the cache and fills the struct hpi_response
287  * accordingly. It returns one if a cache hit occurred, zero otherwise.
288  */
289 short hpi_check_control_cache(struct hpi_control_cache *p_cache,
290 	struct hpi_message *phm, struct hpi_response *phr)
291 {
292 	short found = 1;
293 	u16 control_index;
294 	struct hpi_control_cache_info *pI;
295 	struct hpi_control_cache_single *pC;
296 	struct hpi_control_cache_pad *p_pad;
297 
298 	if (!find_control(phm, p_cache, &pI, &control_index))
299 		return 0;
300 
301 	phr->error = 0;
302 
303 	/* pC is the default cached control strucure. May be cast to
304 	   something else in the following switch statement.
305 	 */
306 	pC = (struct hpi_control_cache_single *)pI;
307 	p_pad = (struct hpi_control_cache_pad *)pI;
308 
309 	switch (pI->control_type) {
310 
311 	case HPI_CONTROL_METER:
312 		if (phm->u.c.attribute == HPI_METER_PEAK) {
313 			phr->u.c.an_log_value[0] = pC->u.p.an_log_peak[0];
314 			phr->u.c.an_log_value[1] = pC->u.p.an_log_peak[1];
315 		} else if (phm->u.c.attribute == HPI_METER_RMS) {
316 			phr->u.c.an_log_value[0] = pC->u.p.an_logRMS[0];
317 			phr->u.c.an_log_value[1] = pC->u.p.an_logRMS[1];
318 		} else
319 			found = 0;
320 		break;
321 	case HPI_CONTROL_VOLUME:
322 		if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
323 			phr->u.c.an_log_value[0] = pC->u.v.an_log[0];
324 			phr->u.c.an_log_value[1] = pC->u.v.an_log[1];
325 		} else
326 			found = 0;
327 		break;
328 	case HPI_CONTROL_MULTIPLEXER:
329 		if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
330 			phr->u.c.param1 = pC->u.x.source_node_type;
331 			phr->u.c.param2 = pC->u.x.source_node_index;
332 		} else {
333 			found = 0;
334 		}
335 		break;
336 	case HPI_CONTROL_CHANNEL_MODE:
337 		if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
338 			phr->u.c.param1 = pC->u.m.mode;
339 		else
340 			found = 0;
341 		break;
342 	case HPI_CONTROL_LEVEL:
343 		if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
344 			phr->u.c.an_log_value[0] = pC->u.l.an_log[0];
345 			phr->u.c.an_log_value[1] = pC->u.l.an_log[1];
346 		} else
347 			found = 0;
348 		break;
349 	case HPI_CONTROL_TUNER:
350 		if (phm->u.c.attribute == HPI_TUNER_FREQ)
351 			phr->u.c.param1 = pC->u.t.freq_ink_hz;
352 		else if (phm->u.c.attribute == HPI_TUNER_BAND)
353 			phr->u.c.param1 = pC->u.t.band;
354 		else if ((phm->u.c.attribute == HPI_TUNER_LEVEL)
355 			&& (phm->u.c.param1 == HPI_TUNER_LEVEL_AVERAGE))
356 			if (pC->u.t.level == HPI_ERROR_ILLEGAL_CACHE_VALUE) {
357 				phr->u.c.param1 = 0;
358 				phr->error =
359 					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
360 			} else
361 				phr->u.c.param1 = pC->u.t.level;
362 		else
363 			found = 0;
364 		break;
365 	case HPI_CONTROL_AESEBU_RECEIVER:
366 		if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS)
367 			phr->u.c.param1 = pC->u.aes3rx.error_status;
368 		else if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
369 			phr->u.c.param1 = pC->u.aes3rx.source;
370 		else
371 			found = 0;
372 		break;
373 	case HPI_CONTROL_AESEBU_TRANSMITTER:
374 		if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
375 			phr->u.c.param1 = pC->u.aes3tx.format;
376 		else
377 			found = 0;
378 		break;
379 	case HPI_CONTROL_TONEDETECTOR:
380 		if (phm->u.c.attribute == HPI_TONEDETECTOR_STATE)
381 			phr->u.c.param1 = pC->u.tone.state;
382 		else
383 			found = 0;
384 		break;
385 	case HPI_CONTROL_SILENCEDETECTOR:
386 		if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) {
387 			phr->u.c.param1 = pC->u.silence.state;
388 			phr->u.c.param2 = pC->u.silence.count;
389 		} else
390 			found = 0;
391 		break;
392 	case HPI_CONTROL_MICROPHONE:
393 		if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
394 			phr->u.c.param1 = pC->u.phantom_power.state;
395 		else
396 			found = 0;
397 		break;
398 	case HPI_CONTROL_SAMPLECLOCK:
399 		if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
400 			phr->u.c.param1 = pC->u.clk.source;
401 		else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) {
402 			if (pC->u.clk.source_index ==
403 				HPI_ERROR_ILLEGAL_CACHE_VALUE) {
404 				phr->u.c.param1 = 0;
405 				phr->error =
406 					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
407 			} else
408 				phr->u.c.param1 = pC->u.clk.source_index;
409 		} else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
410 			phr->u.c.param1 = pC->u.clk.sample_rate;
411 		else
412 			found = 0;
413 		break;
414 	case HPI_CONTROL_PAD:
415 
416 		if (!(p_pad->field_valid_flags & (1 <<
417 					HPI_CTL_ATTR_INDEX(phm->u.c.
418 						attribute)))) {
419 			phr->error = HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
420 			break;
421 		}
422 
423 		if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID)
424 			phr->u.c.param1 = p_pad->pI;
425 		else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE)
426 			phr->u.c.param1 = p_pad->pTY;
427 		else {
428 			unsigned int index =
429 				HPI_CTL_ATTR_INDEX(phm->u.c.attribute) - 1;
430 			unsigned int offset = phm->u.c.param1;
431 			unsigned int pad_string_len, field_size;
432 			char *pad_string;
433 			unsigned int tocopy;
434 
435 			HPI_DEBUG_LOG(VERBOSE, "PADS HPI_PADS_ %d\n",
436 				phm->u.c.attribute);
437 
438 			if (index > ARRAY_SIZE(pad_desc) - 1) {
439 				phr->error =
440 					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
441 				break;
442 			}
443 
444 			pad_string = ((char *)p_pad) + pad_desc[index].offset;
445 			field_size = pad_desc[index].field_size;
446 			/* Ensure null terminator */
447 			pad_string[field_size - 1] = 0;
448 
449 			pad_string_len = strlen(pad_string) + 1;
450 
451 			if (offset > pad_string_len) {
452 				phr->error = HPI_ERROR_INVALID_CONTROL_VALUE;
453 				break;
454 			}
455 
456 			tocopy = pad_string_len - offset;
457 			if (tocopy > sizeof(phr->u.cu.chars8.sz_data))
458 				tocopy = sizeof(phr->u.cu.chars8.sz_data);
459 
460 			HPI_DEBUG_LOG(VERBOSE,
461 				"PADS memcpy(%d), offset %d \n", tocopy,
462 				offset);
463 			memcpy(phr->u.cu.chars8.sz_data, &pad_string[offset],
464 				tocopy);
465 
466 			phr->u.cu.chars8.remaining_chars =
467 				pad_string_len - offset - tocopy;
468 		}
469 		break;
470 	default:
471 		found = 0;
472 		break;
473 	}
474 
475 	if (found)
476 		HPI_DEBUG_LOG(VERBOSE,
477 			"cached adap %d, ctl %d, type %d, attr %d\n",
478 			phm->adapter_index, pI->control_index,
479 			pI->control_type, phm->u.c.attribute);
480 	else
481 		HPI_DEBUG_LOG(VERBOSE,
482 			"uncached adap %d, ctl %d, ctl type %d\n",
483 			phm->adapter_index, pI->control_index,
484 			pI->control_type);
485 
486 	if (found)
487 		phr->size =
488 			sizeof(struct hpi_response_header) +
489 			sizeof(struct hpi_control_res);
490 
491 	return found;
492 }
493 
494 /** Updates the cache with Set values.
495 
496 Only update if no error.
497 Volume and Level return the limited values in the response, so use these
498 Multiplexer does so use sent values
499 */
500 void hpi_sync_control_cache(struct hpi_control_cache *p_cache,
501 	struct hpi_message *phm, struct hpi_response *phr)
502 {
503 	u16 control_index;
504 	struct hpi_control_cache_single *pC;
505 	struct hpi_control_cache_info *pI;
506 
507 	if (phr->error)
508 		return;
509 
510 	if (!find_control(phm, p_cache, &pI, &control_index))
511 		return;
512 
513 	/* pC is the default cached control strucure.
514 	   May be cast to something else in the following switch statement.
515 	 */
516 	pC = (struct hpi_control_cache_single *)pI;
517 
518 	switch (pI->control_type) {
519 	case HPI_CONTROL_VOLUME:
520 		if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
521 			pC->u.v.an_log[0] = phr->u.c.an_log_value[0];
522 			pC->u.v.an_log[1] = phr->u.c.an_log_value[1];
523 		}
524 		break;
525 	case HPI_CONTROL_MULTIPLEXER:
526 		/* mux does not return its setting on Set command. */
527 		if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
528 			pC->u.x.source_node_type = (u16)phm->u.c.param1;
529 			pC->u.x.source_node_index = (u16)phm->u.c.param2;
530 		}
531 		break;
532 	case HPI_CONTROL_CHANNEL_MODE:
533 		/* mode does not return its setting on Set command. */
534 		if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
535 			pC->u.m.mode = (u16)phm->u.c.param1;
536 		break;
537 	case HPI_CONTROL_LEVEL:
538 		if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
539 			pC->u.v.an_log[0] = phr->u.c.an_log_value[0];
540 			pC->u.v.an_log[1] = phr->u.c.an_log_value[1];
541 		}
542 		break;
543 	case HPI_CONTROL_MICROPHONE:
544 		if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
545 			pC->u.phantom_power.state = (u16)phm->u.c.param1;
546 		break;
547 	case HPI_CONTROL_AESEBU_TRANSMITTER:
548 		if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
549 			pC->u.aes3tx.format = phm->u.c.param1;
550 		break;
551 	case HPI_CONTROL_AESEBU_RECEIVER:
552 		if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
553 			pC->u.aes3rx.source = phm->u.c.param1;
554 		break;
555 	case HPI_CONTROL_SAMPLECLOCK:
556 		if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
557 			pC->u.clk.source = (u16)phm->u.c.param1;
558 		else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX)
559 			pC->u.clk.source_index = (u16)phm->u.c.param1;
560 		else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
561 			pC->u.clk.sample_rate = phm->u.c.param1;
562 		break;
563 	default:
564 		break;
565 	}
566 }
567 
568 struct hpi_control_cache *hpi_alloc_control_cache(const u32
569 	number_of_controls, const u32 size_in_bytes,
570 	struct hpi_control_cache_info *pDSP_control_buffer)
571 {
572 	struct hpi_control_cache *p_cache =
573 		kmalloc(sizeof(*p_cache), GFP_KERNEL);
574 	if (!p_cache)
575 		return NULL;
576 	p_cache->p_info =
577 		kmalloc(sizeof(*p_cache->p_info) * number_of_controls,
578 			GFP_KERNEL);
579 	if (!p_cache->p_info) {
580 		kfree(p_cache);
581 		return NULL;
582 	}
583 	p_cache->cache_size_in_bytes = size_in_bytes;
584 	p_cache->control_count = number_of_controls;
585 	p_cache->p_cache =
586 		(struct hpi_control_cache_single *)pDSP_control_buffer;
587 	p_cache->init = 0;
588 	return p_cache;
589 }
590 
591 void hpi_free_control_cache(struct hpi_control_cache *p_cache)
592 {
593 	if (p_cache->init) {
594 		kfree(p_cache->p_info);
595 		p_cache->p_info = NULL;
596 		p_cache->init = 0;
597 		kfree(p_cache);
598 	}
599 }
600 
601 static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
602 {
603 
604 	switch (phm->function) {
605 	case HPI_SUBSYS_OPEN:
606 	case HPI_SUBSYS_CLOSE:
607 	case HPI_SUBSYS_DRIVER_UNLOAD:
608 		phr->error = 0;
609 		break;
610 	case HPI_SUBSYS_DRIVER_LOAD:
611 		wipe_adapter_list();
612 		hpios_alistlock_init(&adapters);
613 		phr->error = 0;
614 		break;
615 	case HPI_SUBSYS_GET_INFO:
616 		subsys_get_adapters(phr);
617 		break;
618 	case HPI_SUBSYS_CREATE_ADAPTER:
619 	case HPI_SUBSYS_DELETE_ADAPTER:
620 		phr->error = 0;
621 		break;
622 	default:
623 		phr->error = HPI_ERROR_INVALID_FUNC;
624 		break;
625 	}
626 }
627 
628 void HPI_COMMON(struct hpi_message *phm, struct hpi_response *phr)
629 {
630 	switch (phm->type) {
631 	case HPI_TYPE_MESSAGE:
632 		switch (phm->object) {
633 		case HPI_OBJ_SUBSYSTEM:
634 			subsys_message(phm, phr);
635 			break;
636 		}
637 		break;
638 
639 	default:
640 		phr->error = HPI_ERROR_INVALID_TYPE;
641 		break;
642 	}
643 }
644