cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

hpimsgx.c (21532B)


      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
      8Extended Message Function With Response Caching
      9
     10(C) Copyright AudioScience Inc. 2002
     11*****************************************************************************/
     12#define SOURCEFILE_NAME "hpimsgx.c"
     13#include "hpi_internal.h"
     14#include "hpi_version.h"
     15#include "hpimsginit.h"
     16#include "hpicmn.h"
     17#include "hpimsgx.h"
     18#include "hpidebug.h"
     19
     20static const struct pci_device_id asihpi_pci_tbl[] = {
     21#include "hpipcida.h"
     22};
     23
     24static struct hpios_spinlock msgx_lock;
     25
     26static hpi_handler_func *hpi_entry_points[HPI_MAX_ADAPTERS];
     27static int logging_enabled = 1;
     28
     29static hpi_handler_func *hpi_lookup_entry_point_function(const struct hpi_pci
     30	*pci_info)
     31{
     32
     33	int i;
     34
     35	for (i = 0; asihpi_pci_tbl[i].vendor != 0; i++) {
     36		if (asihpi_pci_tbl[i].vendor != PCI_ANY_ID
     37			&& asihpi_pci_tbl[i].vendor !=
     38			pci_info->pci_dev->vendor)
     39			continue;
     40		if (asihpi_pci_tbl[i].device != PCI_ANY_ID
     41			&& asihpi_pci_tbl[i].device !=
     42			pci_info->pci_dev->device)
     43			continue;
     44		if (asihpi_pci_tbl[i].subvendor != PCI_ANY_ID
     45			&& asihpi_pci_tbl[i].subvendor !=
     46			pci_info->pci_dev->subsystem_vendor)
     47			continue;
     48		if (asihpi_pci_tbl[i].subdevice != PCI_ANY_ID
     49			&& asihpi_pci_tbl[i].subdevice !=
     50			pci_info->pci_dev->subsystem_device)
     51			continue;
     52
     53		/* HPI_DEBUG_LOG(DEBUG, " %x,%lx\n", i,
     54		   asihpi_pci_tbl[i].driver_data); */
     55		return (hpi_handler_func *) asihpi_pci_tbl[i].driver_data;
     56	}
     57
     58	return NULL;
     59}
     60
     61static inline void hw_entry_point(struct hpi_message *phm,
     62	struct hpi_response *phr)
     63{
     64	if ((phm->adapter_index < HPI_MAX_ADAPTERS)
     65		&& hpi_entry_points[phm->adapter_index])
     66		hpi_entry_points[phm->adapter_index] (phm, phr);
     67	else
     68		hpi_init_response(phr, phm->object, phm->function,
     69			HPI_ERROR_PROCESSING_MESSAGE);
     70}
     71
     72static void adapter_open(struct hpi_message *phm, struct hpi_response *phr);
     73static void adapter_close(struct hpi_message *phm, struct hpi_response *phr);
     74
     75static void mixer_open(struct hpi_message *phm, struct hpi_response *phr);
     76static void mixer_close(struct hpi_message *phm, struct hpi_response *phr);
     77
     78static void outstream_open(struct hpi_message *phm, struct hpi_response *phr,
     79	void *h_owner);
     80static void outstream_close(struct hpi_message *phm, struct hpi_response *phr,
     81	void *h_owner);
     82static void instream_open(struct hpi_message *phm, struct hpi_response *phr,
     83	void *h_owner);
     84static void instream_close(struct hpi_message *phm, struct hpi_response *phr,
     85	void *h_owner);
     86
     87static void HPIMSGX__reset(u16 adapter_index);
     88
     89static u16 HPIMSGX__init(struct hpi_message *phm, struct hpi_response *phr);
     90static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner);
     91
     92#ifndef DISABLE_PRAGMA_PACK1
     93#pragma pack(push, 1)
     94#endif
     95
     96struct hpi_subsys_response {
     97	struct hpi_response_header h;
     98	struct hpi_subsys_res s;
     99};
    100
    101struct hpi_adapter_response {
    102	struct hpi_response_header h;
    103	struct hpi_adapter_res a;
    104};
    105
    106struct hpi_mixer_response {
    107	struct hpi_response_header h;
    108	struct hpi_mixer_res m;
    109};
    110
    111struct hpi_stream_response {
    112	struct hpi_response_header h;
    113	struct hpi_stream_res d;
    114};
    115
    116struct adapter_info {
    117	u16 type;
    118	u16 num_instreams;
    119	u16 num_outstreams;
    120};
    121
    122struct asi_open_state {
    123	int open_flag;
    124	void *h_owner;
    125};
    126
    127#ifndef DISABLE_PRAGMA_PACK1
    128#pragma pack(pop)
    129#endif
    130
    131/* Globals */
    132static struct hpi_adapter_response rESP_HPI_ADAPTER_OPEN[HPI_MAX_ADAPTERS];
    133
    134static struct hpi_stream_response
    135	rESP_HPI_OSTREAM_OPEN[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
    136
    137static struct hpi_stream_response
    138	rESP_HPI_ISTREAM_OPEN[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
    139
    140static struct hpi_mixer_response rESP_HPI_MIXER_OPEN[HPI_MAX_ADAPTERS];
    141
    142static struct adapter_info aDAPTER_INFO[HPI_MAX_ADAPTERS];
    143
    144/* use these to keep track of opens from user mode apps/DLLs */
    145static struct asi_open_state
    146	outstream_user_open[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
    147
    148static struct asi_open_state
    149	instream_user_open[HPI_MAX_ADAPTERS][HPI_MAX_STREAMS];
    150
    151static void subsys_message(struct hpi_message *phm, struct hpi_response *phr,
    152	void *h_owner)
    153{
    154	if (phm->adapter_index != HPI_ADAPTER_INDEX_INVALID)
    155		HPI_DEBUG_LOG(WARNING,
    156			"suspicious adapter index %d in subsys message 0x%x.\n",
    157			phm->adapter_index, phm->function);
    158
    159	switch (phm->function) {
    160	case HPI_SUBSYS_GET_VERSION:
    161		hpi_init_response(phr, HPI_OBJ_SUBSYSTEM,
    162			HPI_SUBSYS_GET_VERSION, 0);
    163		phr->u.s.version = HPI_VER >> 8;	/* return major.minor */
    164		phr->u.s.data = HPI_VER;	/* return major.minor.release */
    165		break;
    166	case HPI_SUBSYS_OPEN:
    167		/*do not propagate the message down the chain */
    168		hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_OPEN, 0);
    169		break;
    170	case HPI_SUBSYS_CLOSE:
    171		/*do not propagate the message down the chain */
    172		hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_CLOSE,
    173			0);
    174		HPIMSGX__cleanup(HPIMSGX_ALLADAPTERS, h_owner);
    175		break;
    176	case HPI_SUBSYS_DRIVER_LOAD:
    177		/* Initialize this module's internal state */
    178		hpios_msgxlock_init(&msgx_lock);
    179		memset(&hpi_entry_points, 0, sizeof(hpi_entry_points));
    180		/* Init subsys_findadapters response to no-adapters */
    181		HPIMSGX__reset(HPIMSGX_ALLADAPTERS);
    182		hpi_init_response(phr, HPI_OBJ_SUBSYSTEM,
    183			HPI_SUBSYS_DRIVER_LOAD, 0);
    184		/* individual HPIs dont implement driver load */
    185		HPI_COMMON(phm, phr);
    186		break;
    187	case HPI_SUBSYS_DRIVER_UNLOAD:
    188		HPI_COMMON(phm, phr);
    189		HPIMSGX__cleanup(HPIMSGX_ALLADAPTERS, h_owner);
    190		hpi_init_response(phr, HPI_OBJ_SUBSYSTEM,
    191			HPI_SUBSYS_DRIVER_UNLOAD, 0);
    192		return;
    193
    194	case HPI_SUBSYS_GET_NUM_ADAPTERS:
    195	case HPI_SUBSYS_GET_ADAPTER:
    196		HPI_COMMON(phm, phr);
    197		break;
    198
    199	case HPI_SUBSYS_CREATE_ADAPTER:
    200		HPIMSGX__init(phm, phr);
    201		break;
    202
    203	default:
    204		/* Must explicitly handle every subsys message in this switch */
    205		hpi_init_response(phr, HPI_OBJ_SUBSYSTEM, phm->function,
    206			HPI_ERROR_INVALID_FUNC);
    207		break;
    208	}
    209}
    210
    211static void adapter_message(struct hpi_message *phm, struct hpi_response *phr,
    212	void *h_owner)
    213{
    214	switch (phm->function) {
    215	case HPI_ADAPTER_OPEN:
    216		adapter_open(phm, phr);
    217		break;
    218	case HPI_ADAPTER_CLOSE:
    219		adapter_close(phm, phr);
    220		break;
    221	case HPI_ADAPTER_DELETE:
    222		HPIMSGX__cleanup(phm->adapter_index, h_owner);
    223		{
    224			struct hpi_message hm;
    225			struct hpi_response hr;
    226			hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
    227				HPI_ADAPTER_CLOSE);
    228			hm.adapter_index = phm->adapter_index;
    229			hw_entry_point(&hm, &hr);
    230		}
    231		hw_entry_point(phm, phr);
    232		break;
    233
    234	default:
    235		hw_entry_point(phm, phr);
    236		break;
    237	}
    238}
    239
    240static void mixer_message(struct hpi_message *phm, struct hpi_response *phr)
    241{
    242	switch (phm->function) {
    243	case HPI_MIXER_OPEN:
    244		mixer_open(phm, phr);
    245		break;
    246	case HPI_MIXER_CLOSE:
    247		mixer_close(phm, phr);
    248		break;
    249	default:
    250		hw_entry_point(phm, phr);
    251		break;
    252	}
    253}
    254
    255static void outstream_message(struct hpi_message *phm,
    256	struct hpi_response *phr, void *h_owner)
    257{
    258	if (phm->obj_index >= aDAPTER_INFO[phm->adapter_index].num_outstreams) {
    259		hpi_init_response(phr, HPI_OBJ_OSTREAM, phm->function,
    260			HPI_ERROR_INVALID_OBJ_INDEX);
    261		return;
    262	}
    263
    264	switch (phm->function) {
    265	case HPI_OSTREAM_OPEN:
    266		outstream_open(phm, phr, h_owner);
    267		break;
    268	case HPI_OSTREAM_CLOSE:
    269		outstream_close(phm, phr, h_owner);
    270		break;
    271	default:
    272		hw_entry_point(phm, phr);
    273		break;
    274	}
    275}
    276
    277static void instream_message(struct hpi_message *phm,
    278	struct hpi_response *phr, void *h_owner)
    279{
    280	if (phm->obj_index >= aDAPTER_INFO[phm->adapter_index].num_instreams) {
    281		hpi_init_response(phr, HPI_OBJ_ISTREAM, phm->function,
    282			HPI_ERROR_INVALID_OBJ_INDEX);
    283		return;
    284	}
    285
    286	switch (phm->function) {
    287	case HPI_ISTREAM_OPEN:
    288		instream_open(phm, phr, h_owner);
    289		break;
    290	case HPI_ISTREAM_CLOSE:
    291		instream_close(phm, phr, h_owner);
    292		break;
    293	default:
    294		hw_entry_point(phm, phr);
    295		break;
    296	}
    297}
    298
    299/* NOTE: HPI_Message() must be defined in the driver as a wrapper for
    300 * HPI_MessageEx so that functions in hpifunc.c compile.
    301 */
    302void hpi_send_recv_ex(struct hpi_message *phm, struct hpi_response *phr,
    303	void *h_owner)
    304{
    305
    306	if (logging_enabled)
    307		HPI_DEBUG_MESSAGE(DEBUG, phm);
    308
    309	if (phm->type != HPI_TYPE_REQUEST) {
    310		hpi_init_response(phr, phm->object, phm->function,
    311			HPI_ERROR_INVALID_TYPE);
    312		return;
    313	}
    314
    315	if (phm->adapter_index >= HPI_MAX_ADAPTERS
    316		&& phm->adapter_index != HPIMSGX_ALLADAPTERS) {
    317		hpi_init_response(phr, phm->object, phm->function,
    318			HPI_ERROR_BAD_ADAPTER_NUMBER);
    319		return;
    320	}
    321
    322	switch (phm->object) {
    323	case HPI_OBJ_SUBSYSTEM:
    324		subsys_message(phm, phr, h_owner);
    325		break;
    326
    327	case HPI_OBJ_ADAPTER:
    328		adapter_message(phm, phr, h_owner);
    329		break;
    330
    331	case HPI_OBJ_MIXER:
    332		mixer_message(phm, phr);
    333		break;
    334
    335	case HPI_OBJ_OSTREAM:
    336		outstream_message(phm, phr, h_owner);
    337		break;
    338
    339	case HPI_OBJ_ISTREAM:
    340		instream_message(phm, phr, h_owner);
    341		break;
    342
    343	default:
    344		hw_entry_point(phm, phr);
    345		break;
    346	}
    347
    348	if (logging_enabled)
    349		HPI_DEBUG_RESPONSE(phr);
    350
    351	if (phr->error >= HPI_ERROR_DSP_COMMUNICATION) {
    352		hpi_debug_level_set(HPI_DEBUG_LEVEL_ERROR);
    353		logging_enabled = 0;
    354	}
    355}
    356
    357static void adapter_open(struct hpi_message *phm, struct hpi_response *phr)
    358{
    359	HPI_DEBUG_LOG(VERBOSE, "adapter_open\n");
    360	memcpy(phr, &rESP_HPI_ADAPTER_OPEN[phm->adapter_index],
    361		sizeof(rESP_HPI_ADAPTER_OPEN[0]));
    362}
    363
    364static void adapter_close(struct hpi_message *phm, struct hpi_response *phr)
    365{
    366	HPI_DEBUG_LOG(VERBOSE, "adapter_close\n");
    367	hpi_init_response(phr, HPI_OBJ_ADAPTER, HPI_ADAPTER_CLOSE, 0);
    368}
    369
    370static void mixer_open(struct hpi_message *phm, struct hpi_response *phr)
    371{
    372	memcpy(phr, &rESP_HPI_MIXER_OPEN[phm->adapter_index],
    373		sizeof(rESP_HPI_MIXER_OPEN[0]));
    374}
    375
    376static void mixer_close(struct hpi_message *phm, struct hpi_response *phr)
    377{
    378	hpi_init_response(phr, HPI_OBJ_MIXER, HPI_MIXER_CLOSE, 0);
    379}
    380
    381static void instream_open(struct hpi_message *phm, struct hpi_response *phr,
    382	void *h_owner)
    383{
    384
    385	struct hpi_message hm;
    386	struct hpi_response hr;
    387
    388	hpi_init_response(phr, HPI_OBJ_ISTREAM, HPI_ISTREAM_OPEN, 0);
    389
    390	hpios_msgxlock_lock(&msgx_lock);
    391
    392	if (instream_user_open[phm->adapter_index][phm->obj_index].open_flag)
    393		phr->error = HPI_ERROR_OBJ_ALREADY_OPEN;
    394	else if (rESP_HPI_ISTREAM_OPEN[phm->adapter_index]
    395		[phm->obj_index].h.error)
    396		memcpy(phr,
    397			&rESP_HPI_ISTREAM_OPEN[phm->adapter_index][phm->
    398				obj_index],
    399			sizeof(rESP_HPI_ISTREAM_OPEN[0][0]));
    400	else {
    401		instream_user_open[phm->adapter_index][phm->
    402			obj_index].open_flag = 1;
    403		hpios_msgxlock_unlock(&msgx_lock);
    404
    405		/* issue a reset */
    406		hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
    407			HPI_ISTREAM_RESET);
    408		hm.adapter_index = phm->adapter_index;
    409		hm.obj_index = phm->obj_index;
    410		hw_entry_point(&hm, &hr);
    411
    412		hpios_msgxlock_lock(&msgx_lock);
    413		if (hr.error) {
    414			instream_user_open[phm->adapter_index][phm->
    415				obj_index].open_flag = 0;
    416			phr->error = hr.error;
    417		} else {
    418			instream_user_open[phm->adapter_index][phm->
    419				obj_index].open_flag = 1;
    420			instream_user_open[phm->adapter_index][phm->
    421				obj_index].h_owner = h_owner;
    422			memcpy(phr,
    423				&rESP_HPI_ISTREAM_OPEN[phm->adapter_index]
    424				[phm->obj_index],
    425				sizeof(rESP_HPI_ISTREAM_OPEN[0][0]));
    426		}
    427	}
    428	hpios_msgxlock_unlock(&msgx_lock);
    429}
    430
    431static void instream_close(struct hpi_message *phm, struct hpi_response *phr,
    432	void *h_owner)
    433{
    434
    435	struct hpi_message hm;
    436	struct hpi_response hr;
    437
    438	hpi_init_response(phr, HPI_OBJ_ISTREAM, HPI_ISTREAM_CLOSE, 0);
    439
    440	hpios_msgxlock_lock(&msgx_lock);
    441	if (h_owner ==
    442		instream_user_open[phm->adapter_index][phm->
    443			obj_index].h_owner) {
    444		/* HPI_DEBUG_LOG(INFO,"closing adapter %d "
    445		   "instream %d owned by %p\n",
    446		   phm->wAdapterIndex, phm->wObjIndex, hOwner); */
    447		instream_user_open[phm->adapter_index][phm->
    448			obj_index].h_owner = NULL;
    449		hpios_msgxlock_unlock(&msgx_lock);
    450		/* issue a reset */
    451		hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
    452			HPI_ISTREAM_RESET);
    453		hm.adapter_index = phm->adapter_index;
    454		hm.obj_index = phm->obj_index;
    455		hw_entry_point(&hm, &hr);
    456		hpios_msgxlock_lock(&msgx_lock);
    457		if (hr.error) {
    458			instream_user_open[phm->adapter_index][phm->
    459				obj_index].h_owner = h_owner;
    460			phr->error = hr.error;
    461		} else {
    462			instream_user_open[phm->adapter_index][phm->
    463				obj_index].open_flag = 0;
    464			instream_user_open[phm->adapter_index][phm->
    465				obj_index].h_owner = NULL;
    466		}
    467	} else {
    468		HPI_DEBUG_LOG(WARNING,
    469			"%p trying to close %d instream %d owned by %p\n",
    470			h_owner, phm->adapter_index, phm->obj_index,
    471			instream_user_open[phm->adapter_index][phm->
    472				obj_index].h_owner);
    473		phr->error = HPI_ERROR_OBJ_NOT_OPEN;
    474	}
    475	hpios_msgxlock_unlock(&msgx_lock);
    476}
    477
    478static void outstream_open(struct hpi_message *phm, struct hpi_response *phr,
    479	void *h_owner)
    480{
    481
    482	struct hpi_message hm;
    483	struct hpi_response hr;
    484
    485	hpi_init_response(phr, HPI_OBJ_OSTREAM, HPI_OSTREAM_OPEN, 0);
    486
    487	hpios_msgxlock_lock(&msgx_lock);
    488
    489	if (outstream_user_open[phm->adapter_index][phm->obj_index].open_flag)
    490		phr->error = HPI_ERROR_OBJ_ALREADY_OPEN;
    491	else if (rESP_HPI_OSTREAM_OPEN[phm->adapter_index]
    492		[phm->obj_index].h.error)
    493		memcpy(phr,
    494			&rESP_HPI_OSTREAM_OPEN[phm->adapter_index][phm->
    495				obj_index],
    496			sizeof(rESP_HPI_OSTREAM_OPEN[0][0]));
    497	else {
    498		outstream_user_open[phm->adapter_index][phm->
    499			obj_index].open_flag = 1;
    500		hpios_msgxlock_unlock(&msgx_lock);
    501
    502		/* issue a reset */
    503		hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
    504			HPI_OSTREAM_RESET);
    505		hm.adapter_index = phm->adapter_index;
    506		hm.obj_index = phm->obj_index;
    507		hw_entry_point(&hm, &hr);
    508
    509		hpios_msgxlock_lock(&msgx_lock);
    510		if (hr.error) {
    511			outstream_user_open[phm->adapter_index][phm->
    512				obj_index].open_flag = 0;
    513			phr->error = hr.error;
    514		} else {
    515			outstream_user_open[phm->adapter_index][phm->
    516				obj_index].open_flag = 1;
    517			outstream_user_open[phm->adapter_index][phm->
    518				obj_index].h_owner = h_owner;
    519			memcpy(phr,
    520				&rESP_HPI_OSTREAM_OPEN[phm->adapter_index]
    521				[phm->obj_index],
    522				sizeof(rESP_HPI_OSTREAM_OPEN[0][0]));
    523		}
    524	}
    525	hpios_msgxlock_unlock(&msgx_lock);
    526}
    527
    528static void outstream_close(struct hpi_message *phm, struct hpi_response *phr,
    529	void *h_owner)
    530{
    531
    532	struct hpi_message hm;
    533	struct hpi_response hr;
    534
    535	hpi_init_response(phr, HPI_OBJ_OSTREAM, HPI_OSTREAM_CLOSE, 0);
    536
    537	hpios_msgxlock_lock(&msgx_lock);
    538
    539	if (h_owner ==
    540		outstream_user_open[phm->adapter_index][phm->
    541			obj_index].h_owner) {
    542		/* HPI_DEBUG_LOG(INFO,"closing adapter %d "
    543		   "outstream %d owned by %p\n",
    544		   phm->wAdapterIndex, phm->wObjIndex, hOwner); */
    545		outstream_user_open[phm->adapter_index][phm->
    546			obj_index].h_owner = NULL;
    547		hpios_msgxlock_unlock(&msgx_lock);
    548		/* issue a reset */
    549		hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
    550			HPI_OSTREAM_RESET);
    551		hm.adapter_index = phm->adapter_index;
    552		hm.obj_index = phm->obj_index;
    553		hw_entry_point(&hm, &hr);
    554		hpios_msgxlock_lock(&msgx_lock);
    555		if (hr.error) {
    556			outstream_user_open[phm->adapter_index][phm->
    557				obj_index].h_owner = h_owner;
    558			phr->error = hr.error;
    559		} else {
    560			outstream_user_open[phm->adapter_index][phm->
    561				obj_index].open_flag = 0;
    562			outstream_user_open[phm->adapter_index][phm->
    563				obj_index].h_owner = NULL;
    564		}
    565	} else {
    566		HPI_DEBUG_LOG(WARNING,
    567			"%p trying to close %d outstream %d owned by %p\n",
    568			h_owner, phm->adapter_index, phm->obj_index,
    569			outstream_user_open[phm->adapter_index][phm->
    570				obj_index].h_owner);
    571		phr->error = HPI_ERROR_OBJ_NOT_OPEN;
    572	}
    573	hpios_msgxlock_unlock(&msgx_lock);
    574}
    575
    576static u16 adapter_prepare(u16 adapter)
    577{
    578	struct hpi_message hm;
    579	struct hpi_response hr;
    580
    581	/* Open the adapter and streams */
    582	u16 i;
    583
    584	/* call to HPI_ADAPTER_OPEN */
    585	hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
    586		HPI_ADAPTER_OPEN);
    587	hm.adapter_index = adapter;
    588	hw_entry_point(&hm, &hr);
    589	memcpy(&rESP_HPI_ADAPTER_OPEN[adapter], &hr,
    590		sizeof(rESP_HPI_ADAPTER_OPEN[0]));
    591	if (hr.error)
    592		return hr.error;
    593
    594	/* call to HPI_ADAPTER_GET_INFO */
    595	hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
    596		HPI_ADAPTER_GET_INFO);
    597	hm.adapter_index = adapter;
    598	hw_entry_point(&hm, &hr);
    599	if (hr.error)
    600		return hr.error;
    601
    602	aDAPTER_INFO[adapter].num_outstreams = hr.u.ax.info.num_outstreams;
    603	aDAPTER_INFO[adapter].num_instreams = hr.u.ax.info.num_instreams;
    604	aDAPTER_INFO[adapter].type = hr.u.ax.info.adapter_type;
    605
    606	/* call to HPI_OSTREAM_OPEN */
    607	for (i = 0; i < aDAPTER_INFO[adapter].num_outstreams; i++) {
    608		hpi_init_message_response(&hm, &hr, HPI_OBJ_OSTREAM,
    609			HPI_OSTREAM_OPEN);
    610		hm.adapter_index = adapter;
    611		hm.obj_index = i;
    612		hw_entry_point(&hm, &hr);
    613		memcpy(&rESP_HPI_OSTREAM_OPEN[adapter][i], &hr,
    614			sizeof(rESP_HPI_OSTREAM_OPEN[0][0]));
    615		outstream_user_open[adapter][i].open_flag = 0;
    616		outstream_user_open[adapter][i].h_owner = NULL;
    617	}
    618
    619	/* call to HPI_ISTREAM_OPEN */
    620	for (i = 0; i < aDAPTER_INFO[adapter].num_instreams; i++) {
    621		hpi_init_message_response(&hm, &hr, HPI_OBJ_ISTREAM,
    622			HPI_ISTREAM_OPEN);
    623		hm.adapter_index = adapter;
    624		hm.obj_index = i;
    625		hw_entry_point(&hm, &hr);
    626		memcpy(&rESP_HPI_ISTREAM_OPEN[adapter][i], &hr,
    627			sizeof(rESP_HPI_ISTREAM_OPEN[0][0]));
    628		instream_user_open[adapter][i].open_flag = 0;
    629		instream_user_open[adapter][i].h_owner = NULL;
    630	}
    631
    632	/* call to HPI_MIXER_OPEN */
    633	hpi_init_message_response(&hm, &hr, HPI_OBJ_MIXER, HPI_MIXER_OPEN);
    634	hm.adapter_index = adapter;
    635	hw_entry_point(&hm, &hr);
    636	memcpy(&rESP_HPI_MIXER_OPEN[adapter], &hr,
    637		sizeof(rESP_HPI_MIXER_OPEN[0]));
    638
    639	return 0;
    640}
    641
    642static void HPIMSGX__reset(u16 adapter_index)
    643{
    644	int i;
    645	u16 adapter;
    646	struct hpi_response hr;
    647
    648	if (adapter_index == HPIMSGX_ALLADAPTERS) {
    649		for (adapter = 0; adapter < HPI_MAX_ADAPTERS; adapter++) {
    650
    651			hpi_init_response(&hr, HPI_OBJ_ADAPTER,
    652				HPI_ADAPTER_OPEN, HPI_ERROR_BAD_ADAPTER);
    653			memcpy(&rESP_HPI_ADAPTER_OPEN[adapter], &hr,
    654				sizeof(rESP_HPI_ADAPTER_OPEN[adapter]));
    655
    656			hpi_init_response(&hr, HPI_OBJ_MIXER, HPI_MIXER_OPEN,
    657				HPI_ERROR_INVALID_OBJ);
    658			memcpy(&rESP_HPI_MIXER_OPEN[adapter], &hr,
    659				sizeof(rESP_HPI_MIXER_OPEN[adapter]));
    660
    661			for (i = 0; i < HPI_MAX_STREAMS; i++) {
    662				hpi_init_response(&hr, HPI_OBJ_OSTREAM,
    663					HPI_OSTREAM_OPEN,
    664					HPI_ERROR_INVALID_OBJ);
    665				memcpy(&rESP_HPI_OSTREAM_OPEN[adapter][i],
    666					&hr,
    667					sizeof(rESP_HPI_OSTREAM_OPEN[adapter]
    668						[i]));
    669				hpi_init_response(&hr, HPI_OBJ_ISTREAM,
    670					HPI_ISTREAM_OPEN,
    671					HPI_ERROR_INVALID_OBJ);
    672				memcpy(&rESP_HPI_ISTREAM_OPEN[adapter][i],
    673					&hr,
    674					sizeof(rESP_HPI_ISTREAM_OPEN[adapter]
    675						[i]));
    676			}
    677		}
    678	} else if (adapter_index < HPI_MAX_ADAPTERS) {
    679		rESP_HPI_ADAPTER_OPEN[adapter_index].h.error =
    680			HPI_ERROR_BAD_ADAPTER;
    681		rESP_HPI_MIXER_OPEN[adapter_index].h.error =
    682			HPI_ERROR_INVALID_OBJ;
    683		for (i = 0; i < HPI_MAX_STREAMS; i++) {
    684			rESP_HPI_OSTREAM_OPEN[adapter_index][i].h.error =
    685				HPI_ERROR_INVALID_OBJ;
    686			rESP_HPI_ISTREAM_OPEN[adapter_index][i].h.error =
    687				HPI_ERROR_INVALID_OBJ;
    688		}
    689	}
    690}
    691
    692static u16 HPIMSGX__init(struct hpi_message *phm,
    693	/* HPI_SUBSYS_CREATE_ADAPTER structure with */
    694	/* resource list or NULL=find all */
    695	struct hpi_response *phr
    696	/* response from HPI_ADAPTER_GET_INFO */
    697	)
    698{
    699	hpi_handler_func *entry_point_func;
    700	struct hpi_response hr;
    701
    702	/* Init response here so we can pass in previous adapter list */
    703	hpi_init_response(&hr, phm->object, phm->function,
    704		HPI_ERROR_INVALID_OBJ);
    705
    706	entry_point_func =
    707		hpi_lookup_entry_point_function(phm->u.s.resource.r.pci);
    708
    709	if (entry_point_func) {
    710		HPI_DEBUG_MESSAGE(DEBUG, phm);
    711		entry_point_func(phm, &hr);
    712	} else {
    713		phr->error = HPI_ERROR_PROCESSING_MESSAGE;
    714		return phr->error;
    715	}
    716	if (hr.error == 0) {
    717		/* the adapter was created successfully
    718		   save the mapping for future use */
    719		hpi_entry_points[hr.u.s.adapter_index] = entry_point_func;
    720		/* prepare adapter (pre-open streams etc.) */
    721		HPI_DEBUG_LOG(DEBUG,
    722			"HPI_SUBSYS_CREATE_ADAPTER successful,"
    723			" preparing adapter\n");
    724		adapter_prepare(hr.u.s.adapter_index);
    725	}
    726	memcpy(phr, &hr, hr.size);
    727	return phr->error;
    728}
    729
    730static void HPIMSGX__cleanup(u16 adapter_index, void *h_owner)
    731{
    732	int i, adapter, adapter_limit;
    733
    734	if (!h_owner)
    735		return;
    736
    737	if (adapter_index == HPIMSGX_ALLADAPTERS) {
    738		adapter = 0;
    739		adapter_limit = HPI_MAX_ADAPTERS;
    740	} else {
    741		adapter = adapter_index;
    742		adapter_limit = adapter + 1;
    743	}
    744
    745	for (; adapter < adapter_limit; adapter++) {
    746		/*      printk(KERN_INFO "Cleanup adapter #%d\n",wAdapter); */
    747		for (i = 0; i < HPI_MAX_STREAMS; i++) {
    748			if (h_owner ==
    749				outstream_user_open[adapter][i].h_owner) {
    750				struct hpi_message hm;
    751				struct hpi_response hr;
    752
    753				HPI_DEBUG_LOG(DEBUG,
    754					"Close adapter %d ostream %d\n",
    755					adapter, i);
    756
    757				hpi_init_message_response(&hm, &hr,
    758					HPI_OBJ_OSTREAM, HPI_OSTREAM_RESET);
    759				hm.adapter_index = (u16)adapter;
    760				hm.obj_index = (u16)i;
    761				hw_entry_point(&hm, &hr);
    762
    763				hm.function = HPI_OSTREAM_HOSTBUFFER_FREE;
    764				hw_entry_point(&hm, &hr);
    765
    766				hm.function = HPI_OSTREAM_GROUP_RESET;
    767				hw_entry_point(&hm, &hr);
    768
    769				outstream_user_open[adapter][i].open_flag = 0;
    770				outstream_user_open[adapter][i].h_owner =
    771					NULL;
    772			}
    773			if (h_owner == instream_user_open[adapter][i].h_owner) {
    774				struct hpi_message hm;
    775				struct hpi_response hr;
    776
    777				HPI_DEBUG_LOG(DEBUG,
    778					"Close adapter %d istream %d\n",
    779					adapter, i);
    780
    781				hpi_init_message_response(&hm, &hr,
    782					HPI_OBJ_ISTREAM, HPI_ISTREAM_RESET);
    783				hm.adapter_index = (u16)adapter;
    784				hm.obj_index = (u16)i;
    785				hw_entry_point(&hm, &hr);
    786
    787				hm.function = HPI_ISTREAM_HOSTBUFFER_FREE;
    788				hw_entry_point(&hm, &hr);
    789
    790				hm.function = HPI_ISTREAM_GROUP_RESET;
    791				hw_entry_point(&hm, &hr);
    792
    793				instream_user_open[adapter][i].open_flag = 0;
    794				instream_user_open[adapter][i].h_owner = NULL;
    795			}
    796		}
    797	}
    798}