Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/pci/asihpi/hpicmn.c
26424 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/******************************************************************************
3
4
AudioScience HPI driver
5
Copyright (C) 1997-2014 AudioScience Inc. <[email protected]>
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
715