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

📄 smscoreapi.c

📁 trident tm5600的linux驱动
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *  Siano core API module * *  This file contains implementation for the interface to sms core component * *  author: Anatoly Greenblat * *  Copyright (c), 2005-2008 Siano Mobile Silicon, Inc. * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License version 2 as *  published by the Free Software Foundation; * *  Software distributed under the License is distributed on an "AS IS" *  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. * *  See the GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <linux/kernel.h>#include <linux/init.h>#include <linux/module.h>#include <linux/moduleparam.h>#include <linux/dma-mapping.h>#include <linux/delay.h>#include <linux/io.h>#include <linux/firmware.h>#include "smscoreapi.h"#include "sms-cards.h"int sms_debug;module_param_named(debug, sms_debug, int, 0644);MODULE_PARM_DESC(debug, "set debug level (info=1, adv=2 (or-able))");struct smscore_device_notifyee_t {	struct list_head entry;	hotplug_t hotplug;};struct smscore_idlist_t {	struct list_head entry;	int		id;	int		data_type;};struct smscore_client_t {	struct list_head entry;	struct smscore_device_t *coredev;	void			*context;	struct list_head 	idlist;	onresponse_t	onresponse_handler;	onremove_t		onremove_handler;};struct smscore_device_t {	struct list_head entry;	struct list_head clients;	struct list_head subclients;	spinlock_t		clientslock;	struct list_head buffers;	spinlock_t		bufferslock;	int				num_buffers;	void			*common_buffer;	int				common_buffer_size;	dma_addr_t		common_buffer_phys;	void			*context;	struct device	*device;	char			devpath[32];	unsigned long	device_flags;	setmode_t		setmode_handler;	detectmode_t	detectmode_handler;	sendrequest_t	sendrequest_handler;	preload_t		preload_handler;	postload_t		postload_handler;	int				mode, modes_supported;	struct completion version_ex_done, data_download_done, trigger_done;	struct completion init_device_done, reload_start_done, resume_done;	int board_id;};void smscore_set_board_id(struct smscore_device_t *core, int id){	core->board_id = id;}int smscore_get_board_id(struct smscore_device_t *core){	return core->board_id;}struct smscore_registry_entry_t {	struct list_head entry;	char			devpath[32];	int				mode;	enum sms_device_type_st	type;};static struct list_head g_smscore_notifyees;static struct list_head g_smscore_devices;static struct mutex g_smscore_deviceslock;static struct list_head g_smscore_registry;static struct mutex g_smscore_registrylock;static int default_mode = 4;module_param(default_mode, int, 0644);MODULE_PARM_DESC(default_mode, "default firmware id (device mode)");static struct smscore_registry_entry_t *smscore_find_registry(char *devpath){	struct smscore_registry_entry_t *entry;	struct list_head *next;	kmutex_lock(&g_smscore_registrylock);	for (next = g_smscore_registry.next;	     next != &g_smscore_registry;	     next = next->next) {		entry = (struct smscore_registry_entry_t *) next;		if (!strcmp(entry->devpath, devpath)) {			kmutex_unlock(&g_smscore_registrylock);			return entry;		}	}	entry = (struct smscore_registry_entry_t *)			kmalloc(sizeof(struct smscore_registry_entry_t),				GFP_KERNEL);	if (entry) {		entry->mode = default_mode;		strcpy(entry->devpath, devpath);		list_add(&entry->entry, &g_smscore_registry);	} else		sms_err("failed to create smscore_registry.");	kmutex_unlock(&g_smscore_registrylock);	return entry;}int smscore_registry_getmode(char *devpath){	struct smscore_registry_entry_t *entry;	entry = smscore_find_registry(devpath);	if (entry)		return entry->mode;	else		sms_err("No registry found.");	return default_mode;}static enum sms_device_type_st smscore_registry_gettype(char *devpath){	struct smscore_registry_entry_t *entry;	entry = smscore_find_registry(devpath);	if (entry)		return entry->type;	else		sms_err("No registry found.");	return -1;}void smscore_registry_setmode(char *devpath, int mode){	struct smscore_registry_entry_t *entry;	entry = smscore_find_registry(devpath);	if (entry)		entry->mode = mode;	else		sms_err("No registry found.");}static void smscore_registry_settype(char *devpath,				     enum sms_device_type_st type){	struct smscore_registry_entry_t *entry;	entry = smscore_find_registry(devpath);	if (entry)		entry->type = type;	else		sms_err("No registry found.");}static void list_add_locked(struct list_head *new, struct list_head *head,			    spinlock_t *lock){	unsigned long flags;	spin_lock_irqsave(lock, flags);	list_add(new, head);	spin_unlock_irqrestore(lock, flags);}/** * register a client callback that called when device plugged in/unplugged * NOTE: if devices exist callback is called immediately for each device * * @param hotplug callback * * @return 0 on success, <0 on error. */int smscore_register_hotplug(hotplug_t hotplug){	struct smscore_device_notifyee_t *notifyee;	struct list_head *next, *first;	int rc = 0;	kmutex_lock(&g_smscore_deviceslock);	notifyee = kmalloc(sizeof(struct smscore_device_notifyee_t),			   GFP_KERNEL);	if (notifyee) {		/* now notify callback about existing devices */		first = &g_smscore_devices;		for (next = first->next;		     next != first && !rc;		     next = next->next) {			struct smscore_device_t *coredev =				(struct smscore_device_t *) next;			rc = hotplug(coredev, coredev->device, 1);		}		if (rc >= 0) {			notifyee->hotplug = hotplug;			list_add(&notifyee->entry, &g_smscore_notifyees);		} else			kfree(notifyee);	} else		rc = -ENOMEM;	kmutex_unlock(&g_smscore_deviceslock);	return rc;}/** * unregister a client callback that called when device plugged in/unplugged * * @param hotplug callback * */void smscore_unregister_hotplug(hotplug_t hotplug){	struct list_head *next, *first;	kmutex_lock(&g_smscore_deviceslock);	first = &g_smscore_notifyees;	for (next = first->next; next != first;) {		struct smscore_device_notifyee_t *notifyee =			(struct smscore_device_notifyee_t *) next;		next = next->next;		if (notifyee->hotplug == hotplug) {			list_del(&notifyee->entry);			kfree(notifyee);		}	}	kmutex_unlock(&g_smscore_deviceslock);}static void smscore_notify_clients(struct smscore_device_t *coredev){	struct smscore_client_t *client;	/* the client must call smscore_unregister_client from remove handler */	while (!list_empty(&coredev->clients)) {		client = (struct smscore_client_t *) coredev->clients.next;		client->onremove_handler(client->context);	}}static int smscore_notify_callbacks(struct smscore_device_t *coredev,				    struct device *device, int arrival){	struct list_head *next, *first;	int rc = 0;	/* note: must be called under g_deviceslock */	first = &g_smscore_notifyees;	for (next = first->next; next != first; next = next->next) {		rc = ((struct smscore_device_notifyee_t *) next)->				hotplug(coredev, device, arrival);		if (rc < 0)			break;	}	return rc;}static structsmscore_buffer_t *smscore_createbuffer(u8 *buffer, void *common_buffer,				       dma_addr_t common_buffer_phys){	struct smscore_buffer_t *cb =		kmalloc(sizeof(struct smscore_buffer_t), GFP_KERNEL);	if (!cb) {		sms_info("kmalloc(...) failed");		return NULL;	}	cb->p = buffer;	cb->offset_in_common = buffer - (u8 *) common_buffer;	cb->phys = common_buffer_phys + cb->offset_in_common;	return cb;}/** * creates coredev object for a device, prepares buffers, * creates buffer mappings, notifies registered hotplugs about new device. * * @param params device pointer to struct with device specific parameters *               and handlers * @param coredev pointer to a value that receives created coredev object * * @return 0 on success, <0 on error. */int smscore_register_device(struct smsdevice_params_t *params,			    struct smscore_device_t **coredev){	struct smscore_device_t *dev;	u8 *buffer;	dev = kzalloc(sizeof(struct smscore_device_t), GFP_KERNEL);	if (!dev) {		sms_info("kzalloc(...) failed");		return -ENOMEM;	}	/* init list entry so it could be safe in smscore_unregister_device */	INIT_LIST_HEAD(&dev->entry);	/* init queues */	INIT_LIST_HEAD(&dev->clients);	INIT_LIST_HEAD(&dev->buffers);	/* init locks */	spin_lock_init(&dev->clientslock);	spin_lock_init(&dev->bufferslock);	/* init completion events */	init_completion(&dev->version_ex_done);	init_completion(&dev->data_download_done);	init_completion(&dev->trigger_done);	init_completion(&dev->init_device_done);	init_completion(&dev->reload_start_done);	init_completion(&dev->resume_done);	/* alloc common buffer */	dev->common_buffer_size = params->buffer_size * params->num_buffers;	dev->common_buffer = dma_alloc_coherent(NULL, dev->common_buffer_size,						&dev->common_buffer_phys,						GFP_KERNEL | GFP_DMA);	if (!dev->common_buffer) {		smscore_unregister_device(dev);		return -ENOMEM;	}	/* prepare dma buffers */	for (buffer = dev->common_buffer;	     dev->num_buffers < params->num_buffers;	     dev->num_buffers++, buffer += params->buffer_size) {		struct smscore_buffer_t *cb =			smscore_createbuffer(buffer, dev->common_buffer,					     dev->common_buffer_phys);		if (!cb) {			smscore_unregister_device(dev);			return -ENOMEM;		}		smscore_putbuffer(dev, cb);	}	sms_info("allocated %d buffers", dev->num_buffers);	dev->mode = DEVICE_MODE_NONE;	dev->context = params->context;	dev->device = params->device;	dev->setmode_handler = params->setmode_handler;	dev->detectmode_handler = params->detectmode_handler;	dev->sendrequest_handler = params->sendrequest_handler;	dev->preload_handler = params->preload_handler;	dev->postload_handler = params->postload_handler;	dev->device_flags = params->flags;	strcpy(dev->devpath, params->devpath);	smscore_registry_settype(dev->devpath, params->device_type);	/* add device to devices list */	kmutex_lock(&g_smscore_deviceslock);	list_add(&dev->entry, &g_smscore_devices);	kmutex_unlock(&g_smscore_deviceslock);	*coredev = dev;	sms_info("device %p created", dev);	return 0;}/** * sets initial device mode and notifies client hotplugs that device is ready * * @param coredev pointer to a coredev object returned by * 		  smscore_register_device * * @return 0 on success, <0 on error. */int smscore_start_device(struct smscore_device_t *coredev){	int rc = smscore_set_device_mode(

⌨️ 快捷键说明

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