📄 l3-core.c
字号:
/* * 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)#endifstatic 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 + -