示例#1
0
/** Allocated an area of locked memory for bus master DMA operations.

On error, return -ENOMEM, and *pMemArea.size = 0
*/
u16 HpiOs_LockedMem_Alloc(
	struct consistent_dma_area *pMemArea,
	u32 size,
	struct pci_dev *pdev
)
{
	/*?? any benefit in using managed dmam_alloc_coherent? */
	pMemArea->vaddr =
		dma_alloc_coherent(&pdev->dev, size,
		&pMemArea->dma_handle, GFP_DMA32);

	if (pMemArea->vaddr) {
		HPI_DEBUG_LOG(DEBUG, "Allocated %d bytes, dma 0x%x vma %p\n",
			size,
			(unsigned int)pMemArea->dma_handle, pMemArea->vaddr);
		pMemArea->pdev = &pdev->dev;
		pMemArea->size = size;
		return 0;
	} else {
		HPI_DEBUG_LOG(WARNING,
			"Failed to allocate %d bytes locked memory\n", size);
		pMemArea->size = 0;
		return -ENOMEM;
	}
}
示例#2
0
文件: hpi6000.c 项目: 020gzh/linux
/* create an adapter object and initialise it based on resource information
 * passed in in the message
 * NOTE - you cannot use this function AND the FindAdapters function at the
 * same time, the application must use only one of them to get the adapters
 */
static void subsys_create_adapter(struct hpi_message *phm,
	struct hpi_response *phr)
{
	/* create temp adapter obj, because we don't know what index yet */
	struct hpi_adapter_obj ao;
	struct hpi_adapter_obj *pao;
	u32 os_error_code;
	u16 err = 0;
	u32 dsp_index = 0;

	HPI_DEBUG_LOG(VERBOSE, "subsys_create_adapter\n");

	memset(&ao, 0, sizeof(ao));

	ao.priv = kzalloc(sizeof(struct hpi_hw_obj), GFP_KERNEL);
	if (!ao.priv) {
		HPI_DEBUG_LOG(ERROR, "can't get mem for adapter object\n");
		phr->error = HPI_ERROR_MEMORY_ALLOC;
		return;
	}

	/* create the adapter object based on the resource information */
	ao.pci = *phm->u.s.resource.r.pci;

	err = create_adapter_obj(&ao, &os_error_code);
	if (err) {
		delete_adapter_obj(&ao);
		if (err >= HPI_ERROR_BACKEND_BASE) {
			phr->error = HPI_ERROR_DSP_BOOTLOAD;
			phr->specific_error = err;
		} else {
			phr->error = err;
		}

		phr->u.s.data = os_error_code;
		return;
	}
	/* need to update paParentAdapter */
	pao = hpi_find_adapter(ao.index);
	if (!pao) {
		/* We just added this adapter, why can't we find it!? */
		HPI_DEBUG_LOG(ERROR, "lost adapter after boot\n");
		phr->error = HPI_ERROR_BAD_ADAPTER;
		return;
	}

	for (dsp_index = 0; dsp_index < MAX_DSPS; dsp_index++) {
		struct hpi_hw_obj *phw = pao->priv;
		phw->ado[dsp_index].pa_parent_adapter = pao;
	}

	phr->u.s.adapter_type = ao.type;
	phr->u.s.adapter_index = ao.index;
	phr->error = 0;
}
示例#3
0
/**
* FindAdapter returns a pointer to the struct hpi_adapter_obj with
* index wAdapterIndex in an HPI_ADAPTERS_LIST structure.
*
*/
struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index)
{
	struct hpi_adapter_obj *pao = NULL;

	if (adapter_index >= HPI_MAX_ADAPTERS) {
		HPI_DEBUG_LOG(VERBOSE, "find_adapter invalid index %d\n",
			adapter_index);
		return NULL;
	}

	pao = &adapters.adapter[adapter_index];
	if (pao->type != 0) {
		/*
		   HPI_DEBUG_LOG(VERBOSE, "Found adapter index %d\n",
		   wAdapterIndex);
		 */
		return pao;
	} else {
		/*
		   HPI_DEBUG_LOG(VERBOSE, "No adapter index %d\n",
		   wAdapterIndex);
		 */
		return NULL;
	}
}
示例#4
0
/**
* SubSysGetAdapters fills awAdapterList in an struct hpi_response structure
* with all adapters in the given HPI_ADAPTERS_LIST.
*
*/
static void subsys_get_adapters(struct hpi_response *phr)
{
	/* fill in the response adapter array with the position */
	/* identified by the adapter number/index of the adapters in */
	/* this HPI */
	/* i.e. if we have an A120 with it's jumper set to */
	/* Adapter Number 2 then put an Adapter type A120 in the */
	/* array in position 1 */
	/* NOTE: AdapterNumber is 1..N, Index is 0..N-1 */

	/* input:  NONE */
	/* output: wNumAdapters */
	/*                 awAdapter[] */
	/* */

	short i;
	struct hpi_adapter_obj *pao = NULL;

	HPI_DEBUG_LOG(VERBOSE, "subsys_get_adapters\n");

	/* for each adapter, place it's type in the position of the array */
	/* corresponding to it's adapter number */
	for (i = 0; i < adapters.gw_num_adapters; i++) {
		pao = &adapters.adapter[i];
		if (phr->u.s.aw_adapter_list[pao->index] != 0) {
			phr->error = HPI_DUPLICATE_ADAPTER_NUMBER;
			phr->specific_error = pao->index;
			return;
		}
		phr->u.s.aw_adapter_list[pao->index] = pao->adapter_type;
	}

	phr->u.s.num_adapters = adapters.gw_num_adapters;
	phr->error = 0;	/* the function completed OK; */
}
示例#5
0
static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC)
{
	unsigned int i;
	int cached = 0;
	if (!pC)
		return 0;
	if ((!pC->init) && (pC->p_cache != NULL) && (pC->control_count)
		&& (pC->cache_size_in_bytes)
		) {
		u32 *p_master_cache;
		pC->init = 1;

		p_master_cache = (u32 *)pC->p_cache;
		HPI_DEBUG_LOG(VERBOSE, "check %d controls\n",
			pC->control_count);
		for (i = 0; i < pC->control_count; i++) {
			struct hpi_control_cache_info *info =
				(struct hpi_control_cache_info *)
				p_master_cache;

			if (info->control_type) {
				pC->p_info[i] = info;
				cached++;
			} else
				pC->p_info[i] = NULL;

			if (info->size_in32bit_words)
				p_master_cache += info->size_in32bit_words;
			else
				p_master_cache +=
					sizeof(struct
					hpi_control_cache_single) /
					sizeof(u32);

			HPI_DEBUG_LOG(VERBOSE,
				"cached %d, pinfo %p index %d type %d\n",
				cached, pC->p_info[i], info->control_index,
				info->control_type);
		}
		/*
		   We didn't find anything to cache, so try again later !
		 */
		if (!cached)
			pC->init = 0;
	}
	return pC->init;
}
示例#6
0
/*-------------------------------------------------------------------*/
void hpi_dsp_code_close(struct dsp_code *ps_dsp_code)
{
	if (ps_dsp_code->ps_firmware != NULL) {
		HPI_DEBUG_LOG(DEBUG, "dsp code closed\n");
		release_firmware(ps_dsp_code->ps_firmware);
		ps_dsp_code->ps_firmware = NULL;
	}
}
示例#7
0
/** Find a control.
*/
static short find_control(u16 control_index,
	struct hpi_control_cache *p_cache, struct hpi_control_cache_info **pI)
{
	if (!control_cache_alloc_check(p_cache)) {
		HPI_DEBUG_LOG(VERBOSE,
			"control_cache_alloc_check() failed %d\n",
			control_index);
		return 0;
	}

	*pI = p_cache->p_info[control_index];
	if (!*pI) {
		HPI_DEBUG_LOG(VERBOSE, "Uncached Control %d\n",
			control_index);
		return 0;
	} else {
		HPI_DEBUG_LOG(VERBOSE, "find_control() type %d\n",
			(*pI)->control_type);
	}
	return 1;
}
示例#8
0
/**
* Given an HPI Message that was sent out and a response that was received,
* validate that the response has the correct fields filled in,
* i.e ObjectType, Function etc
**/
u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr)
{
	if (phr->type != HPI_TYPE_RESPONSE) {
		HPI_DEBUG_LOG(ERROR, "header type %d invalid\n", phr->type);
		return HPI_ERROR_INVALID_RESPONSE;
	}

	if (phr->object != phm->object) {
		HPI_DEBUG_LOG(ERROR, "header object %d invalid\n",
			phr->object);
		return HPI_ERROR_INVALID_RESPONSE;
	}

	if (phr->function != phm->function) {
		HPI_DEBUG_LOG(ERROR, "header function %d invalid\n",
			phr->function);
		return HPI_ERROR_INVALID_RESPONSE;
	}

	return 0;
}
示例#9
0
void hpi_delete_adapter(struct hpi_adapter_obj *pao)
{
	if (!pao->type) {
		HPI_DEBUG_LOG(ERROR, "removing null adapter?\n");
		return;
	}

	hpios_alistlock_lock(&adapters);
	if (adapters.adapter[pao->index].type)
		adapters.gw_num_adapters--;
	memset(&adapters.adapter[pao->index], 0, sizeof(adapters.adapter[0]));
	hpios_alistlock_unlock(&adapters);
}
示例#10
0
/** Allocate an area of locked memory for bus master DMA operations.

If allocation fails, return 1, and *pMemArea.size = 0
*/
u16 hpios_locked_mem_alloc(struct consistent_dma_area *p_mem_area, u32 size,
	struct pci_dev *pdev)
{
	/*?? any benefit in using managed dmam_alloc_coherent? */
	p_mem_area->vaddr =
		dma_alloc_coherent(&pdev->dev, size, &p_mem_area->dma_handle,
		GFP_DMA32 | GFP_KERNEL);

	if (p_mem_area->vaddr) {
		HPI_DEBUG_LOG(DEBUG, "allocated %d bytes, dma 0x%x vma %p\n",
			size, (unsigned int)p_mem_area->dma_handle,
			p_mem_area->vaddr);
		p_mem_area->pdev = &pdev->dev;
		p_mem_area->size = size;
		return 0;
	} else {
		HPI_DEBUG_LOG(WARNING,
			"failed to allocate %d bytes locked memory\n", size);
		p_mem_area->size = 0;
		return 1;
	}
}
示例#11
0
文件: hpios.c 项目: CSCLOG/beaglebone
u16 hpios_locked_mem_free(struct consistent_dma_area *p_mem_area)
{
	if (p_mem_area->size) {
		dma_free_coherent(p_mem_area->pdev, p_mem_area->size,
			p_mem_area->vaddr, p_mem_area->dma_handle);
		HPI_DEBUG_LOG(DEBUG, "freed %lu bytes, dma 0x%x vma %p\n",
			(unsigned long)p_mem_area->size,
			(unsigned int)p_mem_area->dma_handle,
			p_mem_area->vaddr);
		p_mem_area->size = 0;
		return 0;
	} else {
		return 1;
	}
}
示例#12
0
/** Find a control.
*/
static short find_control(struct hpi_message *phm,
	struct hpi_control_cache *p_cache, struct hpi_control_cache_info **pI,
	u16 *pw_control_index)
{
	*pw_control_index = phm->obj_index;

	if (!control_cache_alloc_check(p_cache)) {
		HPI_DEBUG_LOG(VERBOSE,
			"control_cache_alloc_check() failed. adap%d ci%d\n",
			phm->adapter_index, *pw_control_index);
		return 0;
	}

	*pI = p_cache->p_info[*pw_control_index];
	if (!*pI) {
		HPI_DEBUG_LOG(VERBOSE, "uncached adap %d, control %d\n",
			phm->adapter_index, *pw_control_index);
		return 0;
	} else {
		HPI_DEBUG_LOG(VERBOSE, "find_control() type %d\n",
			(*pI)->control_type);
	}
	return 1;
}
示例#13
0
uint16_t HpiOs_LockedMem_Free(
	struct consistent_dma_area * pMemArea
)
{
	if (pMemArea->size) {
		dma_free_coherent(pMemArea->pdev, pMemArea->size,
			pMemArea->vaddr, pMemArea->dma_handle);
		HPI_DEBUG_LOG(DEBUG, "Freed %lu bytes, dma 0x%x vma %p\n",
			(unsigned long)pMemArea->size,
			(unsigned int)pMemArea->dma_handle, pMemArea->vaddr);
		pMemArea->size = 0;
		return 0;
	} else {
		return 1;
	}
}
示例#14
0
u16 hpi_add_adapter(struct hpi_adapter_obj *pao)
{
	u16 retval = 0;
	/*HPI_ASSERT(pao->type); */

	hpios_alistlock_lock(&adapters);

	if (pao->index >= HPI_MAX_ADAPTERS) {
		retval = HPI_ERROR_BAD_ADAPTER_NUMBER;
		goto unlock;
	}

	if (adapters.adapter[pao->index].type) {
		int a;
		for (a = HPI_MAX_ADAPTERS - 1; a >= 0; a--) {
			if (!adapters.adapter[a].type) {
				HPI_DEBUG_LOG(WARNING,
					"ASI%X duplicate index %d moved to %d\n",
					pao->type, pao->index, a);
				pao->index = a;
				break;
			}
		}
		if (a < 0) {
			retval = HPI_ERROR_DUPLICATE_ADAPTER_NUMBER;
			goto unlock;
		}
	}
	adapters.adapter[pao->index] = *pao;
	hpios_dsplock_init(&adapters.adapter[pao->index]);
	adapters.gw_num_adapters++;

unlock:
	hpios_alistlock_unlock(&adapters);
	return retval;
}
示例#15
0
文件: hpi6000.c 项目: 020gzh/linux
/** HPI_6000()
 * Entry point from HPIMAN
 * All calls to the HPI start here
 */
void HPI_6000(struct hpi_message *phm, struct hpi_response *phr)
{
	struct hpi_adapter_obj *pao = NULL;

	if (phm->object != HPI_OBJ_SUBSYSTEM) {
		pao = hpi_find_adapter(phm->adapter_index);
		if (!pao) {
			hpi_init_response(phr, phm->object, phm->function,
				HPI_ERROR_BAD_ADAPTER_NUMBER);
			HPI_DEBUG_LOG(DEBUG, "invalid adapter index: %d \n",
				phm->adapter_index);
			return;
		}

		/* Don't even try to communicate with crashed DSP */
		if (pao->dsp_crashed >= 10) {
			hpi_init_response(phr, phm->object, phm->function,
				HPI_ERROR_DSP_HARDWARE);
			HPI_DEBUG_LOG(DEBUG, "adapter %d dsp crashed\n",
				phm->adapter_index);
			return;
		}
	}
	/* Init default response including the size field */
	if (phm->function != HPI_SUBSYS_CREATE_ADAPTER)
		hpi_init_response(phr, phm->object, phm->function,
			HPI_ERROR_PROCESSING_MESSAGE);

	switch (phm->type) {
	case HPI_TYPE_REQUEST:
		switch (phm->object) {
		case HPI_OBJ_SUBSYSTEM:
			subsys_message(phm, phr);
			break;

		case HPI_OBJ_ADAPTER:
			phr->size =
				sizeof(struct hpi_response_header) +
				sizeof(struct hpi_adapter_res);
			adapter_message(pao, phm, phr);
			break;

		case HPI_OBJ_CONTROL:
			control_message(pao, phm, phr);
			break;

		case HPI_OBJ_OSTREAM:
			outstream_message(pao, phm, phr);
			break;

		case HPI_OBJ_ISTREAM:
			instream_message(pao, phm, phr);
			break;

		default:
			hw_message(pao, phm, phr);
			break;
		}
		break;

	default:
		phr->error = HPI_ERROR_INVALID_TYPE;
		break;
	}
}
示例#16
0
/* create an adapter object and initialise it based on resource information
 * passed in in the message
 * NOTE - you cannot use this function AND the FindAdapters function at the
 * same time, the application must use only one of them to get the adapters
 */
static void subsys_create_adapter(struct hpi_message *phm,
	struct hpi_response *phr)
{
	/* create temp adapter obj, because we don't know what index yet */
	struct hpi_adapter_obj ao;
	struct hpi_adapter_obj *pao;
	u32 os_error_code;
	short error = 0;
	u32 dsp_index = 0;

	HPI_DEBUG_LOG(VERBOSE, "subsys_create_adapter\n");

	memset(&ao, 0, sizeof(ao));

	/* this HPI only creates adapters for TI/PCI2040 based devices */
	if (phm->u.s.resource.bus_type != HPI_BUS_PCI)
		return;
	if (phm->u.s.resource.r.pci->vendor_id != HPI_PCI_VENDOR_ID_TI)
		return;
	if (phm->u.s.resource.r.pci->device_id != HPI_PCI_DEV_ID_PCI2040)
		return;

	ao.priv = kzalloc(sizeof(struct hpi_hw_obj), GFP_KERNEL);
	if (!ao.priv) {
		HPI_DEBUG_LOG(ERROR, "cant get mem for adapter object\n");
		phr->error = HPI_ERROR_MEMORY_ALLOC;
		return;
	}

	/* create the adapter object based on the resource information */
	/*? memcpy(&ao.Pci,&phm->u.s.Resource.r.Pci,sizeof(ao.Pci)); */
	ao.pci = *phm->u.s.resource.r.pci;

	error = create_adapter_obj(&ao, &os_error_code);
	if (!error)
		error = hpi_add_adapter(&ao);
	if (error) {
		phr->u.s.data = os_error_code;
		kfree(ao.priv);
		phr->error = error;
		return;
	}
	/* need to update paParentAdapter */
	pao = hpi_find_adapter(ao.index);
	if (!pao) {
		/* We just added this adapter, why can't we find it!? */
		HPI_DEBUG_LOG(ERROR, "lost adapter after boot\n");
		phr->error = 950;
		return;
	}

	for (dsp_index = 0; dsp_index < MAX_DSPS; dsp_index++) {
		struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv;
		phw->ado[dsp_index].pa_parent_adapter = pao;
	}

	phr->u.s.aw_adapter_list[ao.index] = ao.adapter_type;
	phr->u.s.adapter_index = ao.index;
	phr->u.s.num_adapters++;
	phr->error = 0;
}
示例#17
0
/*-------------------------------------------------------------------*/
short hpi_dsp_code_open(u32 adapter, struct dsp_code *ps_dsp_code,
	u32 *pos_error_code)
{
	const struct firmware *ps_firmware = ps_dsp_code->ps_firmware;
	struct code_header header;
	char fw_name[20];
	int err;

	sprintf(fw_name, "asihpi/dsp%04x.bin", adapter);
	HPI_DEBUG_LOG(INFO, "requesting firmware for %s\n", fw_name);

	err = request_firmware(&ps_firmware, fw_name,
		&ps_dsp_code->ps_dev->dev);
	if (err != 0) {
		HPI_DEBUG_LOG(ERROR, "%d, request_firmware failed for  %s\n",
			err, fw_name);
		goto error1;
	}
	if (ps_firmware->size < sizeof(header)) {
		HPI_DEBUG_LOG(ERROR, "header size too small %s\n", fw_name);
		goto error2;
	}
	memcpy(&header, ps_firmware->data, sizeof(header));
	if (header.adapter != adapter) {
		HPI_DEBUG_LOG(ERROR, "adapter type incorrect %4x != %4x\n",
			header.adapter, adapter);
		goto error2;
	}
	if (header.size != ps_firmware->size) {
		HPI_DEBUG_LOG(ERROR, "code size wrong  %d != %ld\n",
			header.size, (unsigned long)ps_firmware->size);
		goto error2;
	}

	if (header.version / 10000 != HPI_VER_DECIMAL / 10000) {
		HPI_DEBUG_LOG(ERROR,
			"firmware major version mismatch "
			"DSP image %d != driver %d\n", header.version,
			HPI_VER_DECIMAL);
		goto error2;
	}

	if (header.version != HPI_VER_DECIMAL) {
		HPI_DEBUG_LOG(WARNING,
			"version mismatch  DSP image %d != driver %d\n",
			header.version, HPI_VER_DECIMAL);
		/* goto error2;  still allow driver to load */
	}

	HPI_DEBUG_LOG(INFO, "dsp code %s opened\n", fw_name);
	ps_dsp_code->ps_firmware = ps_firmware;
	ps_dsp_code->block_length = header.size / sizeof(u32);
	ps_dsp_code->word_count = sizeof(header) / sizeof(u32);
	ps_dsp_code->version = header.version;
	ps_dsp_code->crc = header.crc;
	return 0;

error2:
	release_firmware(ps_firmware);
error1:
	ps_dsp_code->ps_firmware = NULL;
	ps_dsp_code->block_length = 0;
	return HPI_ERROR_DSP_FILE_NOT_FOUND;
}
示例#18
0
文件: hpi6000.c 项目: sklvjz/alsa
/* create an adapter object and initialise it based on resource information
 * passed in in the message
 * NOTE - you cannot use this function AND the FindAdapters function at the
 * same time, the application must use only one of them to get the adapters
 */
static void SubSysCreateAdapter(
	struct hpi_message *phm,
	struct hpi_response *phr
)
{
	/* create temp adapter obj, because we don't know what index yet */
	struct hpi_adapter_obj ao;
	struct hpi_adapter_obj *pao;
	u32 dwOsErrorCode;
	short nError = 0;
	u32 dwDspIndex = 0;

	HPI_DEBUG_LOG(VERBOSE, "SubSysCreateAdapter\n");

	memset(&ao, 0, sizeof(ao));

	/* this HPI only creates adapters for TI/PCI2040 based devices */
	if (phm->u.s.Resource.wBusType != HPI_BUS_PCI)
		return;
	if (phm->u.s.Resource.r.Pci->wVendorId != HPI_PCI_VENDOR_ID_TI)
		return;
	if (phm->u.s.Resource.r.Pci->wDeviceId != HPI_ADAPTER_PCI2040)
		return;

	ao.priv = kmalloc(sizeof(struct hpi_hw_obj), GFP_KERNEL);
	if (!ao.priv) {
		HPI_DEBUG_LOG(ERROR, "cant get mem for adapter object\n");
		phr->wError = HPI_ERROR_MEMORY_ALLOC;
		return;
	}

	memset(ao.priv, 0, sizeof(struct hpi_hw_obj));
	/* create the adapter object based on the resource information */
	/*? memcpy(&ao.Pci,&phm->u.s.Resource.r.Pci,sizeof(ao.Pci)); */
	ao.Pci = *phm->u.s.Resource.r.Pci;

	nError = CreateAdapterObj(&ao, &dwOsErrorCode);
	if (!nError)
		nError = HpiAddAdapter(&ao);
	if (nError) {
		phr->u.s.dwData = dwOsErrorCode;
		kfree(ao.priv);
		phr->wError = nError;
		return;
	}
	/* need to update paParentAdapter */
	pao = HpiFindAdapter(ao.wIndex);
	if (!pao) {
		/* We just added this adapter, why can't we find it!? */
		HPI_DEBUG_LOG(ERROR, "lost adapter after boot\n");
		phr->wError = 950;
		return;
	}

	for (dwDspIndex = 0; dwDspIndex < MAX_DSPS; dwDspIndex++) {
		struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv;
		phw->ado[dwDspIndex].paParentAdapter = pao;
	}

	phr->u.s.awAdapterList[ao.wIndex] = ao.wAdapterType;
	phr->u.s.wAdapterIndex = ao.wIndex;
	phr->u.s.wNumAdapters++;
	phr->wError = 0;
}
示例#19
0
文件: hpi6000.c 项目: sklvjz/alsa
/* this routine is called from SubSysFindAdapter and SubSysCreateAdapter */
static short CreateAdapterObj(
	struct hpi_adapter_obj *pao,
	u32 *pdwOsErrorCode
)
{
	short nBootError = 0;
	u32 dwDspIndex = 0;
	u32 dwControlCacheSize = 0;
	u32 dwControlCacheCount = 0;
	struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv;

	/* init error reporting */
	pao->wDspCrashed = 0;

	/* The PCI2040 has the following address map */
	/* BAR0 - 4K = HPI control and status registers on PCI2040 (HPI CSR) */
	/* BAR1 - 32K = HPI registers on DSP */
	phw->dw2040_HPICSR = pao->Pci.apMemBase[0];
	phw->dw2040_HPIDSP = pao->Pci.apMemBase[1];
	HPI_DEBUG_LOG(VERBOSE, "csr %p, dsp %p\n",
		phw->dw2040_HPICSR, phw->dw2040_HPIDSP);

	/* set addresses for the possible DSP HPI interfaces */
	for (dwDspIndex = 0; dwDspIndex < MAX_DSPS; dwDspIndex++) {
		phw->ado[dwDspIndex].prHPIControl =
			phw->dw2040_HPIDSP + (CONTROL +
			DSP_SPACING * dwDspIndex);

		phw->ado[dwDspIndex].prHPIAddress =
			phw->dw2040_HPIDSP + (ADDRESS +
			DSP_SPACING * dwDspIndex);
		phw->ado[dwDspIndex].prHPIData =
			phw->dw2040_HPIDSP + (DATA +
			DSP_SPACING * dwDspIndex);

		phw->ado[dwDspIndex].prHPIDataAutoInc =
			phw->dw2040_HPIDSP +
			(DATA_AUTOINC + DSP_SPACING * dwDspIndex);

		HPI_DEBUG_LOG(VERBOSE, "ctl %p, adr %p, dat %p, dat++ %p\n",
			phw->ado[dwDspIndex].prHPIControl,
			phw->ado[dwDspIndex].prHPIAddress,
			phw->ado[dwDspIndex].prHPIData,
			phw->ado[dwDspIndex].prHPIDataAutoInc);

		phw->ado[dwDspIndex].paParentAdapter = pao;
	}

	phw->dwPCI2040HPIErrorCount = 0;
	pao->wHasControlCache = 0;

	/* Set the default number of DSPs on this card */
	/* This is (conditionally) adjusted after bootloading */
	/* of the first DSP in the bootload section. */
	phw->wNumDsp = 1;

	nBootError = Hpi6000_AdapterBootLoadDsp(pao, pdwOsErrorCode);
	if (nBootError)
		return (nBootError);

	HPI_DEBUG_LOG(INFO, "Bootload DSP OK\n");

	phw->dwMessageBufferAddressOnDSP = 0L;
	phw->dwResponseBufferAddressOnDSP = 0L;

	/* get info about the adapter by asking the adapter */
	/* send a HPI_ADAPTER_GET_INFO message */
	{
		struct hpi_message hM;
		struct hpi_response hR0;	/* response from DSP 0 */
		struct hpi_response hR1;	/* response from DSP 1 */
		u16 wError = 0;

		HPI_DEBUG_LOG(VERBOSE, "send ADAPTER_GET_INFO\n");
		memset(&hM, 0, sizeof(hM));
		hM.wType = HPI_TYPE_MESSAGE;
		hM.wSize = sizeof(struct hpi_message);
		hM.wObject = HPI_OBJ_ADAPTER;
		hM.wFunction = HPI_ADAPTER_GET_INFO;
		hM.wAdapterIndex = 0;
		hM.wDspIndex = 0;
		memset(&hR0, 0, sizeof(hR0));
		memset(&hR1, 0, sizeof(hR1));
		hR0.wSize = sizeof(hR0);
		hR1.wSize = sizeof(hR1);

		wError = Hpi6000_MessageResponseSequence(pao, &hM, &hR0);
		if (hR0.wError) {
			HPI_DEBUG_LOG(DEBUG, "message error %d\n",
				hR0.wError);
			return (hR0.wError);	/*error */
		}
		if (phw->wNumDsp == 2) {
			hM.wDspIndex = 1;
			wError = Hpi6000_MessageResponseSequence(pao, &hM,
				&hR1);
			if (wError)
				return wError;
		}
		pao->wAdapterType = hR0.u.a.wAdapterType;
		pao->wIndex = hR0.u.a.wAdapterIndex;
	}

	memset(&phw->aControlCache[0], 0,
		sizeof(struct hpi_control_cache_single) *
		HPI_NMIXER_CONTROLS);
	/* Read the control cache length to figure out if it is turned on */
	dwControlCacheSize = HpiReadWord(&phw->ado[0],
		HPI_HIF_ADDR(dwControlCacheSizeInBytes));
	if (dwControlCacheSize) {
		dwControlCacheCount = HpiReadWord(&phw->ado[0],
			HPI_HIF_ADDR(dwControlCacheCount));
		pao->wHasControlCache = 1;

		phw->pCache = HpiAllocControlCache(dwControlCacheCount,
			dwControlCacheSize, (struct hpi_control_cache_info *)
			&phw->aControlCache[0]
			);
	} else
		pao->wHasControlCache = 0;

	HPI_DEBUG_LOG(DEBUG, "Get adapter info ASI%04X index %d\n",
		pao->wAdapterType, pao->wIndex);
	pao->wOpen = 0;	/* upon creation the adapter is closed */
	return 0;
}
示例#20
0
文件: hpi6000.c 项目: sklvjz/alsa
/** HPI_6000()
 * Entry point from HPIMAN
 * All calls to the HPI start here
 */
