⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smscoreapi.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
			coredev, smscore_registry_getmode(coredev->devpath));	if (rc < 0) {		sms_info("set device mode faile , rc %d", rc);		return rc;	}	kmutex_lock(&g_smscore_deviceslock);	rc = smscore_notify_callbacks(coredev, coredev->device, 1);	sms_info("device %p started, rc %d", coredev, rc);	kmutex_unlock(&g_smscore_deviceslock);	return rc;}static int smscore_sendrequest_and_wait(struct smscore_device_t *coredev,					void *buffer, size_t size,					struct completion *completion){	int rc = coredev->sendrequest_handler(coredev->context, buffer, size);	if (rc < 0) {		sms_info("sendrequest returned error %d", rc);		return rc;	}	return wait_for_completion_timeout(completion,					   msecs_to_jiffies(10000)) ?						0 : -ETIME;}static int smscore_load_firmware_family2(struct smscore_device_t *coredev,					 void *buffer, size_t size){	struct SmsFirmware_ST *firmware = (struct SmsFirmware_ST *) buffer;	struct SmsMsgHdr_ST *msg;	u32 mem_address = firmware->StartAddress;	u8 *payload = firmware->Payload;	int rc = 0;	sms_info("loading FW to addr 0x%x size %d",		 mem_address, firmware->Length);	if (coredev->preload_handler) {		rc = coredev->preload_handler(coredev->context);		if (rc < 0)			return rc;	}	/* PAGE_SIZE buffer shall be enough and dma aligned */	msg = kmalloc(PAGE_SIZE, GFP_KERNEL | GFP_DMA);	if (!msg)		return -ENOMEM;	if (coredev->mode != DEVICE_MODE_NONE) {		sms_debug("sending reload command.");		SMS_INIT_MSG(msg, MSG_SW_RELOAD_START_REQ,			     sizeof(struct SmsMsgHdr_ST));		rc = smscore_sendrequest_and_wait(coredev, msg,						  msg->msgLength,						  &coredev->reload_start_done);		mem_address = *(u32 *) &payload[20];	}	while (size && rc >= 0) {		struct SmsDataDownload_ST *DataMsg =			(struct SmsDataDownload_ST *) msg;		int payload_size = min((int) size, SMS_MAX_PAYLOAD_SIZE);		SMS_INIT_MSG(msg, MSG_SMS_DATA_DOWNLOAD_REQ,			     (u16)(sizeof(struct SmsMsgHdr_ST) +				      sizeof(u32) + payload_size));		DataMsg->MemAddr = mem_address;		memcpy(DataMsg->Payload, payload, payload_size);		if ((coredev->device_flags & SMS_ROM_NO_RESPONSE) &&		    (coredev->mode == DEVICE_MODE_NONE))			rc = coredev->sendrequest_handler(				coredev->context, DataMsg,				DataMsg->xMsgHeader.msgLength);		else			rc = smscore_sendrequest_and_wait(				coredev, DataMsg,				DataMsg->xMsgHeader.msgLength,				&coredev->data_download_done);		payload += payload_size;		size -= payload_size;		mem_address += payload_size;	}	if (rc >= 0) {		if (coredev->mode == DEVICE_MODE_NONE) {			struct SmsMsgData_ST *TriggerMsg =				(struct SmsMsgData_ST *) msg;			SMS_INIT_MSG(msg, MSG_SMS_SWDOWNLOAD_TRIGGER_REQ,				     sizeof(struct SmsMsgHdr_ST) +				     sizeof(u32) * 5);			TriggerMsg->msgData[0] = firmware->StartAddress;						/* Entry point */			TriggerMsg->msgData[1] = 5; /* Priority */			TriggerMsg->msgData[2] = 0x200; /* Stack size */			TriggerMsg->msgData[3] = 0; /* Parameter */			TriggerMsg->msgData[4] = 4; /* Task ID */			if (coredev->device_flags & SMS_ROM_NO_RESPONSE) {				rc = coredev->sendrequest_handler(					coredev->context, TriggerMsg,					TriggerMsg->xMsgHeader.msgLength);				msleep(100);			} else				rc = smscore_sendrequest_and_wait(					coredev, TriggerMsg,					TriggerMsg->xMsgHeader.msgLength,					&coredev->trigger_done);		} else {			SMS_INIT_MSG(msg, MSG_SW_RELOAD_EXEC_REQ,				     sizeof(struct SmsMsgHdr_ST));			rc = coredev->sendrequest_handler(coredev->context,							  msg, msg->msgLength);		}		msleep(500);	}	sms_debug("rc=%d, postload=%p ", rc,		  coredev->postload_handler);	kfree(msg);	return ((rc >= 0) && coredev->postload_handler) ?		coredev->postload_handler(coredev->context) :		rc;}/** * loads specified firmware into a buffer and calls device loadfirmware_handler * * @param coredev pointer to a coredev object returned by *                smscore_register_device * @param filename null-terminated string specifies firmware file name * @param loadfirmware_handler device handler that loads firmware * * @return 0 on success, <0 on error. */static int smscore_load_firmware_from_file(struct smscore_device_t *coredev,					   char *filename,					   loadfirmware_t loadfirmware_handler){	int rc = -ENOENT;	const struct firmware *fw;	u8 *fw_buffer;	if (loadfirmware_handler == NULL && !(coredev->device_flags &					      SMS_DEVICE_FAMILY2))		return -EINVAL;	rc = request_firmware(&fw, filename, coredev->device);	if (rc < 0) {		sms_info("failed to open \"%s\"", filename);		return rc;	}	sms_info("read FW %s, size=%zd", filename, fw->size);	fw_buffer = kmalloc(ALIGN(fw->size, SMS_ALLOC_ALIGNMENT),			    GFP_KERNEL | GFP_DMA);	if (fw_buffer) {		memcpy(fw_buffer, fw->data, fw->size);		rc = (coredev->device_flags & SMS_DEVICE_FAMILY2) ?		      smscore_load_firmware_family2(coredev,						    fw_buffer,						    fw->size) :		      loadfirmware_handler(coredev->context,					   fw_buffer, fw->size);		kfree(fw_buffer);	} else {		sms_info("failed to allocate firmware buffer");		rc = -ENOMEM;	}	release_firmware(fw);	return rc;}/** * notifies all clients registered with the device, notifies hotplugs, * frees all buffers and coredev object * * @param coredev pointer to a coredev object returned by *                smscore_register_device * * @return 0 on success, <0 on error. */void smscore_unregister_device(struct smscore_device_t *coredev){	struct smscore_buffer_t *cb;	int num_buffers = 0;	int retry = 0;	kmutex_lock(&g_smscore_deviceslock);	smscore_notify_clients(coredev);	smscore_notify_callbacks(coredev, NULL, 0);	/* at this point all buffers should be back	 * onresponse must no longer be called */	while (1) {		while ((cb = smscore_getbuffer(coredev))) {			kfree(cb);			num_buffers++;		}		if (num_buffers == coredev->num_buffers)			break;		if (++retry > 10) {			sms_info("exiting although "				 "not all buffers released.");			break;		}		sms_info("waiting for %d buffer(s)",			 coredev->num_buffers - num_buffers);		msleep(100);	}	sms_info("freed %d buffers", num_buffers);	if (coredev->common_buffer)		dma_free_coherent(NULL, coredev->common_buffer_size,				  coredev->common_buffer,				  coredev->common_buffer_phys);	list_del(&coredev->entry);	kfree(coredev);	kmutex_unlock(&g_smscore_deviceslock);	sms_info("device %p destroyed", coredev);}static int smscore_detect_mode(struct smscore_device_t *coredev){	void *buffer = kmalloc(sizeof(struct SmsMsgHdr_ST) + SMS_DMA_ALIGNMENT,			       GFP_KERNEL | GFP_DMA);	struct SmsMsgHdr_ST *msg =		(struct SmsMsgHdr_ST *) SMS_ALIGN_ADDRESS(buffer);	int rc;	if (!buffer)		return -ENOMEM;	SMS_INIT_MSG(msg, MSG_SMS_GET_VERSION_EX_REQ,		     sizeof(struct SmsMsgHdr_ST));	rc = smscore_sendrequest_and_wait(coredev, msg, msg->msgLength,					  &coredev->version_ex_done);	if (rc == -ETIME) {		sms_err("MSG_SMS_GET_VERSION_EX_REQ failed first try");		if (wait_for_completion_timeout(&coredev->resume_done,						msecs_to_jiffies(5000))) {			rc = smscore_sendrequest_and_wait(				coredev, msg, msg->msgLength,				&coredev->version_ex_done);			if (rc < 0)				sms_err("MSG_SMS_GET_VERSION_EX_REQ failed "					"second try, rc %d", rc);		} else			rc = -ETIME;	}	kfree(buffer);	return rc;}static char *smscore_fw_lkup[][SMS_NUM_OF_DEVICE_TYPES] = {	/*Stellar		NOVA A0		Nova B0		VEGA*/	/*DVBT*/	{"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},	/*DVBH*/	{"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},	/*TDMB*/	{"none", "tdmb_nova_12mhz.inp", "none", "none"},	/*DABIP*/	{"none", "none", "none", "none"},	/*BDA*/	{"none", "dvb_nova_12mhz.inp", "dvb_nova_12mhz_b0.inp", "none"},	/*ISDBT*/	{"none", "isdbt_nova_12mhz.inp", "dvb_nova_12mhz.inp", "none"},	/*ISDBTBDA*/	{"none", "isdbt_nova_12mhz.inp", "isdbt_nova_12mhz_b0.inp", "none"},	/*CMMB*/	{"none", "none", "none", "cmmb_vega_12mhz.inp"}};static inline char *sms_get_fw_name(struct smscore_device_t *coredev,				    int mode, enum sms_device_type_st type){	char **fw = sms_get_board(smscore_get_board_id(coredev))->fw;	return (fw && fw[mode]) ? fw[mode] : smscore_fw_lkup[mode][type];}/** * calls device handler to change mode of operation * NOTE: stellar/usb may disconnect when changing mode * * @param coredev pointer to a coredev object returned by *                smscore_register_device * @param mode requested mode of operation * * @return 0 on success, <0 on error. */int smscore_set_device_mode(struct smscore_device_t *coredev, int mode){	void *buffer;	int rc = 0;	enum sms_device_type_st type;	sms_debug("set device mode to %d", mode);	if (coredev->device_flags & SMS_DEVICE_FAMILY2) {		if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_RAW_TUNER) {			sms_err("invalid mode specified %d", mode);			return -EINVAL;		}		smscore_registry_setmode(coredev->devpath, mode);		if (!(coredev->device_flags & SMS_DEVICE_NOT_READY)) {			rc = smscore_detect_mode(coredev);			if (rc < 0) {				sms_err("mode detect failed %d", rc);				return rc;			}		}		if (coredev->mode == mode) {			sms_info("device mode %d already set", mode);			return 0;		}		if (!(coredev->modes_supported & (1 << mode))) {			char *fw_filename;			type = smscore_registry_gettype(coredev->devpath);			fw_filename = sms_get_fw_name(coredev, mode, type);			rc = smscore_load_firmware_from_file(coredev,							     fw_filename, NULL);			if (rc < 0) {				sms_warn("error %d loading firmware: %s, "					 "trying again with default firmware",					 rc, fw_filename);				/* try again with the default firmware */				fw_filename = smscore_fw_lkup[mode][type];				rc = smscore_load_firmware_from_file(coredev,							     fw_filename, NULL);				if (rc < 0) {					sms_warn("error %d loading "						 "firmware: %s", rc,						 fw_filename);					return rc;				}			}			sms_log("firmware download success: %s", fw_filename);		} else			sms_info("mode %d supported by running "				 "firmware", mode);		buffer = kmalloc(sizeof(struct SmsMsgData_ST) +				 SMS_DMA_ALIGNMENT, GFP_KERNEL | GFP_DMA);		if (buffer) {			struct SmsMsgData_ST *msg =				(struct SmsMsgData_ST *)					SMS_ALIGN_ADDRESS(buffer);			SMS_INIT_MSG(&msg->xMsgHeader, MSG_SMS_INIT_DEVICE_REQ,				     sizeof(struct SmsMsgData_ST));			msg->msgData[0] = mode;			rc = smscore_sendrequest_and_wait(				coredev, msg, msg->xMsgHeader.msgLength,				&coredev->init_device_done);			kfree(buffer);		} else {			sms_err("Could not allocate buffer for "				"init device message.");			rc = -ENOMEM;		}	} else {		if (mode < DEVICE_MODE_DVBT || mode > DEVICE_MODE_DVBT_BDA) {			sms_err("invalid mode specified %d", mode);			return -EINVAL;		}		smscore_registry_setmode(coredev->devpath, mode);		if (coredev->detectmode_handler)			coredev->detectmode_handler(coredev->context,						    &coredev->mode);		if (coredev->mode != mode && coredev->setmode_handler)			rc = coredev->setmode_handler(coredev->context, mode);	}	if (rc >= 0) {		coredev->mode = mode;		coredev->device_flags &= ~SMS_DEVICE_NOT_READY;	}	if (rc != 0)		sms_err("return error code %d.", rc);	return rc;}/** * calls device handler to get current mode of operation * * @param coredev pointer to a coredev object returned by *                smscore_register_device * * @return current mode */int smscore_get_device_mode(struct smscore_device_t *coredev){	return coredev->mode;}/** * find client by response id & type within the clients list.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -