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