void HPI_6000(
	struct hpi_message *phm,
	struct hpi_response *phr
)
{
	struct hpi_adapter_obj *pao = NULL;

	/* subsytem messages get executed by every HPI. */
	/* All other messages are ignored unless the adapter index matches */
	/* an adapter in the HPI */
	HPI_DEBUG_LOG(DEBUG, "O %d,F %x\n", phm->wObject, phm->wFunction);

	/* if Dsp has crashed then do not communicate with it any more */
	if (phm->wObject != HPI_OBJ_SUBSYSTEM) {
		pao = HpiFindAdapter(phm->wAdapterIndex);
		if (!pao) {
			HPI_DEBUG_LOG(DEBUG,
				" %d,%d refused, for another HPI?\n",
				phm->wObject, phm->wFunction);
			return;
		}

		if (pao->wDspCrashed >= 10) {
			HPI_InitResponse(phr, phm->wObject, phm->wFunction,
				HPI_ERROR_DSP_HARDWARE);
			HPI_DEBUG_LOG(DEBUG, " %d,%d dsp crashed.\n",
				phm->wObject, phm->wFunction);
			return;
		}
	}
	/* Init default response including the size field */
	if (phm->wFunction != HPI_SUBSYS_CREATE_ADAPTER)
		HPI_InitResponse(phr, phm->wObject, phm->wFunction,
			HPI_ERROR_PROCESSING_MESSAGE);

	switch (phm->wType) {
	case HPI_TYPE_MESSAGE:
		switch (phm->wObject) {
		case HPI_OBJ_SUBSYSTEM:
			SubSysMessage(phm, phr);
			break;

		case HPI_OBJ_ADAPTER:
			phr->wSize =
				sizeof(struct hpi_response_header) +
				sizeof(struct hpi_adapter_res);
			AdapterMessage(pao, phm, phr);
			break;

		case HPI_OBJ_CONTROL:
			ControlMessage(pao, phm, phr);
			break;

		case HPI_OBJ_OSTREAM:
			OStreamMessage(pao, phm, phr);
			break;

		case HPI_OBJ_ISTREAM:
			IStreamMessage(pao, phm, phr);
			break;

		default:
			HW_Message(pao, phm, phr);
			break;
		}
		break;

	default:
		phr->wError = HPI_ERROR_INVALID_TYPE;
		break;
	}
}
示例#21
0
文件: hpi6000.c 项目: 020gzh/linux
static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
	u32 *pos_error_code)
{
	struct hpi_hw_obj *phw = pao->priv;
	short error;
	u32 timeout;
	u32 read = 0;
	u32 i = 0;
	u32 data = 0;
	u32 j = 0;
	u32 test_addr = 0x80000000;
	u32 test_data = 0x00000001;
	u32 dw2040_reset = 0;
	u32 dsp_index = 0;
	u32 endian = 0;
	u32 adapter_info = 0;
	u32 delay = 0;

	struct dsp_code dsp_code;
	u16 boot_load_family = 0;

	/* NOTE don't use wAdapterType in this routine. It is not setup yet */

	switch (pao->pci.pci_dev->subsystem_device) {
	case 0x5100:
	case 0x5110:	/* ASI5100 revB or higher with C6711D */
	case 0x5200:	/* ASI5200 PCIe version of ASI5100 */
	case 0x6100:
	case 0x6200:
		boot_load_family = HPI_ADAPTER_FAMILY_ASI(0x6200);
		break;
	default:
		return HPI6000_ERROR_UNHANDLED_SUBSYS_ID;
	}

	/* reset all DSPs, indicate two DSPs are present
	 * set RST3-=1 to disconnect HAD8 to set DSP in little endian mode
	 */
	endian = 0;
	dw2040_reset = 0x0003000F;
	iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET);

	/* read back register to make sure PCI2040 chip is functioning
	 * note that bits 4..15 are read-only and so should always return zero,
	 * even though we wrote 1 to them
	 */
	hpios_delay_micro_seconds(1000);
	delay = ioread32(phw->dw2040_HPICSR + HPI_RESET);

	if (delay != dw2040_reset) {
		HPI_DEBUG_LOG(ERROR, "INIT_PCI2040 %x %x\n", dw2040_reset,
			delay);
		return HPI6000_ERROR_INIT_PCI2040;
	}

	/* Indicate that DSP#0,1 is a C6X */
	iowrite32(0x00000003, phw->dw2040_HPICSR + HPI_DATA_WIDTH);
	/* set Bit30 and 29 - which will prevent Target aborts from being
	 * issued upon HPI or GP error
	 */
	iowrite32(0x60000000, phw->dw2040_HPICSR + INTERRUPT_MASK_SET);

	/* isolate DSP HAD8 line from PCI2040 so that
	 * Little endian can be set by pullup
	 */
	dw2040_reset = dw2040_reset & (~(endian << 3));
	iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET);

	phw->ado[0].c_dsp_rev = 'B';	/* revB */
	phw->ado[1].c_dsp_rev = 'B';	/* revB */

	/*Take both DSPs out of reset, setting HAD8 to the correct Endian */
	dw2040_reset = dw2040_reset & (~0x00000001);	/* start DSP 0 */
	iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET);
	dw2040_reset = dw2040_reset & (~0x00000002);	/* start DSP 1 */
	iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET);

	/* set HAD8 back to PCI2040, now that DSP set to little endian mode */
	dw2040_reset = dw2040_reset & (~0x00000008);
	iowrite32(dw2040_reset, phw->dw2040_HPICSR + HPI_RESET);
	/*delay to allow DSP to get going */
	hpios_delay_micro_seconds(100);

	/* loop through all DSPs, downloading DSP code */
	for (dsp_index = 0; dsp_index < phw->num_dsp; dsp_index++) {
		struct dsp_obj *pdo = &phw->ado[dsp_index];

		/* configure DSP so that we download code into the SRAM */
		/* set control reg for little endian, HWOB=1 */
		iowrite32(0x00010001, pdo->prHPI_control);

		/* test access to the HPI address register (HPIA) */
		test_data = 0x00000001;
		for (j = 0; j < 32; j++) {
			iowrite32(test_data, pdo->prHPI_address);
			data = ioread32(pdo->prHPI_address);
			if (data != test_data) {
				HPI_DEBUG_LOG(ERROR, "INIT_DSPHPI %x %x %x\n",
					test_data, data, dsp_index);
				return HPI6000_ERROR_INIT_DSPHPI;
			}
			test_data = test_data << 1;
		}

/* if C6713 the setup PLL to generate 225MHz from 25MHz.
* Since the PLLDIV1 read is sometimes wrong, even on a C6713,
* we're going to do this unconditionally
*/
/* PLLDIV1 should have a value of 8000 after reset */
/*
	if (HpiReadWord(pdo,0x01B7C118) == 0x8000)
*/
		{
			/* C6713 datasheet says we cannot program PLL from HPI,
			 * and indeed if we try to set the PLL multiply from the
			 * HPI, the PLL does not seem to lock,
			 * so we enable the PLL and use the default of x 7
			 */
			/* bypass PLL */
			hpi_write_word(pdo, 0x01B7C100, 0x0000);
			hpios_delay_micro_seconds(100);

			/*  ** use default of PLL  x7 ** */
			/* EMIF = 225/3=75MHz */
			hpi_write_word(pdo, 0x01B7C120, 0x8002);
			hpios_delay_micro_seconds(100);

			/* peri = 225/2 */
			hpi_write_word(pdo, 0x01B7C11C, 0x8001);
			hpios_delay_micro_seconds(100);

			/* cpu  = 225/1 */
			hpi_write_word(pdo, 0x01B7C118, 0x8000);

			/* ~2ms delay */
			hpios_delay_micro_seconds(2000);

			/* PLL not bypassed */
			hpi_write_word(pdo, 0x01B7C100, 0x0001);
			/* ~2ms delay */
			hpios_delay_micro_seconds(2000);
		}

		/* test r/w to internal DSP memory
		 * C6711 has L2 cache mapped to 0x0 when reset
		 *
		 *  revB - because of bug 3.0.1 last HPI read
		 * (before HPI address issued) must be non-autoinc
		 */
		/* test each bit in the 32bit word */
		for (i = 0; i < 100; i++) {
			test_addr = 0x00000000;
			test_data = 0x00000001;
			for (j = 0; j < 32; j++) {
				hpi_write_word(pdo, test_addr + i, test_data);
				data = hpi_read_word(pdo, test_addr + i);
				if (data != test_data) {
					HPI_DEBUG_LOG(ERROR,
						"DSP mem %x %x %x %x\n",
						test_addr + i, test_data,
						data, dsp_index);

					return HPI6000_ERROR_INIT_DSPINTMEM;
				}
				test_data = test_data << 1;
			}
		}

		/* memory map of ASI6200
		   00000000-0000FFFF    16Kx32 internal program
		   01800000-019FFFFF    Internal peripheral
		   80000000-807FFFFF    CE0 2Mx32 SDRAM running @ 100MHz
		   90000000-9000FFFF    CE1 Async peripherals:

		   EMIF config
		   ------------
		   Global EMIF control
		   0 -
		   1 -
		   2 -
		   3 CLK2EN = 1   CLKOUT2 enabled
		   4 CLK1EN = 0   CLKOUT1 disabled
		   5 EKEN = 1 <--!! C6713 specific, enables ECLKOUT
		   6 -
		   7 NOHOLD = 1   external HOLD disabled
		   8 HOLDA = 0    HOLDA output is low
		   9 HOLD = 0             HOLD input is low
		   10 ARDY = 1    ARDY input is high
		   11 BUSREQ = 0   BUSREQ output is low
		   12,13 Reserved = 1
		 */
		hpi_write_word(pdo, 0x01800000, 0x34A8);

		/* EMIF CE0 setup - 2Mx32 Sync DRAM
		   31..28       Wr setup
		   27..22       Wr strobe
		   21..20       Wr hold
		   19..16       Rd setup
		   15..14       -
		   13..8        Rd strobe
		   7..4         MTYPE   0011            Sync DRAM 32bits
		   3            Wr hold MSB
		   2..0         Rd hold
		 */
		hpi_write_word(pdo, 0x01800008, 0x00000030);

		/* EMIF SDRAM Extension
		   31-21        0
		   20           WR2RD = 0
		   19-18        WR2DEAC = 1
		   17           WR2WR = 0
		   16-15        R2WDQM = 2
		   14-12        RD2WR = 4
		   11-10        RD2DEAC = 1
		   9            RD2RD = 1
		   8-7          THZP = 10b
		   6-5          TWR  = 2-1 = 01b (tWR = 10ns)
		   4            TRRD = 0b = 2 ECLK (tRRD = 14ns)
		   3-1          TRAS = 5-1 = 100b (Tras=42ns = 5 ECLK)
		   1            CAS latency = 3 ECLK
		   (for Micron 2M32-7 operating at 100Mhz)
		 */

		/* need to use this else DSP code crashes */
		hpi_write_word(pdo, 0x01800020, 0x001BDF29);

		/* EMIF SDRAM control - set up for a 2Mx32 SDRAM (512x32x4 bank)
		   31           -               -
		   30           SDBSZ   1               4 bank
		   29..28       SDRSZ   00              11 row address pins
		   27..26       SDCSZ   01              8 column address pins
		   25           RFEN    1               refersh enabled
		   24           INIT    1               init SDRAM
		   23..20       TRCD    0001
		   19..16       TRP             0001
		   15..12       TRC             0110
		   11..0        -               -
		 */
		/*      need to use this else DSP code crashes */
		hpi_write_word(pdo, 0x01800018, 0x47117000);

		/* EMIF SDRAM Refresh Timing */
		hpi_write_word(pdo, 0x0180001C, 0x00000410);

		/*MIF CE1 setup - Async peripherals
		   @100MHz bus speed, each cycle is 10ns,
		   31..28       Wr setup  = 1
		   27..22       Wr strobe = 3                   30ns
		   21..20       Wr hold = 1
		   19..16       Rd setup =1
		   15..14       Ta = 2
		   13..8        Rd strobe = 3                   30ns
		   7..4         MTYPE   0010            Async 32bits
		   3            Wr hold MSB =0
		   2..0         Rd hold = 1
		 */
		{
			u32 cE1 =
				(1L << 28) | (3L << 22) | (1L << 20) | (1L <<
				16) | (2L << 14) | (3L << 8) | (2L << 4) | 1L;
			hpi_write_word(pdo, 0x01800004, cE1);
		}

		/* delay a little to allow SDRAM and DSP to "get going" */
		hpios_delay_micro_seconds(1000);

		/* test access to SDRAM */
		{
			test_addr = 0x80000000;
			test_data = 0x00000001;
			/* test each bit in the 32bit word */
			for (j = 0; j < 32; j++) {
				hpi_write_word(pdo, test_addr, test_data);
				data = hpi_read_word(pdo, test_addr);
				if (data != test_data) {
					HPI_DEBUG_LOG(ERROR,
						"DSP dram %x %x %x %x\n",
						test_addr, test_data, data,
						dsp_index);

					return HPI6000_ERROR_INIT_SDRAM1;
				}
				test_data = test_data << 1;
			}
			/* test every Nth address in the DRAM */
#define DRAM_SIZE_WORDS 0x200000	/*2_mx32 */
#define DRAM_INC 1024
			test_addr = 0x80000000;
			test_data = 0x0;
			for (i = 0; i < DRAM_SIZE_WORDS; i = i + DRAM_INC) {
				hpi_write_word(pdo, test_addr + i, test_data);
				test_data++;
			}
			test_addr = 0x80000000;
			test_data = 0x0;
			for (i = 0; i < DRAM_SIZE_WORDS; i = i + DRAM_INC) {
				data = hpi_read_word(pdo, test_addr + i);
				if (data != test_data) {
					HPI_DEBUG_LOG(ERROR,
						"DSP dram %x %x %x %x\n",
						test_addr + i, test_data,
						data, dsp_index);
					return HPI6000_ERROR_INIT_SDRAM2;
				}
				test_data++;
			}

		}

		/* write the DSP code down into the DSPs memory */
		error = hpi_dsp_code_open(boot_load_family, pao->pci.pci_dev,
			&dsp_code, pos_error_code);

		if (error)
			return error;

		while (1) {
			u32 length;
			u32 address;
			u32 type;
			u32 *pcode;

			error = hpi_dsp_code_read_word(&dsp_code, &length);
			if (error)
				break;
			if (length == 0xFFFFFFFF)
				break;	/* end of code */

			error = hpi_dsp_code_read_word(&dsp_code, &address);
			if (error)
				break;
			error = hpi_dsp_code_read_word(&dsp_code, &type);
			if (error)
				break;
			error = hpi_dsp_code_read_block(length, &dsp_code,
				&pcode);
			if (error)
				break;
			error = hpi6000_dsp_block_write32(pao, (u16)dsp_index,
				address, pcode, length);
			if (error)
				break;
		}

		if (error) {
			hpi_dsp_code_close(&dsp_code);
			return error;
		}
		/* verify that code was written correctly */
		/* this time through, assume no errors in DSP code file/array */
		hpi_dsp_code_rewind(&dsp_code);
		while (1) {
			u32 length;
			u32 address;
			u32 type;
			u32 *pcode;

			hpi_dsp_code_read_word(&dsp_code, &length);
			if (length == 0xFFFFFFFF)
				break;	/* end of code */

			hpi_dsp_code_read_word(&dsp_code, &address);
			hpi_dsp_code_read_word(&dsp_code, &type);
			hpi_dsp_code_read_block(length, &dsp_code, &pcode);

			for (i = 0; i < length; i++) {
				data = hpi_read_word(pdo, address);
				if (data != *pcode) {
					error = HPI6000_ERROR_INIT_VERIFY;
					HPI_DEBUG_LOG(ERROR,
						"DSP verify %x %x %x %x\n",
						address, *pcode, data,
						dsp_index);
					break;
				}
				pcode++;
				address += 4;
			}
			if (error)
				break;
		}
		hpi_dsp_code_close(&dsp_code);
		if (error)
			return error;

		/* zero out the hostmailbox */
		{
			u32 address = HPI_HIF_ADDR(host_cmd);
			for (i = 0; i < 4; i++) {
				hpi_write_word(pdo, address, 0);
				address += 4;
			}
		}
		/* write the DSP number into the hostmailbox */
		/* structure before starting the DSP */
		hpi_write_word(pdo, HPI_HIF_ADDR(dsp_number), dsp_index);

		/* write the DSP adapter Info into the */
		/* hostmailbox before starting the DSP */
		if (dsp_index > 0)
			hpi_write_word(pdo, HPI_HIF_ADDR(adapter_info),
				adapter_info);

		/* step 3. Start code by sending interrupt */
		iowrite32(0x00030003, pdo->prHPI_control);
		hpios_delay_micro_seconds(10000);

		/* wait for a non-zero value in hostcmd -
		 * indicating initialization is complete
		 *
		 * Init could take a while if DSP checks SDRAM memory
		 * Was 200000. Increased to 2000000 for ASI8801 so we
		 * don't get 938 errors.
		 */
		timeout = 2000000;
		while (timeout) {
			do {
				read = hpi_read_word(pdo,
					HPI_HIF_ADDR(host_cmd));
			} while (--timeout
				&& hpi6000_check_PCI2040_error_flag(pao,
					H6READ));

			if (read)
				break;
			/* The following is a workaround for bug #94:
			 * Bluescreen on install and subsequent boots on a
			 * DELL PowerEdge 600SC PC with 1.8GHz P4 and
			 * ServerWorks chipset. Without this delay the system
			 * locks up with a bluescreen (NOT GPF or pagefault).
			 */
			else
				hpios_delay_micro_seconds(10000);
		}
		if (timeout == 0)
			return HPI6000_ERROR_INIT_NOACK;

		/* read the DSP adapter Info from the */
		/* hostmailbox structure after starting the DSP */
		if (dsp_index == 0) {
			/*u32 dwTestData=0; */
			u32 mask = 0;

			adapter_info =
				hpi_read_word(pdo,
				HPI_HIF_ADDR(adapter_info));
			if (HPI_ADAPTER_FAMILY_ASI
				(HPI_HIF_ADAPTER_INFO_EXTRACT_ADAPTER
					(adapter_info)) ==
				HPI_ADAPTER_FAMILY_ASI(0x6200))
				/* all 6200 cards have this many DSPs */
				phw->num_dsp = 2;

			/* test that the PLD is programmed */
			/* and we can read/write 24bits */
#define PLD_BASE_ADDRESS 0x90000000L	/*for ASI6100/6200/8800 */

			switch (boot_load_family) {
			case HPI_ADAPTER_FAMILY_ASI(0x6200):
				/* ASI6100/6200 has 24bit path to FPGA */
				mask = 0xFFFFFF00L;
				/* ASI5100 uses AX6 code, */
				/* but has no PLD r/w register to test */
				if (HPI_ADAPTER_FAMILY_ASI(pao->pci.pci_dev->
						subsystem_device) ==
					HPI_ADAPTER_FAMILY_ASI(0x5100))
					mask = 0x00000000L;
				/* ASI5200 uses AX6 code, */
				/* but has no PLD r/w register to test */
				if (HPI_ADAPTER_FAMILY_ASI(pao->pci.pci_dev->
						subsystem_device) ==
					HPI_ADAPTER_FAMILY_ASI(0x5200))
					mask = 0x00000000L;
				break;
			case HPI_ADAPTER_FAMILY_ASI(0x8800):
				/* ASI8800 has 16bit path to FPGA */
				mask = 0xFFFF0000L;
				break;
			}
			test_data = 0xAAAAAA00L & mask;
			/* write to 24 bit Debug register (D31-D8) */
			hpi_write_word(pdo, PLD_BASE_ADDRESS + 4L, test_data);
			read = hpi_read_word(pdo,
				PLD_BASE_ADDRESS + 4L) & mask;
			if (read != test_data) {
				HPI_DEBUG_LOG(ERROR, "PLD %x %x\n", test_data,
					read);
				return HPI6000_ERROR_INIT_PLDTEST1;
			}
			test_data = 0x55555500L & mask;
			hpi_write_word(pdo, PLD_BASE_ADDRESS + 4L, test_data);
			read = hpi_read_word(pdo,
				PLD_BASE_ADDRESS + 4L) & mask;
			if (read != test_data) {
				HPI_DEBUG_LOG(ERROR, "PLD %x %x\n", test_data,
					read);
				return HPI6000_ERROR_INIT_PLDTEST2;
			}
		}
	}	/* for numDSP */
	return 0;
}
示例#22
0
int asihpi_adapter_probe(struct pci_dev *pci_dev,
                         const struct pci_device_id *pci_id)
{
    int idx, nm, low_latency_mode = 0, irq_supported = 0;
    int adapter_index;
    unsigned int memlen;
    struct hpi_message hm;
    struct hpi_response hr;
    struct hpi_adapter adapter;
    struct hpi_pci pci;

    memset(&adapter, 0, sizeof(adapter));

    dev_printk(KERN_DEBUG, &pci_dev->dev,
               "probe %04x:%04x,%04x:%04x,%04x\n", pci_dev->vendor,
               pci_dev->device, pci_dev->subsystem_vendor,
               pci_dev->subsystem_device, pci_dev->devfn);

    if (pci_enable_device(pci_dev) < 0) {
        dev_err(&pci_dev->dev,
                "pci_enable_device failed, disabling device\n");
        return -EIO;
    }

    pci_set_master(pci_dev);	/* also sets latency timer if < 16 */

    hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
                              HPI_SUBSYS_CREATE_ADAPTER);
    hpi_init_response(&hr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_CREATE_ADAPTER,
                      HPI_ERROR_PROCESSING_MESSAGE);

    hm.adapter_index = HPI_ADAPTER_INDEX_INVALID;

    nm = HPI_MAX_ADAPTER_MEM_SPACES;

    for (idx = 0; idx < nm; idx++) {
        HPI_DEBUG_LOG(INFO, "resource %d %pR\n", idx,
                      &pci_dev->resource[idx]);

        if (pci_resource_flags(pci_dev, idx) & IORESOURCE_MEM) {
            memlen = pci_resource_len(pci_dev, idx);
            pci.ap_mem_base[idx] =
                ioremap(pci_resource_start(pci_dev, idx),
                        memlen);
            if (!pci.ap_mem_base[idx]) {
                HPI_DEBUG_LOG(ERROR,
                              "ioremap failed, aborting\n");
                /* unmap previously mapped pci mem space */
                goto err;
            }
        }
    }

    pci.pci_dev = pci_dev;
    hm.u.s.resource.bus_type = HPI_BUS_PCI;
    hm.u.s.resource.r.pci = &pci;

    /* call CreateAdapterObject on the relevant hpi module */
    hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
    if (hr.error)
        goto err;

    adapter_index = hr.u.s.adapter_index;
    adapter.adapter = hpi_find_adapter(adapter_index);

    if (prealloc_stream_buf) {
        adapter.p_buffer = vmalloc(prealloc_stream_buf);
        if (!adapter.p_buffer) {
            HPI_DEBUG_LOG(ERROR,
                          "HPI could not allocate "
                          "kernel buffer size %d\n",
                          prealloc_stream_buf);
            goto err;
        }
    }

    hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
                              HPI_ADAPTER_OPEN);
    hm.adapter_index = adapter.adapter->index;
    hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);

    if (hr.error) {
        HPI_DEBUG_LOG(ERROR, "HPI_ADAPTER_OPEN failed, aborting\n");
        goto err;
    }

    /* Check if current mode == Low Latency mode */
    hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
                              HPI_ADAPTER_GET_MODE);
    hm.adapter_index = adapter.adapter->index;
    hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);

    if (!hr.error
            && hr.u.ax.mode.adapter_mode == HPI_ADAPTER_MODE_LOW_LATENCY)
        low_latency_mode = 1;
    else
        dev_info(&pci_dev->dev,
                 "Adapter at index %d is not in low latency mode\n",
                 adapter.adapter->index);

    /* Check if IRQs are supported */
    hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
                              HPI_ADAPTER_GET_PROPERTY);
    hm.adapter_index = adapter.adapter->index;
    hm.u.ax.property_set.property = HPI_ADAPTER_PROPERTY_SUPPORTS_IRQ;
    hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
    if (hr.error || !hr.u.ax.property_get.parameter1) {
        dev_info(&pci_dev->dev,
                 "IRQs not supported by adapter at index %d\n",
                 adapter.adapter->index);
    } else {
        irq_supported = 1;
    }

    /* WARNING can't init mutex in 'adapter'
     * and then copy it to adapters[] ?!?!
     */
    adapters[adapter_index] = adapter;
    mutex_init(&adapters[adapter_index].mutex);
    pci_set_drvdata(pci_dev, &adapters[adapter_index]);

    if (low_latency_mode && irq_supported) {
        if (!adapter.adapter->irq_query_and_clear) {
            dev_err(&pci_dev->dev,
                    "no IRQ handler for adapter %d, aborting\n",
                    adapter.adapter->index);
            goto err;
        }

        /* Disable IRQ generation on DSP side by setting the rate to 0 */
        hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
                                  HPI_ADAPTER_SET_PROPERTY);
        hm.adapter_index = adapter.adapter->index;
        hm.u.ax.property_set.property = HPI_ADAPTER_PROPERTY_IRQ_RATE;
        hm.u.ax.property_set.parameter1 = 0;
        hm.u.ax.property_set.parameter2 = 0;
        hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
        if (hr.error) {
            HPI_DEBUG_LOG(ERROR,
                          "HPI_ADAPTER_GET_MODE failed, aborting\n");
            goto err;
        }

        /* Note: request_irq calls asihpi_isr here */
        if (request_irq(pci_dev->irq, asihpi_isr, IRQF_SHARED,
                        "asihpi", &adapters[adapter_index])) {
            dev_err(&pci_dev->dev, "request_irq(%d) failed\n",
                    pci_dev->irq);
            goto err;
        }

        adapters[adapter_index].interrupt_mode = 1;

        dev_info(&pci_dev->dev, "using irq %d\n", pci_dev->irq);
        adapters[adapter_index].irq = pci_dev->irq;
    } else {
        dev_info(&pci_dev->dev, "using polled mode\n");
    }

    dev_info(&pci_dev->dev, "probe succeeded for ASI%04X HPI index %d\n",
             adapter.adapter->type, adapter_index);

    return 0;

