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