1719f82d3SEliot Blennerhassett /****************************************************************************** 2719f82d3SEliot Blennerhassett 3719f82d3SEliot Blennerhassett AudioScience HPI driver 451e6f47dSEliot Blennerhassett Copyright (C) 1997-2014 AudioScience Inc. <support@audioscience.com> 5719f82d3SEliot Blennerhassett 6719f82d3SEliot Blennerhassett This program is free software; you can redistribute it and/or modify 7719f82d3SEliot Blennerhassett it under the terms of version 2 of the GNU General Public License as 8719f82d3SEliot Blennerhassett published by the Free Software Foundation; 9719f82d3SEliot Blennerhassett 10719f82d3SEliot Blennerhassett This program is distributed in the hope that it will be useful, 11719f82d3SEliot Blennerhassett but WITHOUT ANY WARRANTY; without even the implied warranty of 12719f82d3SEliot Blennerhassett MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13719f82d3SEliot Blennerhassett GNU General Public License for more details. 14719f82d3SEliot Blennerhassett 15719f82d3SEliot Blennerhassett You should have received a copy of the GNU General Public License 16719f82d3SEliot Blennerhassett along with this program; if not, write to the Free Software 17719f82d3SEliot Blennerhassett Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18719f82d3SEliot Blennerhassett 19719f82d3SEliot Blennerhassett Hardware Programming Interface (HPI) Utility functions. 20719f82d3SEliot Blennerhassett 21719f82d3SEliot Blennerhassett (C) Copyright AudioScience Inc. 2007 22719f82d3SEliot Blennerhassett *******************************************************************************/ 23719f82d3SEliot Blennerhassett 24719f82d3SEliot Blennerhassett #include "hpi_internal.h" 25719f82d3SEliot Blennerhassett #include "hpimsginit.h" 26*f9d94b57STakashi Iwai #include <linux/nospec.h> 27719f82d3SEliot Blennerhassett 28719f82d3SEliot Blennerhassett /* The actual message size for each object type */ 29719f82d3SEliot Blennerhassett static u16 msg_size[HPI_OBJ_MAXINDEX + 1] = HPI_MESSAGE_SIZE_BY_OBJECT; 30719f82d3SEliot Blennerhassett /* The actual response size for each object type */ 31719f82d3SEliot Blennerhassett static u16 res_size[HPI_OBJ_MAXINDEX + 1] = HPI_RESPONSE_SIZE_BY_OBJECT; 32719f82d3SEliot Blennerhassett /* Flag to enable alternate message type for SSX2 bypass. */ 33719f82d3SEliot Blennerhassett static u16 gwSSX2_bypass; 34719f82d3SEliot Blennerhassett 35719f82d3SEliot Blennerhassett /** \internal 36719f82d3SEliot Blennerhassett * initialize the HPI message structure 37719f82d3SEliot Blennerhassett */ 38719f82d3SEliot Blennerhassett static void hpi_init_message(struct hpi_message *phm, u16 object, 39719f82d3SEliot Blennerhassett u16 function) 40719f82d3SEliot Blennerhassett { 4151e6f47dSEliot Blennerhassett u16 size; 4251e6f47dSEliot Blennerhassett 43*f9d94b57STakashi Iwai if ((object > 0) && (object <= HPI_OBJ_MAXINDEX)) { 44*f9d94b57STakashi Iwai object = array_index_nospec(object, HPI_OBJ_MAXINDEX + 1); 4551e6f47dSEliot Blennerhassett size = msg_size[object]; 46*f9d94b57STakashi Iwai } else { 4751e6f47dSEliot Blennerhassett size = sizeof(*phm); 48*f9d94b57STakashi Iwai } 4951e6f47dSEliot Blennerhassett 5051e6f47dSEliot Blennerhassett memset(phm, 0, size); 5151e6f47dSEliot Blennerhassett phm->size = size; 52719f82d3SEliot Blennerhassett 53719f82d3SEliot Blennerhassett if (gwSSX2_bypass) 54719f82d3SEliot Blennerhassett phm->type = HPI_TYPE_SSX2BYPASS_MESSAGE; 55719f82d3SEliot Blennerhassett else 5682b5774fSEliot Blennerhassett phm->type = HPI_TYPE_REQUEST; 57719f82d3SEliot Blennerhassett phm->object = object; 58719f82d3SEliot Blennerhassett phm->function = function; 59719f82d3SEliot Blennerhassett phm->version = 0; 603285ea10SEliot Blennerhassett phm->adapter_index = HPI_ADAPTER_INDEX_INVALID; 610a1602c0SEliot Blennerhassett /* Expect actual adapter index to be set by caller */ 62719f82d3SEliot Blennerhassett } 63719f82d3SEliot Blennerhassett 64719f82d3SEliot Blennerhassett /** \internal 65719f82d3SEliot Blennerhassett * initialize the HPI response structure 66719f82d3SEliot Blennerhassett */ 67719f82d3SEliot Blennerhassett void hpi_init_response(struct hpi_response *phr, u16 object, u16 function, 68719f82d3SEliot Blennerhassett u16 error) 69719f82d3SEliot Blennerhassett { 7051e6f47dSEliot Blennerhassett u16 size; 7151e6f47dSEliot Blennerhassett 72*f9d94b57STakashi Iwai if ((object > 0) && (object <= HPI_OBJ_MAXINDEX)) { 73*f9d94b57STakashi Iwai object = array_index_nospec(object, HPI_OBJ_MAXINDEX + 1); 7451e6f47dSEliot Blennerhassett size = res_size[object]; 75*f9d94b57STakashi Iwai } else { 7651e6f47dSEliot Blennerhassett size = sizeof(*phr); 77*f9d94b57STakashi Iwai } 7851e6f47dSEliot Blennerhassett 7951e6f47dSEliot Blennerhassett memset(phr, 0, sizeof(*phr)); 8051e6f47dSEliot Blennerhassett phr->size = size; 8151e6f47dSEliot Blennerhassett phr->type = HPI_TYPE_RESPONSE; 82719f82d3SEliot Blennerhassett phr->object = object; 83719f82d3SEliot Blennerhassett phr->function = function; 84719f82d3SEliot Blennerhassett phr->error = error; 85719f82d3SEliot Blennerhassett phr->specific_error = 0; 86719f82d3SEliot Blennerhassett phr->version = 0; 87719f82d3SEliot Blennerhassett } 88719f82d3SEliot Blennerhassett 89719f82d3SEliot Blennerhassett void hpi_init_message_response(struct hpi_message *phm, 90719f82d3SEliot Blennerhassett struct hpi_response *phr, u16 object, u16 function) 91719f82d3SEliot Blennerhassett { 92719f82d3SEliot Blennerhassett hpi_init_message(phm, object, function); 93719f82d3SEliot Blennerhassett /* default error return if the response is 94719f82d3SEliot Blennerhassett not filled in by the callee */ 95719f82d3SEliot Blennerhassett hpi_init_response(phr, object, function, 96719f82d3SEliot Blennerhassett HPI_ERROR_PROCESSING_MESSAGE); 97719f82d3SEliot Blennerhassett } 98719f82d3SEliot Blennerhassett 99719f82d3SEliot Blennerhassett static void hpi_init_messageV1(struct hpi_message_header *phm, u16 size, 100719f82d3SEliot Blennerhassett u16 object, u16 function) 101719f82d3SEliot Blennerhassett { 10251e6f47dSEliot Blennerhassett memset(phm, 0, size); 103719f82d3SEliot Blennerhassett if ((object > 0) && (object <= HPI_OBJ_MAXINDEX)) { 104719f82d3SEliot Blennerhassett phm->size = size; 10582b5774fSEliot Blennerhassett phm->type = HPI_TYPE_REQUEST; 106719f82d3SEliot Blennerhassett phm->object = object; 107719f82d3SEliot Blennerhassett phm->function = function; 108719f82d3SEliot Blennerhassett phm->version = 1; 109719f82d3SEliot Blennerhassett /* Expect adapter index to be set by caller */ 110719f82d3SEliot Blennerhassett } 111719f82d3SEliot Blennerhassett } 112719f82d3SEliot Blennerhassett 113719f82d3SEliot Blennerhassett void hpi_init_responseV1(struct hpi_response_header *phr, u16 size, 114719f82d3SEliot Blennerhassett u16 object, u16 function) 115719f82d3SEliot Blennerhassett { 11651e6f47dSEliot Blennerhassett (void)object; 11751e6f47dSEliot Blennerhassett (void)function; 11851e6f47dSEliot Blennerhassett memset(phr, 0, size); 119719f82d3SEliot Blennerhassett phr->size = size; 120719f82d3SEliot Blennerhassett phr->version = 1; 121719f82d3SEliot Blennerhassett phr->type = HPI_TYPE_RESPONSE; 122719f82d3SEliot Blennerhassett phr->error = HPI_ERROR_PROCESSING_MESSAGE; 123719f82d3SEliot Blennerhassett } 124719f82d3SEliot Blennerhassett 125719f82d3SEliot Blennerhassett void hpi_init_message_responseV1(struct hpi_message_header *phm, u16 msg_size, 126719f82d3SEliot Blennerhassett struct hpi_response_header *phr, u16 res_size, u16 object, 127719f82d3SEliot Blennerhassett u16 function) 128719f82d3SEliot Blennerhassett { 129719f82d3SEliot Blennerhassett hpi_init_messageV1(phm, msg_size, object, function); 130719f82d3SEliot Blennerhassett hpi_init_responseV1(phr, res_size, object, function); 131719f82d3SEliot Blennerhassett } 132