err:
    for (idx = 0; idx < HPI_MAX_ADAPTER_MEM_SPACES; idx++) {
        if (pci.ap_mem_base[idx]) {
            iounmap(pci.ap_mem_base[idx]);
            pci.ap_mem_base[idx] = NULL;
        }
    }

    if (adapter.p_buffer) {
        adapter.buffer_size = 0;
        vfree(adapter.p_buffer);
    }

    HPI_DEBUG_LOG(ERROR, "adapter_probe failed\n");
    return -ENODEV;
}
示例#23
0
int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
	const struct pci_device_id *pci_id)
{
	int err, idx, nm;
	unsigned int memlen;
	struct hpi_message hm;
	struct hpi_response hr;
	struct hpi_adapter adapter;
	struct hpi_pci pci;

	memset(&adapter, 0, sizeof(adapter));

	printk(KERN_DEBUG "probe PCI device (%04x:%04x,%04x:%04x,%04x)\n",
		pci_dev->vendor, pci_dev->device, pci_dev->subsystem_vendor,
		pci_dev->subsystem_device, pci_dev->devfn);

	hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
		HPI_SUBSYS_CREATE_ADAPTER);
	hpi_init_response(&hr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_CREATE_ADAPTER,
		HPI_ERROR_PROCESSING_MESSAGE);

	hm.adapter_index = -1;	/* an invalid index */

	/* fill in HPI_PCI information from kernel provided information */
	adapter.pci = pci_dev;

	nm = HPI_MAX_ADAPTER_MEM_SPACES;

	for (idx = 0; idx < nm; idx++) {
		HPI_DEBUG_LOG(INFO, "resource %d %s %08llx-%08llx %04llx\n",
			idx, pci_dev->resource[idx].name,
			(unsigned long long)pci_resource_start(pci_dev, idx),
			(unsigned long long)pci_resource_end(pci_dev, idx),
			(unsigned long long)pci_resource_flags(pci_dev, idx));

		if (pci_resource_flags(pci_dev, idx) & IORESOURCE_MEM) {
			memlen = pci_resource_len(pci_dev, idx);
			adapter.ap_remapped_mem_base[idx] =
				ioremap(pci_resource_start(pci_dev, idx),
				memlen);
			if (!adapter.ap_remapped_mem_base[idx]) {
				HPI_DEBUG_LOG(ERROR,
					"ioremap failed, aborting\n");
				/* unmap previously mapped pci mem space */
				goto err;
			}
		}

		pci.ap_mem_base[idx] = adapter.ap_remapped_mem_base[idx];
	}

	/* could replace Pci with direct pointer to pci_dev for linux
	   Instead wrap accessor functions for IDs etc.
	   Would it work for windows?
	 */
	pci.bus_number = pci_dev->bus->number;
	pci.vendor_id = (u16)pci_dev->vendor;
	pci.device_id = (u16)pci_dev->device;
	pci.subsys_vendor_id = (u16)(pci_dev->subsystem_vendor & 0xffff);
	pci.subsys_device_id = (u16)(pci_dev->subsystem_device & 0xffff);
	pci.device_number = pci_dev->devfn;
	pci.interrupt = pci_dev->irq;
	pci.p_os_data = pci_dev;

	hm.u.s.resource.bus_type = HPI_BUS_PCI;
	hm.u.s.resource.r.pci = &pci;

	/* call CreateAdapterObject on the relevant hpi module */
	hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
	if (hr.error)
		goto err;

	if (prealloc_stream_buf) {
		adapter.p_buffer = vmalloc(prealloc_stream_buf);
		if (!adapter.p_buffer) {
			HPI_DEBUG_LOG(ERROR,
				"HPI could not allocate "
				"kernel buffer size %d\n",
				prealloc_stream_buf);
			goto err;
		}
	}

	adapter.index = hr.u.s.adapter_index;
	adapter.type = hr.u.s.aw_adapter_list[adapter.index];
	hm.adapter_index = adapter.index;

	err = hpi_adapter_open(NULL, adapter.index);
	if (err)
		goto err;

	adapter.snd_card_asihpi = NULL;
	/* WARNING can't init mutex in 'adapter'
	 * and then copy it to adapters[] ?!?!
	 */
	adapters[hr.u.s.adapter_index] = adapter;
	mutex_init(&adapters[adapter.index].mutex);
	pci_set_drvdata(pci_dev, &adapters[adapter.index]);

	printk(KERN_INFO "probe found adapter ASI%04X HPI index #%d.\n",
		adapter.type, adapter.index);

	return 0;

err:
	for (idx = 0; idx < HPI_MAX_ADAPTER_MEM_SPACES; idx++) {
		if (adapter.ap_remapped_mem_base[idx]) {
			iounmap(adapter.ap_remapped_mem_base[idx]);
			adapter.ap_remapped_mem_base[idx] = NULL;
		}
	}

	if (adapter.p_buffer) {
		adapter.buffer_size = 0;
		vfree(adapter.p_buffer);
	}

	HPI_DEBUG_LOG(ERROR, "adapter_probe failed\n");
	return -ENODEV;
}
示例#24
0
static unsigned int control_cache_alloc_check(struct hpi_control_cache *pC)
{
	unsigned int i;
	int cached = 0;
	if (!pC)
		return 0;

	if (pC->init)
		return pC->init;

	if (!pC->p_cache)
		return 0;

	if (pC->control_count && pC->cache_size_in_bytes) {
		char *p_master_cache;
		unsigned int byte_count = 0;

		p_master_cache = (char *)pC->p_cache;
		HPI_DEBUG_LOG(DEBUG, "check %d controls\n",
			pC->control_count);
		for (i = 0; i < pC->control_count; i++) {
			struct hpi_control_cache_info *info =
				(struct hpi_control_cache_info *)
				&p_master_cache[byte_count];

			if (!info->size_in32bit_words) {
				if (!i) {
					HPI_DEBUG_LOG(INFO,
						"adap %d cache not ready?\n",
						pC->adap_idx);
					return 0;
				}
				/* The cache is invalid.
				 * Minimum valid entry size is
				 * sizeof(struct hpi_control_cache_info)
				 */
				HPI_DEBUG_LOG(ERROR,
					"adap %d zero size cache entry %d\n",
					pC->adap_idx, i);
				break;
			}

			if (info->control_type) {
				pC->p_info[info->control_index] = info;
				cached++;
			} else {	/* dummy cache entry */
				pC->p_info[info->control_index] = NULL;
			}

			byte_count += info->size_in32bit_words * 4;

			HPI_DEBUG_LOG(VERBOSE,
				"cached %d, pinfo %p index %d type %d size %d\n",
				cached, pC->p_info[info->control_index],
				info->control_index, info->control_type,
				info->size_in32bit_words);

			/* quit loop early if whole cache has been scanned.
			 * dwControlCount is the maximum possible entries
			 * but some may be absent from the cache
			 */
			if (byte_count >= pC->cache_size_in_bytes)
				break;
			/* have seen last control index */
			if (info->control_index == pC->control_count - 1)
				break;
		}

		if (byte_count != pC->cache_size_in_bytes)
			HPI_DEBUG_LOG(WARNING,
				"adap %d bytecount %d != cache size %d\n",
				pC->adap_idx, byte_count,
				pC->cache_size_in_bytes);
		else
			HPI_DEBUG_LOG(DEBUG,
				"adap %d cache good, bytecount == cache size = %d\n",
				pC->adap_idx, byte_count);

		pC->init = (u16)cached;
	}
	return pC->init;
}
示例#25
0
文件: hpi6000.c 项目: 020gzh/linux
/* this routine is called from SubSysFindAdapter and SubSysCreateAdapter */
static short create_adapter_obj(struct hpi_adapter_obj *pao,
	u32 *pos_error_code)
{
	short boot_error = 0;
	u32 dsp_index = 0;
	u32 control_cache_size = 0;
	u32 control_cache_count = 0;
	struct hpi_hw_obj *phw = pao->priv;

	/* The PCI2040 has the following address map */
	/* BAR0 - 4K = HPI control and status registers on PCI2040 (HPI CSR) */
	/* BAR1 - 32K = HPI registers on DSP */
	phw->dw2040_HPICSR = pao->pci.ap_mem_base[0];
	phw->dw2040_HPIDSP = pao->pci.ap_mem_base[1];
	HPI_DEBUG_LOG(VERBOSE, "csr %p, dsp %p\n", phw->dw2040_HPICSR,
		phw->dw2040_HPIDSP);

	/* set addresses for the possible DSP HPI interfaces */
	for (dsp_index = 0; dsp_index < MAX_DSPS; dsp_index++) {
		phw->ado[dsp_index].prHPI_control =
			phw->dw2040_HPIDSP + (CONTROL +
			DSP_SPACING * dsp_index);

		phw->ado[dsp_index].prHPI_address =
			phw->dw2040_HPIDSP + (ADDRESS +
			DSP_SPACING * dsp_index);
		phw->ado[dsp_index].prHPI_data =
			phw->dw2040_HPIDSP + (DATA + DSP_SPACING * dsp_index);

		phw->ado[dsp_index].prHPI_data_auto_inc =
			phw->dw2040_HPIDSP + (DATA_AUTOINC +
			DSP_SPACING * dsp_index);

		HPI_DEBUG_LOG(VERBOSE, "ctl %p, adr %p, dat %p, dat++ %p\n",
			phw->ado[dsp_index].prHPI_control,
			phw->ado[dsp_index].prHPI_address,
			phw->ado[dsp_index].prHPI_data,
			phw->ado[dsp_index].prHPI_data_auto_inc);

		phw->ado[dsp_index].pa_parent_adapter = pao;
	}

	phw->pCI2040HPI_error_count = 0;
	pao->has_control_cache = 0;

	/* Set the default number of DSPs on this card */
	/* This is (conditionally) adjusted after bootloading */
	/* of the first DSP in the bootload section. */
	phw->num_dsp = 1;

	boot_error = hpi6000_adapter_boot_load_dsp(pao, pos_error_code);
	if (boot_error)
		return boot_error;

	HPI_DEBUG_LOG(INFO, "bootload DSP OK\n");

	phw->message_buffer_address_on_dsp = 0L;
	phw->response_buffer_address_on_dsp = 0L;

	/* get info about the adapter by asking the adapter */
	/* send a HPI_ADAPTER_GET_INFO message */
	{
		struct hpi_message hm;
		struct hpi_response hr0;	/* response from DSP 0 */
		struct hpi_response hr1;	/* response from DSP 1 */
		u16 error = 0;

		HPI_DEBUG_LOG(VERBOSE, "send ADAPTER_GET_INFO\n");
		memset(&hm, 0, sizeof(hm));
		hm.type = HPI_TYPE_REQUEST;
		hm.size = sizeof(struct hpi_message);
		hm.object = HPI_OBJ_ADAPTER;
		hm.function = HPI_ADAPTER_GET_INFO;
		hm.adapter_index = 0;
		memset(&hr0, 0, sizeof(hr0));
		memset(&hr1, 0, sizeof(hr1));
		hr0.size = sizeof(hr0);
		hr1.size = sizeof(hr1);

		error = hpi6000_message_response_sequence(pao, 0, &hm, &hr0);
		if (hr0.error) {
			HPI_DEBUG_LOG(DEBUG, "message error %d\n", hr0.error);
			return hr0.error;
		}
		if (phw->num_dsp == 2) {
			error = hpi6000_message_response_sequence(pao, 1, &hm,
				&hr1);
			if (error)
				return error;
		}
		pao->type = hr0.u.ax.info.adapter_type;
		pao->index = hr0.u.ax.info.adapter_index;
	}

	memset(&phw->control_cache[0], 0,
		sizeof(struct hpi_control_cache_single) *
		HPI_NMIXER_CONTROLS);
	/* Read the control cache length to figure out if it is turned on */
	control_cache_size =
		hpi_read_word(&phw->ado[0],
		HPI_HIF_ADDR(control_cache_size_in_bytes));
	if (control_cache_size) {
		control_cache_count =
			hpi_read_word(&phw->ado[0],
			HPI_HIF_ADDR(control_cache_count));

		phw->p_cache =
			hpi_alloc_control_cache(control_cache_count,
			control_cache_size, (unsigned char *)
			&phw->control_cache[0]
			);
		if (phw->p_cache)
			pao->has_control_cache = 1;
	}

	HPI_DEBUG_LOG(DEBUG, "get adapter info ASI%04X index %d\n", pao->type,
		pao->index);

	if (phw->p_cache)
		phw->p_cache->adap_idx = pao->index;

	return hpi_add_adapter(pao);
}
示例#26
0
/** Updates the cache with Set values.

Only update if no error.
Volume and Level return the limited values in the response, so use these
Multiplexer does so use sent values
*/
void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *p_cache,
	struct hpi_message *phm, struct hpi_response *phr)
{
	struct hpi_control_cache_single *pC;
	struct hpi_control_cache_info *pI;

	if (phr->error)
		return;

	if (!find_control(phm->obj_index, p_cache, &pI)) {
		HPI_DEBUG_LOG(VERBOSE,
			"HPICMN find_control() failed for adap %d\n",
			phm->adapter_index);
		return;
	}

	/* pC is the default cached control strucure.
	   May be cast to something else in the following switch statement.
	 */
	pC = (struct hpi_control_cache_single *)pI;

