linux/sound/pci/asihpi/hpicmn.c
<<
>>
Prefs
   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
  31struct 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
  37static 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**/
  44u16 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
  56u16 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
  78unlock:
  79        hpios_alistlock_un_lock(&adapters);
  80        return retval;
  81}
  82
  83void 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*/
  97struct 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**/
 128static 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*/
 139static 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
 175static 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*/
 225static 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 */
 252short 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
 274struct pad_ofs_size {
 275        unsigned int offset;
 276        unsigned int field_size;
 277};
 278
 279static 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 */
 289short 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
 496Only update if no error.
 497Volume and Level return the limited values in the response, so use these
 498Multiplexer does so use sent values
 499*/
 500void 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
 568struct 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
 591void 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
 601static 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
 628void 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