333 lines
10 KiB
C
333 lines
10 KiB
C
/*******************************************************************************
|
|
** This file is provided under a dual BSD/GPLv2 license. When using or
|
|
** redistributing this file, you may do so under either license.
|
|
**
|
|
** GPL LICENSE SUMMARY
|
|
**
|
|
** Copyright (c) 2013 Intel Corporation All Rights Reserved
|
|
**
|
|
** This program is free software; you can redistribute it and/or modify it under
|
|
** the terms of version 2 of the GNU General Public License as published by the
|
|
** Free Software Foundation.
|
|
**
|
|
** This program is distributed in the hope that it will be useful, but WITHOUT
|
|
** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
** FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
** details.
|
|
**
|
|
** You should have received a copy of the GNU General Public License along with
|
|
** this program; if not, write to the Free Software Foundation, Inc.,
|
|
** 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
|
|
** The full GNU General Public License is included in this distribution in the
|
|
** file called LICENSE.GPL.
|
|
**
|
|
** BSD LICENSE
|
|
**
|
|
** Copyright (c) 2013 Intel Corporation All Rights Reserved
|
|
**
|
|
** Redistribution and use in source and binary forms, with or without
|
|
** modification, are permitted provided that the following conditions are met:
|
|
**
|
|
** * Redistributions of source code must retain the above copyright notice, this
|
|
** list of conditions and the following disclaimer.
|
|
** * Redistributions in binary form must reproduce the above copyright notice,
|
|
** this list of conditions and the following disclaimer in the documentation
|
|
** and/or other materials provided with the distribution.
|
|
** * Neither the name of Intel Corporation nor the names of its contributors may
|
|
** be used to endorse or promote products derived from this software without
|
|
** specific prior written permission.
|
|
**
|
|
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
|
** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
** POSSIBILITY OF SUCH DAMAGE.
|
|
**
|
|
*******************************************************************************/
|
|
#include "esif.h"
|
|
#include "esif_cpc.h"
|
|
#include "esif_lf_domain.h"
|
|
|
|
#ifdef ESIF_ATTR_OS_WINDOWS
|
|
|
|
/*
|
|
*
|
|
* The Windows banned-API check header must be included after all other headers,
|
|
* or issues can be identified
|
|
* against Windows SDK/DDK included headers which we have no control over.
|
|
*
|
|
*/
|
|
#define _SDL_BANNED_RECOMMENDED
|
|
#include "win\banned.h"
|
|
#endif
|
|
|
|
/* Debug Logging Defintions */
|
|
#define INIT_DEBUG 0
|
|
#define CPC_DEBUG 1
|
|
|
|
#define ESIF_TRACE_DYN_INIT(format, ...) \
|
|
ESIF_TRACE_DYN(ESIF_DEBUG_MOD_CPC, INIT_DEBUG, format, ##__VA_ARGS__)
|
|
#define ESIF_TRACE_DYN_CPC(format, ...) \
|
|
ESIF_TRACE_DYN(ESIF_DEBUG_MOD_CPC, CPC_DEBUG, format, ##__VA_ARGS__)
|
|
|
|
/*
|
|
******************************************************************************
|
|
* PRIVATE
|
|
******************************************************************************
|
|
*/
|
|
|
|
/* Assumes hash table has already been created */
|
|
static enum esif_rc esif_cpc_to_dsp(struct esif_lp_dsp *dsp_ptr)
|
|
{
|
|
struct esif_lp_cpc *cpc_ptr = dsp_ptr->cpc_ptr;
|
|
struct esif_cpc_primitive *primitive_ptr = NULL;
|
|
struct esif_cpc_algorithm *algorithm_ptr;
|
|
struct esif_cpc_event *event_ptr;
|
|
struct domain *domain_ptr;
|
|
enum esif_rc rc = ESIF_OK;
|
|
u32 i;
|
|
u8 *base_ptr;
|
|
u64 offset;
|
|
|
|
base_ptr = (u8 *)cpc_ptr;
|
|
dsp_ptr->code_ptr = (esif_string)cpc_ptr->header.code;
|
|
|
|
dsp_ptr->domain_count_ptr = (u8 *)&cpc_ptr->number_of_domains;
|
|
dsp_ptr->ver_major_ptr = (u8 *)&cpc_ptr->header.ver_major;
|
|
dsp_ptr->ver_minor_ptr = (u8 *)&cpc_ptr->header.ver_minor;
|
|
dsp_ptr->capability_ptr = (esif_flags_t *)
|
|
&cpc_ptr->header.cpc.capability;
|
|
|
|
ESIF_TRACE_DYN_CPC(
|
|
"%s: <cpc @ %p> CPC name '%s' size %d num_primitives %u, num_algorithms %u, num_domains %u\n",
|
|
ESIF_FUNC,
|
|
cpc_ptr,
|
|
cpc_ptr->header.code,
|
|
cpc_ptr->size,
|
|
cpc_ptr->number_of_basic_primitives,
|
|
cpc_ptr->number_of_algorithms,
|
|
*dsp_ptr->domain_count_ptr);
|
|
|
|
/* 1. Insert All Primitives Into Hash */
|
|
/* Locate First Primitive Laid After CPC Struct */
|
|
primitive_ptr =
|
|
(struct esif_cpc_primitive *)((u8 *)cpc_ptr +
|
|
sizeof(struct esif_lp_cpc));
|
|
for (i = 0; i < cpc_ptr->number_of_basic_primitives; i++) {
|
|
offset = (u64)((u8 *)primitive_ptr - base_ptr);
|
|
ESIF_TRACE_DYN_CPC(
|
|
"<%06llu> Primitive[%03d]: size %03d tuple <%03u %03u %03u> operation %u(%s) num_actions %d\n",
|
|
offset,
|
|
i,
|
|
primitive_ptr->size,
|
|
primitive_ptr->tuple.id,
|
|
primitive_ptr->tuple.domain,
|
|
primitive_ptr->tuple.instance,
|
|
primitive_ptr->operation,
|
|
esif_primitive_opcode_str(
|
|
(enum esif_primitive_opcode)
|
|
primitive_ptr->operation),
|
|
primitive_ptr->number_of_actions);
|
|
|
|
/* Must Be ESIF Primitive Not CPC Primitive Format */
|
|
rc = dsp_ptr->insert_primitive(dsp_ptr, primitive_ptr);
|
|
if (ESIF_OK != rc)
|
|
goto exit;
|
|
|
|
/* Primitives Have Varaible Length Due To Number Of Actions */
|
|
primitive_ptr =
|
|
(struct esif_cpc_primitive *)((u8 *)primitive_ptr +
|
|
primitive_ptr->size);
|
|
}
|
|
|
|
/* 2. Insert All Algorithms Into Linked List */
|
|
/* First Algorithm Laid After the Last Primitive */
|
|
algorithm_ptr = (struct esif_cpc_algorithm *)primitive_ptr;
|
|
for (i = 0; i < cpc_ptr->number_of_algorithms; i++) {
|
|
offset = (u64)((u8 *)algorithm_ptr - base_ptr);
|
|
ESIF_TRACE_DYN_CPC("<%06llu> Algorithm[%3d]: action_type %u(%s) temp_xform %u tempC1 %u tempC2 %u size %u\n",
|
|
offset,
|
|
i,
|
|
algorithm_ptr->action_type,
|
|
esif_action_type_str(
|
|
(enum esif_action_type)algorithm_ptr
|
|
->action_type),
|
|
algorithm_ptr->temp_xform,
|
|
algorithm_ptr->tempC1,
|
|
algorithm_ptr->tempC2,
|
|
algorithm_ptr->size);
|
|
|
|
rc = dsp_ptr->insert_algorithm(dsp_ptr, algorithm_ptr);
|
|
if (ESIF_OK != rc)
|
|
goto exit;
|
|
|
|
/* Next Algorithm. Algorithms Are Fix-Sized */
|
|
algorithm_ptr++;
|
|
}
|
|
|
|
/* Truncate any unsupported domain conunts */
|
|
if (*dsp_ptr->domain_count_ptr > ESIF_DOMAIN_MAX)
|
|
*dsp_ptr->domain_count_ptr = ESIF_DOMAIN_MAX;
|
|
|
|
/* Domains are contained in an array one entry per domain */
|
|
if (*dsp_ptr->domain_count_ptr > 0) {
|
|
dsp_ptr->domains_ptr = (struct domain *)algorithm_ptr;
|
|
ESIF_TRACE_DYN_CPC("%s: First DWORD %08x\n",
|
|
ESIF_FUNC,
|
|
*(u32 *)dsp_ptr->domains_ptr);
|
|
}
|
|
|
|
/* Domain */
|
|
domain_ptr = (struct domain *)algorithm_ptr;
|
|
for (i = 0; i < cpc_ptr->number_of_domains; i++) {
|
|
offset = (u64)((u8 *)domain_ptr - base_ptr);
|
|
ESIF_TRACE_DYN_CPC("<%06llu> domain size %d name %s\n",
|
|
offset,
|
|
domain_ptr->size,
|
|
domain_ptr->descriptor.name);
|
|
domain_ptr =
|
|
(struct domain *)((u8 *)domain_ptr + domain_ptr->size);
|
|
}
|
|
|
|
/* Event */
|
|
event_ptr = (struct esif_cpc_event *)domain_ptr;
|
|
for (i = 0; i < cpc_ptr->number_of_events; i++) {
|
|
offset = (u64)((u8 *)event_ptr - base_ptr);
|
|
ESIF_TRACE_DYN_CPC(
|
|
"<%06llu> name %s notify %x esif_event %s(%d) esif_event_group TBD(%d)\n",
|
|
offset,
|
|
event_ptr->name,
|
|
event_ptr->event_key[i],
|
|
esif_event_type_str(event_ptr->esif_event),
|
|
event_ptr->esif_event,
|
|
event_ptr->esif_group);
|
|
|
|
/* Todo Handle Other Types Here */
|
|
if (ESIF_EVENT_GROUP_ACPI == event_ptr->esif_group) {
|
|
rc = dsp_ptr->insert_event(dsp_ptr, event_ptr);
|
|
if (ESIF_OK != rc)
|
|
goto exit;
|
|
}
|
|
/* Next Event. Events Are Fix-Sized */
|
|
event_ptr++;
|
|
}
|
|
|
|
exit:
|
|
|
|
ESIF_TRACE_DYN_CPC(
|
|
"%s: %u primitives, %u algorithms and %u events inserted, status %s! %u domain found\n",
|
|
ESIF_FUNC,
|
|
cpc_ptr->number_of_basic_primitives,
|
|
cpc_ptr->number_of_algorithms,
|
|
cpc_ptr->number_of_events,
|
|
esif_rc_str(rc),
|
|
cpc_ptr->number_of_domains);
|
|
|
|
return rc;
|
|
}
|
|
|
|
|
|
/*
|
|
******************************************************************************
|
|
* PUBLIC
|
|
******************************************************************************
|
|
*/
|
|
|
|
/* CPC Unpack */
|
|
enum esif_rc esif_cpc_unpack(
|
|
struct esif_lp_dsp *dsp_ptr,
|
|
const struct esif_data *req_data_ptr
|
|
)
|
|
{
|
|
struct esif_lp_cpc *cpc_ptr = NULL;
|
|
struct esif_cpc_header *cpc_header_ptr = NULL;
|
|
|
|
ESIF_TRACE_DYN_CPC("%s: START\n", ESIF_FUNC);
|
|
ESIF_TRACE_DYN_CPC("%s: dsp %p req_data %p cpc %p size %d\n",
|
|
ESIF_FUNC,
|
|
dsp_ptr,
|
|
req_data_ptr,
|
|
req_data_ptr->buf_ptr,
|
|
req_data_ptr->buf_len);
|
|
|
|
/* Validate Thourougly Here */
|
|
if (req_data_ptr->type != ESIF_DATA_DSP)
|
|
return ESIF_E_INVALID_REQUEST_TYPE;
|
|
|
|
if (req_data_ptr->buf_len < sizeof(struct esif_cpc_header))
|
|
return ESIF_E_CPC_SHORT;
|
|
|
|
cpc_ptr = (struct esif_lp_cpc *)req_data_ptr->buf_ptr;
|
|
cpc_header_ptr = (struct esif_cpc_header *)&cpc_ptr->header;
|
|
|
|
ESIF_TRACE_DYN_CPC(
|
|
"%s: code %s ver %x (%x,%x), signature %08x, version %x\n",
|
|
ESIF_FUNC,
|
|
cpc_header_ptr->code,
|
|
cpc_header_ptr->version,
|
|
cpc_header_ptr->ver_major,
|
|
cpc_header_ptr->ver_minor,
|
|
cpc_header_ptr->cpc.signature,
|
|
cpc_header_ptr->cpc.version);
|
|
|
|
if (cpc_header_ptr->cpc.signature != *(unsigned int *)"@CPC")
|
|
return ESIF_E_CPC_SIGNATURE;
|
|
|
|
/* Make a copy for now */
|
|
cpc_ptr = (struct esif_lp_cpc *)esif_ccb_malloc(req_data_ptr->buf_len);
|
|
if (NULL != cpc_ptr) {
|
|
esif_ccb_memcpy(cpc_ptr,
|
|
req_data_ptr->buf_ptr,
|
|
req_data_ptr->buf_len);
|
|
|
|
dsp_ptr->cpc_ptr = cpc_ptr;
|
|
esif_cpc_to_dsp(dsp_ptr);
|
|
}
|
|
ESIF_TRACE_DYN_CPC(" %s: STOP\n", ESIF_FUNC);
|
|
return ESIF_OK;
|
|
}
|
|
|
|
|
|
/* CPC Free */
|
|
void esif_cpc_free(struct esif_lp_dsp *dsp_ptr)
|
|
{
|
|
ESIF_TRACE_DYN_CPC("%s: START\n", ESIF_FUNC);
|
|
|
|
if (NULL == dsp_ptr || NULL == dsp_ptr->cpc_ptr)
|
|
return;
|
|
|
|
esif_ccb_free(dsp_ptr->cpc_ptr);
|
|
dsp_ptr->cpc_ptr = NULL;
|
|
|
|
ESIF_TRACE_DYN_CPC("%s: STOP\n", ESIF_FUNC);
|
|
}
|
|
|
|
|
|
/* Init */
|
|
enum esif_rc esif_cpc_init(void)
|
|
{
|
|
ESIF_TRACE_DYN_INIT("%s: Initialize Compact Primitive Catalog(CPC)\n",
|
|
ESIF_FUNC);
|
|
return ESIF_OK;
|
|
}
|
|
|
|
|
|
/* Exit */
|
|
void esif_cpc_exit(void)
|
|
{
|
|
ESIF_TRACE_DYN_INIT("%s: UnInitialize Compact Primitive Catalog(CPC)\n",
|
|
ESIF_FUNC);
|
|
}
|
|
|
|
|
|
/*****************************************************************************/
|
|
/*****************************************************************************/
|
|
/*****************************************************************************/
|
|
|