	switch (pI->control_type) {
	case HPI_CONTROL_VOLUME:
		if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
			pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
			pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
		} else if (phm->u.c.attribute == HPI_VOLUME_MUTE) {
			if (phm->u.c.param1)
				pC->u.vol.flags |= HPI_VOLUME_FLAG_MUTED;
			else
				pC->u.vol.flags &= ~HPI_VOLUME_FLAG_MUTED;
		}
		break;
	case HPI_CONTROL_MULTIPLEXER:
		/* mux does not return its setting on Set command. */
		if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
			pC->u.mux.source_node_type = (u16)phm->u.c.param1;
			pC->u.mux.source_node_index = (u16)phm->u.c.param2;
		}
		break;
	case HPI_CONTROL_CHANNEL_MODE:
		/* mode does not return its setting on Set command. */
		if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
			pC->u.mode.mode = (u16)phm->u.c.param1;
		break;
	case HPI_CONTROL_LEVEL:
		if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
			pC->u.vol.an_log[0] = phr->u.c.an_log_value[0];
			pC->u.vol.an_log[1] = phr->u.c.an_log_value[1];
		}
		break;
	case HPI_CONTROL_MICROPHONE:
		if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
			pC->u.microphone.phantom_state = (u16)phm->u.c.param1;
		break;
	case HPI_CONTROL_AESEBU_TRANSMITTER:
		if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
			pC->u.aes3tx.format = phm->u.c.param1;
		break;
	case HPI_CONTROL_AESEBU_RECEIVER:
		if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
			pC->u.aes3rx.format = phm->u.c.param1;
		break;
	case HPI_CONTROL_SAMPLECLOCK:
		if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
			pC->u.clk.source = (u16)phm->u.c.param1;
		else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX)
			pC->u.clk.source_index = (u16)phm->u.c.param1;
		else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
			pC->u.clk.sample_rate = phm->u.c.param1;
		break;
	default:
		break;
	}
}
示例#27
0
int asihpi_adapter_probe(struct pci_dev *pci_dev,
			 const struct pci_device_id *pci_id)
{
	int idx, nm;
	int adapter_index;
	unsigned int memlen;
	struct hpi_message hm;
	struct hpi_response hr;
	struct hpi_adapter adapter;
	struct hpi_pci pci;

	memset(&adapter, 0, sizeof(adapter));

	dev_printk(KERN_DEBUG, &pci_dev->dev,
		"probe %04x:%04x,%04x:%04x,%04x\n", pci_dev->vendor,
		pci_dev->device, pci_dev->subsystem_vendor,
		pci_dev->subsystem_device, pci_dev->devfn);

	if (pci_enable_device(pci_dev) < 0) {
		dev_err(&pci_dev->dev,
			"pci_enable_device failed, disabling device\n");
		return -EIO;
	}

	pci_set_master(pci_dev);	/* also sets latency timer if < 16 */

	hpi_init_message_response(&hm, &hr, HPI_OBJ_SUBSYSTEM,
		HPI_SUBSYS_CREATE_ADAPTER);
	hpi_init_response(&hr, HPI_OBJ_SUBSYSTEM, HPI_SUBSYS_CREATE_ADAPTER,
		HPI_ERROR_PROCESSING_MESSAGE);

	hm.adapter_index = HPI_ADAPTER_INDEX_INVALID;

	nm = HPI_MAX_ADAPTER_MEM_SPACES;

	for (idx = 0; idx < nm; idx++) {
		HPI_DEBUG_LOG(INFO, "resource %d %pR\n", idx,
			&pci_dev->resource[idx]);

		if (pci_resource_flags(pci_dev, idx) & IORESOURCE_MEM) {
			memlen = pci_resource_len(pci_dev, idx);
			pci.ap_mem_base[idx] =
				ioremap(pci_resource_start(pci_dev, idx),
				memlen);
			if (!pci.ap_mem_base[idx]) {
				HPI_DEBUG_LOG(ERROR,
					"ioremap failed, aborting\n");
				/* unmap previously mapped pci mem space */
				goto err;
			}
		}
	}

	pci.pci_dev = pci_dev;
	hm.u.s.resource.bus_type = HPI_BUS_PCI;
	hm.u.s.resource.r.pci = &pci;

	/* call CreateAdapterObject on the relevant hpi module */
	hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
	if (hr.error)
		goto err;

	adapter_index = hr.u.s.adapter_index;
	adapter.adapter = hpi_find_adapter(adapter_index);

	if (prealloc_stream_buf) {
		adapter.p_buffer = vmalloc(prealloc_stream_buf);
		if (!adapter.p_buffer) {
			HPI_DEBUG_LOG(ERROR,
				"HPI could not allocate "
				"kernel buffer size %d\n",
				prealloc_stream_buf);
			goto err;
		}
	}

	hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
		HPI_ADAPTER_OPEN);
	hm.adapter_index = adapter.adapter->index;
	hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);

	if (hr.error)
		goto err;

	/* WARNING can't init mutex in 'adapter'
	 * and then copy it to adapters[] ?!?!
	 */
	adapters[adapter_index] = adapter;
	mutex_init(&adapters[adapter_index].mutex);
	pci_set_drvdata(pci_dev, &adapters[adapter_index]);

	dev_info(&pci_dev->dev, "probe succeeded for ASI%04X HPI index %d\n",
		 adapter.adapter->type, adapter_index);

	return 0;

err:
	for (idx = 0; idx < HPI_MAX_ADAPTER_MEM_SPACES; idx++) {
		if (pci.ap_mem_base[idx]) {
			iounmap(pci.ap_mem_base[idx]);
			pci.ap_mem_base[idx] = NULL;
		}
	}

	if (adapter.p_buffer) {
		adapter.buffer_size = 0;
		vfree(adapter.p_buffer);
	}

	HPI_DEBUG_LOG(ERROR, "adapter_probe failed\n");
	return -ENODEV;
}
示例#28
0
/*-------------------------------------------------------------------*/
short hpi_dsp_code_open(u32 adapter, struct dsp_code *ps_dsp_code,
	u32 *pos_error_code)
{
	const struct firmware *ps_firmware = ps_dsp_code->ps_firmware;
	struct code_header header;
	char fw_name[20];
	int err;

	sprintf(fw_name, "asihpi/dsp%04x.bin", adapter);

	err = request_firmware(&ps_firmware, fw_name,
		&ps_dsp_code->ps_dev->dev);

	if (err != 0) {
//		dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev,
//			"%d, request_firmware failed for  %s\n", err,
;
		goto error1;
	}
	if (ps_firmware->size < sizeof(header)) {
//		dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev,
;
		goto error2;
	}
	memcpy(&header, ps_firmware->data, sizeof(header));
	if (header.adapter != adapter) {
//		dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev,
//			"Adapter type incorrect %4x != %4x\n", header.adapter,
;
		goto error2;
	}
	if (header.size != ps_firmware->size) {
//		dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev,
//			"Code size wrong  %d != %ld\n", header.size,
;
		goto error2;
	}

	if (header.version / 100 != HPI_VER_DECIMAL / 100) {
//		dev_printk(KERN_ERR, &ps_dsp_code->ps_dev->dev,
//			"Incompatible firmware version "
//			"DSP image %d != Driver %d\n", header.version,
;
		goto error2;
	}

	if (header.version != HPI_VER_DECIMAL) {
//		dev_printk(KERN_WARNING, &ps_dsp_code->ps_dev->dev,
//			"Firmware: release version mismatch  DSP image %d != Driver %d\n",
;
	}

	HPI_DEBUG_LOG(DEBUG, "dsp code %s opened\n", fw_name);
	ps_dsp_code->ps_firmware = ps_firmware;
	ps_dsp_code->block_length = header.size / sizeof(u32);
	ps_dsp_code->word_count = sizeof(header) / sizeof(u32);
	ps_dsp_code->version = header.version;
	ps_dsp_code->crc = header.crc;
	return 0;

error2:
	release_firmware(ps_firmware);
error1:
	ps_dsp_code->ps_firmware = NULL;
	ps_dsp_code->block_length = 0;
	return HPI_ERROR_DSP_FILE_NOT_FOUND;
}
示例#29
0
long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
	struct hpi_ioctl_linux __user *phpi_ioctl_data;
	void __user *puhm;
	void __user *puhr;
	union hpi_message_buffer_v1 *hm;
	union hpi_response_buffer_v1 *hr;
	u16 res_max_size;
	u32 uncopied_bytes;
	struct hpi_adapter *pa = NULL;
	int err = 0;

	if (cmd != HPI_IOCTL_LINUX)
		return -EINVAL;

	hm = kmalloc(sizeof(*hm), GFP_KERNEL);
	hr = kmalloc(sizeof(*hr), GFP_KERNEL);
	if (!hm || !hr) {
		err = -ENOMEM;
		goto out;
	}

	phpi_ioctl_data = (struct hpi_ioctl_linux __user *)arg;

	/* Read the message and response pointers from user space.  */
	get_user(puhm, &phpi_ioctl_data->phm);
	get_user(puhr, &phpi_ioctl_data->phr);

	/* Now read the message size and data from user space.  */
	get_user(hm->h.size, (u16 __user *)puhm);
	if (hm->h.size > sizeof(*hm))
		hm->h.size = sizeof(*hm);

	/*printk(KERN_INFO "message size %d\n", hm->h.wSize); */

	uncopied_bytes = copy_from_user(hm, puhm, hm->h.size);
	if (uncopied_bytes) {
		HPI_DEBUG_LOG(ERROR, "uncopied bytes %d\n", uncopied_bytes);
		err = -EFAULT;
		goto out;
	}

	get_user(res_max_size, (u16 __user *)puhr);
	/* printk(KERN_INFO "user response size %d\n", res_max_size); */
	if (res_max_size < sizeof(struct hpi_response_header)) {
		HPI_DEBUG_LOG(WARNING, "small res size %d\n", res_max_size);
		err = -EFAULT;
		goto out;
	}

	pa = &adapters[hm->h.adapter_index];
	hr->h.size = 0;
	if (hm->h.object == HPI_OBJ_SUBSYSTEM) {
		switch (hm->h.function) {
		case HPI_SUBSYS_CREATE_ADAPTER:
		case HPI_SUBSYS_DELETE_ADAPTER:
			/* Application must not use these functions! */
			hr->h.size = sizeof(hr->h);
			hr->h.error = HPI_ERROR_INVALID_OPERATION;
			hr->h.function = hm->h.function;
			uncopied_bytes = copy_to_user(puhr, hr, hr->h.size);
			if (uncopied_bytes)
				err = -EFAULT;
			else
				err = 0;
			goto out;

		default:
			hpi_send_recv_f(&hm->m0, &hr->r0, file);
		}
	} else {
		u16 __user *ptr = NULL;
		u32 size = 0;

		/* -1=no data 0=read from user mem, 1=write to user mem */
		int wrflag = -1;
		u32 adapter = hm->h.adapter_index;

		if ((hm->h.adapter_index > HPI_MAX_ADAPTERS) || (!pa->type)) {
			hpi_init_response(&hr->r0, HPI_OBJ_ADAPTER,
				HPI_ADAPTER_OPEN,
				HPI_ERROR_BAD_ADAPTER_NUMBER);

			uncopied_bytes =
				copy_to_user(puhr, hr, sizeof(hr->h));
			if (uncopied_bytes)
				err = -EFAULT;
			else
				err = 0;
			goto out;
		}

		if (mutex_lock_interruptible(&adapters[adapter].mutex)) {
			err = -EINTR;
			goto out;
		}

		/* Dig out any pointers embedded in the message.  */
		switch (hm->h.function) {
		case HPI_OSTREAM_WRITE:
		case HPI_ISTREAM_READ:{
				/* Yes, sparse, this is correct. */
				ptr = (u16 __user *)hm->m0.u.d.u.data.pb_data;
				size = hm->m0.u.d.u.data.data_size;

				/* Allocate buffer according to application request.
				   ?Is it better to alloc/free for the duration
				   of the transaction?
				 */
				if (pa->buffer_size < size) {
					HPI_DEBUG_LOG(DEBUG,
						"realloc adapter %d stream "
						"buffer from %zd to %d\n",
						hm->h.adapter_index,
						pa->buffer_size, size);
					if (pa->p_buffer) {
						pa->buffer_size = 0;
						vfree(pa->p_buffer);
					}
					pa->p_buffer = vmalloc(size);
					if (pa->p_buffer)
						pa->buffer_size = size;
					else {
						HPI_DEBUG_LOG(ERROR,
							"HPI could not allocate "
							"stream buffer size %d\n",
							size);

						mutex_unlock(&adapters
							[adapter].mutex);
						err = -EINVAL;
						goto out;
					}
				}

				hm->m0.u.d.u.data.pb_data = pa->p_buffer;
				if (hm->h.function == HPI_ISTREAM_READ)
					/* from card, WRITE to user mem */
					wrflag = 1;
				else
					wrflag = 0;
				break;
			}

		default:
			size = 0;
			break;
		}

		if (size && (wrflag == 0)) {
			uncopied_bytes =
				copy_from_user(pa->p_buffer, ptr, size);
			if (uncopied_bytes)
				HPI_DEBUG_LOG(WARNING,
					"missed %d of %d "
					"bytes from user\n", uncopied_bytes,
					size);
		}

		hpi_send_recv_f(&hm->m0, &hr->r0, file);

		if (size && (wrflag == 1)) {
			uncopied_bytes =
				copy_to_user(ptr, pa->p_buffer, size);
			if (uncopied_bytes)
				HPI_DEBUG_LOG(WARNING,
					"missed %d of %d " "bytes to user\n",
					uncopied_bytes, size);
		}

		mutex_unlock(&adapters[adapter].mutex);
	}

	/* on return response size must be set */
	/*printk(KERN_INFO "response size %d\n", hr->h.wSize); */

	if (!hr->h.size) {
		HPI_DEBUG_LOG(ERROR, "response zero size\n");
		err = -EFAULT;
		goto out;
	}

	if (hr->h.size > res_max_size) {
		HPI_DEBUG_LOG(ERROR, "response too big %d %d\n", hr->h.size,
			res_max_size);
		/*HPI_DEBUG_MESSAGE(ERROR, hm); */
		err = -EFAULT;
		goto out;
	}

	uncopied_bytes = copy_to_user(puhr, hr, hr->h.size);
	if (uncopied_bytes) {
		HPI_DEBUG_LOG(ERROR, "uncopied bytes %d\n", uncopied_bytes);
		err = -EFAULT;
		goto out;
	}

