📄 l3-core_c.txt
字号:
/*
* linux/drivers/l3/l3-core.c
*
* Copyright (C) 2001 Russell King
*
* General structure taken from i2c-core.c by Simon G. Vogl
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License.
*
* See linux/Documentation/l3 for further documentation.
*/
//#define DEBUG 1
#include "debug.h"
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/slab.h>
#include <linux/proc_fs.h>
#include <linux/kmod.h>
#include <linux/init.h>
#include "l3.h"
#ifdef DEBUG
#undef pr_debug
#define pr_debug(fmt,arg...) printk(fmt,##arg)
#endif
static DECLARE_MUTEX(adapter_lock);
static LIST_HEAD(adapter_list);
static DECLARE_MUTEX(driver_lock);
static LIST_HEAD(driver_list);
/**
* l3_add_adapter - register a new L3 bus adapter
* @adap: l3_adapter structure for the registering adapter
*
* Make the adapter available for use by clients using name adap->name.
* The adap->adapters list is initialised by this function.
*
* Returns 0;
*/
int l3_add_adapter(struct l3_adapter *adap)
{
pr_debug("--- %s\n", __FUNCTION__);
down(&adapter_lock);
list_add(&adap->adapters, &adapter_list);
up(&adapter_lock);
return 0;
}
/**
* l3_del_adapter - unregister a L3 bus adapter
* @adap: l3_adapter structure to unregister
*
* Remove an adapter from the list of available L3 Bus adapters.
*
* Returns 0;
*/
int l3_del_adapter(struct l3_adapter *adap)
{
pr_debug("--- %s\n", __FUNCTION__);
down(&adapter_lock);
list_del(&adap->adapters);
up(&adapter_lock);
return 0;
}
static struct l3_adapter *__l3_get_adapter(const char *name)
{
struct list_head *l;
pr_debug("--- %s\n", __FUNCTION__);
list_for_each(l, &adapter_list) {
struct l3_adapter *adap = list_entry(l, struct l3_adapter, adapters);
if (strcmp(adap->name, name) == 0)
return adap;
}
return NULL;
}
/**
* l3_get_adapter - get a reference to an adapter
* @name: driver name
*
* Obtain a l3_adapter structure for the specified adapter. If the adapter
* is not currently load, then load it. The adapter will be locked in core
* until all references are released via l3_put_adapter.
*/
struct l3_adapter *l3_get_adapter(const char *name)
{
struct l3_adapter *adap;
int try;
pr_debug("--- %s\n", __FUNCTION__);
for (try = 0; try < 2; try ++) {
down(&adapter_lock);
adap = __l3_get_adapter(name);
if (adap && !try_module_get(adap->owner))
adap = NULL;
up(&adapter_lock);
if (adap)
break;
if (try == 0)
request_module(name);
}
return adap;
}
/**
* l3_put_adapter - release a reference to an adapter
* @adap: driver to release reference
*
* Indicate to the L3 core that you no longer require the adapter reference.
* The adapter module may be unloaded when there are no references to its
* data structure.
*
* You must not use the reference after calling this function.
*/
void l3_put_adapter(struct l3_adapter *adap)
{
pr_debug("--- %s\n", __FUNCTION__);
if (adap && adap->owner)
module_put(adap->owner);
}
/**
* l3_transfer - transfer information on an L3 bus
* @adap: adapter structure to perform transfer on
* @msgs: array of l3_msg structures describing transfer
* @num: number of l3_msg structures
*
* Transfer the specified messages to/from a device on the L3 bus.
*
* Returns number of messages successfully transferred, otherwise negative
* error code.
*/
int l3_transfer(struct l3_adapter *adap, struct l3_msg msgs[], int num)
{
int ret = -ENOSYS;
pr_debug("--- %s\n", __FUNCTION__);
if (adap->algo->xfer) {
down(adap->lock);
ret = adap->algo->xfer(adap, msgs, num);
up(adap->lock);
}
return ret;
}
/**
* l3_write - send data to a device on an L3 bus
* @adap: L3 bus adapter
* @addr: L3 bus address
* @buf: buffer for bytes to send
* @len: number of bytes to send
*
* Send len bytes pointed to by buf to device address addr on the L3 bus
* described by client.
*
* Returns the number of bytes transferred, or negative error code.
*/
int l3_write(struct l3_adapter *adap, int addr, const unsigned char *buf, int len)
{
struct l3_msg msg;
int ret;
pr_debug("--- %s\n", __FUNCTION__);
msg.addr = addr;
msg.flags = 0;
msg.buf = (char *)buf;
msg.len = len;
#ifdef DEBUG
//DEBUG
{
int i;
printk("-> %02x:", addr);
for(i=0;i<len;i++)
printk(" %02x", buf[i]);
printk("\n");
}
#endif
ret = l3_transfer(adap, &msg, 1);
return ret == 1 ? len : ret;
}
/**
* l3_read - receive data from a device on an L3 bus
* @adap: L3 bus adapter
* @addr: L3 bus address
* @buf: buffer for bytes to receive
* @len: number of bytes to receive
*
* Receive len bytes from device address addr on the L3 bus described by
* client to a buffer pointed to by buf.
*
* Returns the number of bytes transferred, or negative error code.
*/
int l3_read(struct l3_adapter *adap, int addr, char *buf, int len)
{
struct l3_msg msg;
int ret;
pr_debug("--- %s\n", __FUNCTION__);
msg.addr = addr;
msg.flags = L3_M_RD;
msg.buf = buf;
msg.len = len;
ret = l3_transfer(adap, &msg, 1);
return ret == 1 ? len : ret;
}
EXPORT_SYMBOL(l3_add_adapter);
EXPORT_SYMBOL(l3_del_adapter);
EXPORT_SYMBOL(l3_get_adapter);
EXPORT_SYMBOL(l3_put_adapter);
EXPORT_SYMBOL(l3_transfer);
EXPORT_SYMBOL(l3_write);
EXPORT_SYMBOL(l3_read);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("l3 core");
MODULE_AUTHOR("RMK");
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -