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 *pI = p_cache->p_info[control_index]; 280 if (!*pI) { 281 HPI_DEBUG_LOG(VERBOSE, "Uncached Control %d\n", 282 control_index); 283 return 0; 284 } else { 285 HPI_DEBUG_LOG(VERBOSE, "find_control() type %d\n", 286 (*pI)->control_type); 287 } 288 return 1; 289 } 290 291 /* allow unified treatment of several string fields within struct */ 292 #define HPICMN_PAD_OFS_AND_SIZE(m) {\ 293 offsetof(struct hpi_control_cache_pad, m), \ 294 sizeof(((struct hpi_control_cache_pad *)(NULL))->m) } 295 296 struct pad_ofs_size { 297 unsigned int offset; 298 unsigned int field_size; 299 }; 300 301 static const struct pad_ofs_size pad_desc[] = { 302 HPICMN_PAD_OFS_AND_SIZE(c_channel), /* HPI_PAD_CHANNEL_NAME */ 303 HPICMN_PAD_OFS_AND_SIZE(c_artist), /* HPI_PAD_ARTIST */ 304 HPICMN_PAD_OFS_AND_SIZE(c_title), /* HPI_PAD_TITLE */ 305 HPICMN_PAD_OFS_AND_SIZE(c_comment), /* HPI_PAD_COMMENT */ 306 }; 307 308 /** CheckControlCache checks the cache and fills the struct hpi_response 309 * accordingly. It returns one if a cache hit occurred, zero otherwise. 310 */ 311 short hpi_check_control_cache_single(struct hpi_control_cache_single *pC, 312 struct hpi_message *phm, struct hpi_response *phr) 313 { 314 size_t response_size; 315 short found = 1; 316 317 /* set the default response size */ 318 response_size = 319 sizeof(struct hpi_response_header) + 320 sizeof(struct hpi_control_res); 321 322 switch (pC->u.i.control_type) { 323 324 case HPI_CONTROL_METER: 325 if (phm->u.c.attribute == HPI_METER_PEAK) { 326 phr->u.c.an_log_value[0] = pC->u.meter.an_log_peak[0]; 327 phr->u.c.an_log_value[1] = pC->u.meter.an_log_peak[1]; 328 } else if (phm->u.c.attribute == HPI_METER_RMS) { 329 if (pC->u.meter.an_logRMS[0] == 330 HPI_CACHE_INVALID_SHORT) { 331 phr->error = 332 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; 333 phr->u.c.an_log_value[0] = HPI_METER_MINIMUM; 334 phr->u.c.an_log_value[1] = HPI_METER_MINIMUM; 335 } else { 336 phr->u.c.an_log_value[0] = 337 pC->u.meter.an_logRMS[0]; 338 phr->u.c.an_log_value[1] = 339 pC->u.meter.an_logRMS[1]; 340 } 341 } else 342 found = 0; 343 break; 344 case HPI_CONTROL_VOLUME: 345 if (phm->u.c.attribute == HPI_VOLUME_GAIN) { 346 phr->u.c.an_log_value[0] = pC->u.vol.an_log[0]; 347 phr->u.c.an_log_value[1] = pC->u.vol.an_log[1]; 348 } else if (phm->u.c.attribute == HPI_VOLUME_MUTE) { 349 if (pC->u.vol.flags & HPI_VOLUME_FLAG_HAS_MUTE) { 350 if (pC->u.vol.flags & HPI_VOLUME_FLAG_MUTED) 351 phr->u.c.param1 = 352 HPI_BITMASK_ALL_CHANNELS; 353 else 354 phr->u.c.param1 = 0; 355 } else { 356 phr->error = 357 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; 358 phr->u.c.param1 = 0; 359 } 360 } else { 361 found = 0; 362 } 363 break; 364 case HPI_CONTROL_MULTIPLEXER: 365 if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) { 366 phr->u.c.param1 = pC->u.mux.source_node_type; 367 phr->u.c.param2 = pC->u.mux.source_node_index; 368 } else { 369 found = 0; 370 } 371 break; 372 case HPI_CONTROL_CHANNEL_MODE: 373 if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE) 374 phr->u.c.param1 = pC->u.mode.mode; 375 else 376 found = 0; 377 break; 378 case HPI_CONTROL_LEVEL: 379 if (phm->u.c.attribute == HPI_LEVEL_GAIN) { 380 phr->u.c.an_log_value[0] = pC->u.level.an_log[0]; 381 phr->u.c.an_log_value[1] = pC->u.level.an_log[1]; 382 } else 383 found = 0; 384 break; 385 case HPI_CONTROL_TUNER: 386 if (phm->u.c.attribute == HPI_TUNER_FREQ) 387 phr->u.c.param1 = pC->u.tuner.freq_ink_hz; 388 else if (phm->u.c.attribute == HPI_TUNER_BAND) 389 phr->u.c.param1 = pC->u.tuner.band; 390 else if (phm->u.c.attribute == HPI_TUNER_LEVEL_AVG) 391 if (pC->u.tuner.s_level_avg == 392 HPI_CACHE_INVALID_SHORT) { 393 phr->u.cu.tuner.s_level = 0; 394 phr->error = 395 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; 396 } else 397 phr->u.cu.tuner.s_level = 398 pC->u.tuner.s_level_avg; 399 else 400 found = 0; 401 break; 402 case HPI_CONTROL_AESEBU_RECEIVER: 403 if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS) 404 phr->u.c.param1 = pC->u.aes3rx.error_status; 405 else if (phm->u.c.attribute == HPI_AESEBURX_FORMAT) 406 phr->u.c.param1 = pC->u.aes3rx.format; 407 else 408 found = 0; 409 break; 410 case HPI_CONTROL_AESEBU_TRANSMITTER: 411 if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT) 412 phr->u.c.param1 = pC->u.aes3tx.format; 413 else 414 found = 0; 415 break; 416 case HPI_CONTROL_TONEDETECTOR: 417 if (phm->u.c.attribute == HPI_TONEDETECTOR_STATE) 418 phr->u.c.param1 = pC->u.tone.state; 419 else 420 found = 0; 421 break; 422 case HPI_CONTROL_SILENCEDETECTOR: 423 if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) { 424 phr->u.c.param1 = pC->u.silence.state; 425 } else 426 found = 0; 427 break; 428 case HPI_CONTROL_MICROPHONE: 429 if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER) 430 phr->u.c.param1 = pC->u.microphone.phantom_state; 431 else 432 found = 0; 433 break; 434 case HPI_CONTROL_SAMPLECLOCK: 435 if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE) 436 phr->u.c.param1 = pC->u.clk.source; 437 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) { 438 if (pC->u.clk.source_index == 439 HPI_CACHE_INVALID_UINT16) { 440 phr->u.c.param1 = 0; 441 phr->error = 442 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; 443 } else 444 phr->u.c.param1 = pC->u.clk.source_index; 445 } else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE) 446 phr->u.c.param1 = pC->u.clk.sample_rate; 447 else 448 found = 0; 449 break; 450 case HPI_CONTROL_PAD:{ 451 struct hpi_control_cache_pad *p_pad; 452 p_pad = (struct hpi_control_cache_pad *)pC; 453 454 if (!(p_pad->field_valid_flags & (1 << 455 HPI_CTL_ATTR_INDEX(phm->u.c. 456 attribute)))) { 457 phr->error = 458 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; 459 break; 460 } 461 462 if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID) 463 phr->u.c.param1 = p_pad->pI; 464 else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE) 465 phr->u.c.param1 = p_pad->pTY; 466 else { 467 unsigned int index = 468 HPI_CTL_ATTR_INDEX(phm->u.c. 469 attribute) - 1; 470 unsigned int offset = phm->u.c.param1; 471 unsigned int pad_string_len, field_size; 472 char *pad_string; 473 unsigned int tocopy; 474 475 if (index > ARRAY_SIZE(pad_desc) - 1) { 476 phr->error = 477 HPI_ERROR_INVALID_CONTROL_ATTRIBUTE; 478 break; 479 } 480 481 pad_string = 482 ((char *)p_pad) + 483 pad_desc[index].offset; 484 field_size = pad_desc[index].field_size; 485 /* Ensure null terminator */ 486 pad_string[field_size - 1] = 0; 487 488 pad_string_len = strlen(pad_string) + 1; 489 490 if (offset > pad_string_len) { 491 phr->error = 492 HPI_ERROR_INVALID_CONTROL_VALUE; 493 break; 494 } 495 496 tocopy = pad_string_len - offset; 497 if (tocopy > sizeof(phr->u.cu.chars8.sz_data)) 498 tocopy = sizeof(phr->u.cu.chars8. 499 sz_data); 500 501 memcpy(phr->u.cu.chars8.sz_data, 502 &pad_string[offset], tocopy); 503 504 phr->u.cu.chars8.remaining_chars = 505 pad_string_len - offset - tocopy; 506 } 507 } 508 break; 509 default: 510 found = 0; 511 break; 512 } 513 514 HPI_DEBUG_LOG(VERBOSE, "%s Adap %d, Ctl %d, Type %d, Attr %d\n", 515 found ? "Cached" : "Uncached", phm->adapter_index, 516 pC->u.i.control_index, pC->u.i.control_type, 517 phm->u.c.attribute); 518 519 if (found) { 520 phr->size = (u16)response_size; 521 phr->type = HPI_TYPE_RESPONSE; 522 phr->object = phm->object; 523 phr->function = phm->function; 524 } 525 526 return found; 527 } 528 529 short hpi_check_control_cache(struct hpi_control_cache *p_cache, 530 struct hpi_message *phm, struct hpi_response *phr) 531 { 532 struct hpi_control_cache_info *pI; 533 534 if (!find_control(phm->obj_index, p_cache, &pI)) { 535 HPI_DEBUG_LOG(VERBOSE, 536 "HPICMN find_control() failed for adap %d\n", 537 phm->adapter_index); 538 return 0; 539 } 540 541 phr->error = 0; 542 phr->specific_error = 0; 543 phr->version = 0; 544 545 return hpi_check_control_cache_single((struct hpi_control_cache_single 546 *)pI, phm, phr); 547 } 548 549 /** Updates the cache with Set values. 550 551 Only update if no error. 552 Volume and Level return the limited values in the response, so use these 553 Multiplexer does so use sent values 554 */ 555 void hpi_cmn_control_cache_sync_to_msg_single(struct hpi_control_cache_single 556 *pC, struct hpi_message *phm, struct hpi_response *phr) 557 { 558 switch (pC->u.i.control_type) { 559 case HPI_CONTROL_VOLUME: 560 if (phm->u.c.attribute == HPI_VOLUME_GAIN) { 561 pC->u.vol.an_log[0] = phr->u.c.an_log_value[0]; 562 pC->u.vol.an_log[1] = phr->u.c.an_log_value[1]; 563 } else if (phm->u.c.attribute == HPI_VOLUME_MUTE) { 564 if (phm->u.c.param1) 565 pC->u.vol.flags |= HPI_VOLUME_FLAG_MUTED; 566 else 567 pC->u.vol.flags &= ~HPI_VOLUME_FLAG_MUTED; 568 } 569 break; 570 case HPI_CONTROL_MULTIPLEXER: 571 /* mux does not return its setting on Set command. */ 572 if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) { 573 pC->u.mux.source_node_type = (u16)phm->u.c.param1; 574 pC->u.mux.source_node_index = (u16)phm->u.c.param2; 575 } 576 break; 577 case HPI_CONTROL_CHANNEL_MODE: 578 /* mode does not return its setting on Set command. */ 579 if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE) 580 pC->u.mode.mode = (u16)phm->u.c.param1; 581 break; 582 case HPI_CONTROL_LEVEL: 583 if (phm->u.c.attribute == HPI_LEVEL_GAIN) { 584 pC->u.vol.an_log[0] = phr->u.c.an_log_value[0]; 585 pC->u.vol.an_log[1] = phr->u.c.an_log_value[1]; 586 } 587 break; 588 case HPI_CONTROL_MICROPHONE: 589 if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER) 590 pC->u.microphone.phantom_state = (u16)phm->u.c.param1; 591 break; 592 case HPI_CONTROL_AESEBU_TRANSMITTER: 593 if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT) 594 pC->u.aes3tx.format = phm->u.c.param1; 595 break; 596 case HPI_CONTROL_AESEBU_RECEIVER: 597 if (phm->u.c.attribute == HPI_AESEBURX_FORMAT) 598 pC->u.aes3rx.format = phm->u.c.param1; 599 break; 600 case HPI_CONTROL_SAMPLECLOCK: 601 if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE) 602 pC->u.clk.source = (u16)phm->u.c.param1; 603 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) 604 pC->u.clk.source_index = (u16)phm->u.c.param1; 605 else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE) 606 pC->u.clk.sample_rate = phm->u.c.param1; 607 break; 608 default: 609 break; 610 } 611 } 612 613 void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *p_cache, 614 struct hpi_message *phm, struct hpi_response *phr) 615 { 616 struct hpi_control_cache_single *pC; 617 struct hpi_control_cache_info *pI; 618 619 if (phr->error) 620 return; 621 622 if (!find_control(phm->obj_index, p_cache, &pI)) { 623 HPI_DEBUG_LOG(VERBOSE, 624 "HPICMN find_control() failed for adap %d\n", 625 phm->adapter_index); 626 return; 627 } 628 629 /* pC is the default cached control strucure. 630 May be cast to something else in the following switch statement. 631 */ 632 pC = (struct hpi_control_cache_single *)pI; 633 634 hpi_cmn_control_cache_sync_to_msg_single(pC, phm, phr); 635 } 636 637 /** Allocate control cache. 638 639 \return Cache pointer, or NULL if allocation fails. 640 */ 641 struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count, 642 const u32 size_in_bytes, u8 *p_dsp_control_buffer) 643 { 644 struct hpi_control_cache *p_cache = 645 kmalloc(sizeof(*p_cache), GFP_KERNEL); 646 if (!p_cache) 647 return NULL; 648 649 p_cache->p_info = 650 kcalloc(control_count, sizeof(*p_cache->p_info), GFP_KERNEL); 651 if (!p_cache->p_info) { 652 kfree(p_cache); 653 return NULL; 654 } 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 if (p_cache) { 666 kfree(p_cache->p_info); 667 kfree(p_cache); 668 } 669 } 670 671 static void subsys_message(struct hpi_message *phm, struct hpi_response *phr) 672 { 673 hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function, 0); 674 675 switch (phm->function) { 676 case HPI_SUBSYS_OPEN: 677 case HPI_SUBSYS_CLOSE: 678 case HPI_SUBSYS_DRIVER_UNLOAD: 679 break; 680 case HPI_SUBSYS_DRIVER_LOAD: 681 wipe_adapter_list(); 682 hpios_alistlock_init(&adapters); 683 break; 684 case HPI_SUBSYS_GET_ADAPTER: 685 subsys_get_adapter(phm, phr); 686 break; 687 case HPI_SUBSYS_GET_NUM_ADAPTERS: 688 phr->u.s.num_adapters = adapters.gw_num_adapters; 689 break; 690 case HPI_SUBSYS_CREATE_ADAPTER: 691 break; 692 default: 693 phr->error = HPI_ERROR_INVALID_FUNC; 694 break; 695 } 696 } 697 698 void HPI_COMMON(struct hpi_message *phm, struct hpi_response *phr) 699 { 700 switch (phm->type) { 701 case HPI_TYPE_REQUEST: 702 switch (phm->object) { 703 case HPI_OBJ_SUBSYSTEM: 704 subsys_message(phm, phr); 705 break; 706 } 707 break; 708 709 default: 710 phr->error = HPI_ERROR_INVALID_TYPE; 711 break; 712 } 713 } 714