/*
* Linux ARCnet driver - device-independent routines
*/
#define VERSION "arcnet: v3.94 BETA 2007/02/08 - by Avery Pennarun et al.\n"
#include <linux/module.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/netdevice.h>
#include <linux/if_arp.h>
#include <net/arp.h>
#include <linux/init.h>
#include <linux/arcdevice.h>
#include <linux/jiffies.h>
/* "do nothing" functions for protocol drivers */
static void null_rx(struct net_device *dev, int bufnum,
struct archdr *pkthdr, int length);
static int null_build_header(struct sk_buff *skb, struct net_device *dev,
unsigned short type, uint8_t daddr);
static int null_prepare_tx(struct net_device *dev, struct archdr *pkt,
int length, int bufnum);
static void arcnet_rx(struct net_device *dev, int bufnum);
/*
* one ArcProto per possible proto ID. None of the elements of
* arc_proto_map are allowed to be NULL; they will get set to
* arc_proto_default instead. It also must not be NULL; if you would like
* to set it to NULL, set it to &arc_proto_null instead.
*/
struct ArcProto *arc_proto_map[256], *arc_proto_default,
*arc_bcast_proto, *arc_raw_proto;
static struct ArcProto arc_proto_null =
{
.suffix = '?',
.mtu = XMTU,
.is_ip = 0,
.rx = null_rx,
.build_header = null_build_header,
.prepare_tx = null_prepare_tx,
.continue_tx = NULL,
.ack_tx = NULL
};
/* Exported function prototypes */
int arcnet_debug = ARCNET_DEBUG;
EXPORT_SYMBOL(arc_proto_map);
EXPORT_SYMBOL(arc_proto_default);
EXPORT_SYMBOL(arc_bcast_proto);
EXPORT_SYMBOL(arc_raw_proto);
EXPORT_SYMBOL(arcnet_unregister_proto);
EXPORT_SYMBOL(arcnet_debug);
EXPORT_SYMBOL(alloc_arcdev);
EXPORT_SYMBOL(arcnet_interrupt);
EXPORT_SYMBOL(arcnet_open);
EXPORT_SYMBOL(arcnet_close);
EXPORT_SYMBOL(arcnet_send_packet);
EXPORT_SYMBOL(arcnet_timeout);
/* Internal function prototypes */
static int arcnet_header(struct sk_buff *skb, struct net_device *dev,
unsigned short type, const void *daddr,
const void *saddr, unsigned len);
static int arcnet_rebuild_header(struct sk_buff *skb);
static int go_tx(struct net_device *dev);
static int debug = ARCNET_DEBUG;
module_param(debug, int, 0);
MODULE_LICENSE("GPL");
static int __init arcnet_init(void)
{
int count;
arcnet_debug = debug;
printk("arcnet loaded.\n");
#ifdef ALPHA_WARNING
BUGLVL(D_EXTRA) {
printk("arcnet: ***\n"
"arcnet: * Read arcnet.txt for important release notes!\n"
"arcnet: *\n"
"arcnet: * This is an ALPHA version! (Last stable release: v3.02) E-mail\n"
"arcnet: * me if you have any questions, comments, or bug reports.\n"
"arcnet: ***\n");
}
#endif
/* initialize the protocol map */
arc_raw_proto = arc_proto_default = arc_bcast_proto = &arc_proto_null;
for (count = 0; count < 256; count++)
arc_proto_map[count] = arc_proto_default;
BUGLVL(D_DURING)
printk("arcnet: struct sizes: %Zd %Zd %Zd %Zd %Zd\n",
sizeof(struct arc_hardware), sizeof(struct arc_rfc1201),
sizeof(struct arc_rfc1051), sizeof(struct arc_eth_encap),
sizeof(struct archdr));
return 0;
}
static void __exit arcnet_exit(void)
{
}
module_init(arcnet_init);
module_exit(arcnet_exit);
/*
* Dump the contents of an sk_buff
*/
#if ARCNET_DEBUG_MAX & D_SKB
void arcnet_dump_skb(struct net_device *dev,
struct sk_buff *skb, char *desc)
{
char hdr[32];
/* dump the packet */
snprintf(hdr, sizeof(hdr), "%6s:%s skb->data:", dev->name, desc);
print_hex_dump(KERN_DEBUG, hdr, DUMP_PREFIX_OFFSET,
16, 1, skb->data, skb->len, true);
}
EXPORT_SYMBOL(arcnet_dump_skb);
#endif
/*
* Dump the contents of an ARCnet buffer
*/
#if (ARCNET_DEBUG_MAX & (D_RX | D_TX))
static void arcnet_dump_packet(struct net_device *dev, int bufnum,
char *desc, int take_arcnet_lock)
{
struct arcnet_local *lp = netdev_priv(dev);
int i, length;
unsigned long flags = 0;
static uint8_t buf[512];
char hdr[32];
/* hw.copy_from_card expects IRQ context so take the IRQ lock
to keep it single threaded */
if(take_arcnet_lock)
spin_lock_irqsave(&lp->lock, flags);
lp->hw.copy_from_card(dev, bufnum, 0, buf, 512);
if(take_arcnet_lock)
spin_unlock_irqrestore(&lp->lock, flags);
/* if the offset[0] byte is nonzero, this is a 256-byte packet */
length = (buf[2] ? 256 : 512);
/* dump the packet */
snprintf(hdr, sizeof(hdr), "%6s:%s packet dump:", dev->name, desc);
print_hex_dump(KERN_DEBUG, hdr, DUMP_PREFIX_OFFSET,
16, 1, buf, length, true);
}
#else
#define arcnet_dump_packet(dev, bufnum, desc,take_arcnet_lock) do { } while (0)
#endif
/*
* Unregister a protocol driver from the arc_proto_map. Protocol drivers
* are responsible for registering themselves, but the unregister routine
* is pretty generic so we'll do it here.
*/
void arcnet_unregister_proto(struct ArcProto *proto)
{
int count;
if (arc_proto_default == proto)
arc_proto_default = &arc_proto_null;
if (arc_bcast_proto == proto)
arc_bcast_proto = arc_proto_default;
if (arc_raw_proto == proto)
arc_raw_proto = arc_proto_default;
for (count = 0; count < 256; count++) {
if (arc_proto_map[count] == proto)
arc_proto_map[count] = arc_proto_default;
}
}
/*
* Add a buffer to the queue. Only the interrupt handler is allowed to do
* this, unless interrupts are disabled.
*
* Note: we don't check for a full queue, since there aren't enough buffers
* to more than fill it.
*/
static void release_arcbuf(struct net_device *dev, int bufnum)
{
struct arcnet_local *lp = netdev_priv(dev);
int i;
lp->buf_queue[lp->first_free_buf++] = bufnum;
lp->first_free_buf %= 5;
BUGLVL(D_DURING) {
BUGMSG(D_DURING, "release_arcbuf: freed #%d; buffer queue is now: ",
bufnum);
for (i = lp->next_buf; i != lp->first_free_buf; i = (i+1) % 5)
BUGMSG2(D_DURING, "#%d ", lp->buf_queue[i]);
BUGMSG2(D_DURING, "\n");
}
}
/*
* Get a buffer from the queue. If this returns -1, there are no buffers
* available.
*/
static int get_arcbuf(struct net_device *dev)
{
struct arcnet_local *lp = netdev_priv(dev);
int buf = -1, i;
if (!atomic_dec_and_test(&lp->buf_lock)) {
/* already in this function */
BUGMSG(D_NORMAL, "get_arcbuf: overlap (%d)!\n",
lp->buf_lock.counter);
}
else { /* we can continue */
if (lp->next_buf >= 5)
lp->next_buf -= 5;
if (lp->next_buf == lp->first_free_buf)
BUGMSG(D_NORMAL, "get_arcbuf: BUG: no buffers are available??\n");
else {
buf = lp->buf_queue[lp->next_buf++];
lp->next_buf %= 5;
}
}
BUGLVL(D_DURING) {
BUGMSG(D_DURING, "get_arcbuf: got #%d; buffer queue is now: ", buf);
for (i = lp->next_buf; i != lp->first_free_buf; i = (i+1) % 5)
BUGMSG2(D_DURING, "#%d ", lp->buf_queue[i]);
BUGMSG2(D_DURING, "\n");
}
atomic_inc(&lp->buf_lock);
return buf;
}
static int choose_mtu(void)
{
int count, mtu = 65535;
/* choose the smallest MTU of all available encaps */
for (count = 0; count < 256; count++) {
if (arc_proto_map[count] != &arc_proto_null &&
arc_proto_map[count]->mtu < mtu) {
mtu = arc_proto_map[count]->mtu;
}
}
return mtu == 65535 ? XMTU : mtu;
}
static const struct header_ops arcnet_header_ops = {
.create = arcnet_header,
.rebuild = arcnet_rebuild_header,
};
static const struct net_device_ops arcnet_netdev_ops = {
.ndo_open = arcnet_open,
.ndo_stop = arcnet_close,
.ndo_start_xmit = arcnet_send_packet,
.ndo_tx_timeout = arcnet_timeout,
};
/* Setup a struct device for ARCnet. */
static void arcdev_setup(struct net_device *dev)
{
dev->type = ARPHRD_ARCNET;
dev->netdev_ops = &arcnet_netdev_ops;
dev->header_ops = &arcnet_header_ops;
dev->hard_header_len = sizeof(struct archdr);
dev->mtu = choose_mtu();
dev->addr_len = ARCNET_ALEN;
dev->tx_queue_len = 100;
dev->broadcast[0] = 0x00; /* for us, broadcasts are address 0 */
dev->watchdog_timeo = TX_TIMEOUT;
/* New-style flags. */
dev->flags = IFF_BROADCAST;
}
struct net_device *alloc_arcdev(const char *name)
{
struct net_device *dev;
dev = allo
arcnet.rar_arcnet
版权申诉
123 浏览量
2022-09-24
19:49:21
上传
评论
收藏 9KB RAR 举报
寒泊
- 粉丝: 75
- 资源: 1万+
最新资源
- 基于Typescript的兔子饭店经营类游戏源码设计免费送cocoscreator
- 基于Java的web快速开发数据权限管理脚手架wonder-server设计源码
- 基于Apache Log4cxx的C++日志库设计源码
- 基于Vue3的likeadmin免费任意商用管理后台设计源码
- 基于JavaScript的Chrome扩展WeNote分享插件设计源码
- 基于C++的中泰EM9108S动态库开发示例源码
- gxlx2-p291-1g.dts和gxlx2-p291-1g.dtb
- STM32WBxx Keil芯片包
- 基于CNN+Bi-LSTM+Attention 的自动对对联系统
- 基于Java的IndexBar Android字母索引栏设计源码
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