out:
	kfree(hm);
	kfree(hr);
	return err;
}
示例#30
0
/** CheckControlCache checks the cache and fills the struct hpi_response
 * accordingly. It returns one if a cache hit occurred, zero otherwise.
 */
short hpi_check_control_cache(struct hpi_control_cache *p_cache,
	struct hpi_message *phm, struct hpi_response *phr)
{
	short found = 1;
	struct hpi_control_cache_info *pI;
	struct hpi_control_cache_single *pC;
	size_t response_size;
	if (!find_control(phm->obj_index, p_cache, &pI)) {
		HPI_DEBUG_LOG(VERBOSE,
			"HPICMN find_control() failed for adap %d\n",
			phm->adapter_index);
		return 0;
	}

	phr->error = 0;
	phr->specific_error = 0;
	phr->version = 0;

	/* set the default response size */
	response_size =
		sizeof(struct hpi_response_header) +
		sizeof(struct hpi_control_res);

	/* pC is the default cached control strucure. May be cast to
	   something else in the following switch statement.
	 */
	pC = (struct hpi_control_cache_single *)pI;

	switch (pI->control_type) {

	case HPI_CONTROL_METER:
		if (phm->u.c.attribute == HPI_METER_PEAK) {
			phr->u.c.an_log_value[0] = pC->u.meter.an_log_peak[0];
			phr->u.c.an_log_value[1] = pC->u.meter.an_log_peak[1];
		} else if (phm->u.c.attribute == HPI_METER_RMS) {
			if (pC->u.meter.an_logRMS[0] ==
				HPI_CACHE_INVALID_SHORT) {
				phr->error =
					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
				phr->u.c.an_log_value[0] = HPI_METER_MINIMUM;
				phr->u.c.an_log_value[1] = HPI_METER_MINIMUM;
			} else {
				phr->u.c.an_log_value[0] =
					pC->u.meter.an_logRMS[0];
				phr->u.c.an_log_value[1] =
					pC->u.meter.an_logRMS[1];
			}
		} else
			found = 0;
		break;
	case HPI_CONTROL_VOLUME:
		if (phm->u.c.attribute == HPI_VOLUME_GAIN) {
			phr->u.c.an_log_value[0] = pC->u.vol.an_log[0];
			phr->u.c.an_log_value[1] = pC->u.vol.an_log[1];
		} else if (phm->u.c.attribute == HPI_VOLUME_MUTE) {
			if (pC->u.vol.flags & HPI_VOLUME_FLAG_HAS_MUTE) {
				if (pC->u.vol.flags & HPI_VOLUME_FLAG_MUTED)
					phr->u.c.param1 =
						HPI_BITMASK_ALL_CHANNELS;
				else
					phr->u.c.param1 = 0;
			} else {
				phr->error =
					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
				phr->u.c.param1 = 0;
			}
		} else {
			found = 0;
		}
		break;
	case HPI_CONTROL_MULTIPLEXER:
		if (phm->u.c.attribute == HPI_MULTIPLEXER_SOURCE) {
			phr->u.c.param1 = pC->u.mux.source_node_type;
			phr->u.c.param2 = pC->u.mux.source_node_index;
		} else {
			found = 0;
		}
		break;
	case HPI_CONTROL_CHANNEL_MODE:
		if (phm->u.c.attribute == HPI_CHANNEL_MODE_MODE)
			phr->u.c.param1 = pC->u.mode.mode;
		else
			found = 0;
		break;
	case HPI_CONTROL_LEVEL:
		if (phm->u.c.attribute == HPI_LEVEL_GAIN) {
			phr->u.c.an_log_value[0] = pC->u.level.an_log[0];
			phr->u.c.an_log_value[1] = pC->u.level.an_log[1];
		} else
			found = 0;
		break;
	case HPI_CONTROL_TUNER:
		if (phm->u.c.attribute == HPI_TUNER_FREQ)
			phr->u.c.param1 = pC->u.tuner.freq_ink_hz;
		else if (phm->u.c.attribute == HPI_TUNER_BAND)
			phr->u.c.param1 = pC->u.tuner.band;
		else if (phm->u.c.attribute == HPI_TUNER_LEVEL_AVG)
			if (pC->u.tuner.s_level_avg ==
				HPI_CACHE_INVALID_SHORT) {
				phr->u.cu.tuner.s_level = 0;
				phr->error =
					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
			} else
				phr->u.cu.tuner.s_level =
					pC->u.tuner.s_level_avg;
		else
			found = 0;
		break;
	case HPI_CONTROL_AESEBU_RECEIVER:
		if (phm->u.c.attribute == HPI_AESEBURX_ERRORSTATUS)
			phr->u.c.param1 = pC->u.aes3rx.error_status;
		else if (phm->u.c.attribute == HPI_AESEBURX_FORMAT)
			phr->u.c.param1 = pC->u.aes3rx.format;
		else
			found = 0;
		break;
	case HPI_CONTROL_AESEBU_TRANSMITTER:
		if (phm->u.c.attribute == HPI_AESEBUTX_FORMAT)
			phr->u.c.param1 = pC->u.aes3tx.format;
		else
			found = 0;
		break;
	case HPI_CONTROL_TONEDETECTOR:
		if (phm->u.c.attribute == HPI_TONEDETECTOR_STATE)
			phr->u.c.param1 = pC->u.tone.state;
		else
			found = 0;
		break;
	case HPI_CONTROL_SILENCEDETECTOR:
		if (phm->u.c.attribute == HPI_SILENCEDETECTOR_STATE) {
			phr->u.c.param1 = pC->u.silence.state;
		} else
			found = 0;
		break;
	case HPI_CONTROL_MICROPHONE:
		if (phm->u.c.attribute == HPI_MICROPHONE_PHANTOM_POWER)
			phr->u.c.param1 = pC->u.microphone.phantom_state;
		else
			found = 0;
		break;
	case HPI_CONTROL_SAMPLECLOCK:
		if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE)
			phr->u.c.param1 = pC->u.clk.source;
		else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SOURCE_INDEX) {
			if (pC->u.clk.source_index ==
				HPI_CACHE_INVALID_UINT16) {
				phr->u.c.param1 = 0;
				phr->error =
					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
			} else
				phr->u.c.param1 = pC->u.clk.source_index;
		} else if (phm->u.c.attribute == HPI_SAMPLECLOCK_SAMPLERATE)
			phr->u.c.param1 = pC->u.clk.sample_rate;
		else
			found = 0;
		break;
	case HPI_CONTROL_PAD:{
			struct hpi_control_cache_pad *p_pad;
			p_pad = (struct hpi_control_cache_pad *)pI;

			if (!(p_pad->field_valid_flags & (1 <<
						HPI_CTL_ATTR_INDEX(phm->u.c.
							attribute)))) {
				phr->error =
					HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
				break;
			}

			if (phm->u.c.attribute == HPI_PAD_PROGRAM_ID)
				phr->u.c.param1 = p_pad->pI;
			else if (phm->u.c.attribute == HPI_PAD_PROGRAM_TYPE)
				phr->u.c.param1 = p_pad->pTY;
			else {
				unsigned int index =
					HPI_CTL_ATTR_INDEX(phm->u.c.
					attribute) - 1;
				unsigned int offset = phm->u.c.param1;
				unsigned int pad_string_len, field_size;
				char *pad_string;
				unsigned int tocopy;

				if (index > ARRAY_SIZE(pad_desc) - 1) {
					phr->error =
						HPI_ERROR_INVALID_CONTROL_ATTRIBUTE;
					break;
				}

				pad_string =
					((char *)p_pad) +
					pad_desc[index].offset;
				field_size = pad_desc[index].field_size;
				/* Ensure null terminator */
				pad_string[field_size - 1] = 0;

				pad_string_len = strlen(pad_string) + 1;

				if (offset > pad_string_len) {
					phr->error =
						HPI_ERROR_INVALID_CONTROL_VALUE;
					break;
				}

				tocopy = pad_string_len - offset;
				if (tocopy > sizeof(phr->u.cu.chars8.sz_data))
					tocopy = sizeof(phr->u.cu.chars8.
						sz_data);

				memcpy(phr->u.cu.chars8.sz_data,
					&pad_string[offset], tocopy);

				phr->u.cu.chars8.remaining_chars =
					pad_string_len - offset - tocopy;
			}
		}
		break;
	default:
		found = 0;
		break;
	}

	HPI_DEBUG_LOG(VERBOSE, "%s Adap %d, Ctl %d, Type %d, Attr %d\n",
		found ? "Cached" : "Uncached", phm->adapter_index,
		pI->control_index, pI->control_type, phm->u.c.attribute);

	if (found) {
		phr->size = (u16)response_size;
		phr->type = HPI_TYPE_RESPONSE;
		phr->object = phm->object;
		phr->function = phm->function;
	}

	return found;
}