e0a08f61a34870209050bc7a38f448f7a00adadb
[cascardo/linux.git] / sound / pci / asihpi / hpicmn.c
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 }