OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [net/] [wan/] [hdlc_raw_eth.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * Generic HDLC support routines for Linux
3
 * HDLC Ethernet emulation support
4
 *
5
 * Copyright (C) 2002-2006 Krzysztof Halasa <khc@pm.waw.pl>
6
 *
7
 * This program is free software; you can redistribute it and/or modify it
8
 * under the terms of version 2 of the GNU General Public License
9
 * as published by the Free Software Foundation.
10
 */
11
 
12
#include <linux/module.h>
13
#include <linux/kernel.h>
14
#include <linux/slab.h>
15
#include <linux/poll.h>
16
#include <linux/errno.h>
17
#include <linux/if_arp.h>
18
#include <linux/init.h>
19
#include <linux/skbuff.h>
20
#include <linux/pkt_sched.h>
21
#include <linux/random.h>
22
#include <linux/inetdevice.h>
23
#include <linux/lapb.h>
24
#include <linux/rtnetlink.h>
25
#include <linux/etherdevice.h>
26
#include <linux/hdlc.h>
27
 
28
static int raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr);
29
 
30
static int eth_tx(struct sk_buff *skb, struct net_device *dev)
31
{
32
        int pad = ETH_ZLEN - skb->len;
33
        if (pad > 0) {           /* Pad the frame with zeros */
34
                int len = skb->len;
35
                if (skb_tailroom(skb) < pad)
36
                        if (pskb_expand_head(skb, 0, pad, GFP_ATOMIC)) {
37
                                hdlc_stats(dev)->tx_dropped++;
38
                                dev_kfree_skb(skb);
39
                                return 0;
40
                        }
41
                skb_put(skb, pad);
42
                memset(skb->data + len, 0, pad);
43
        }
44
        return dev_to_hdlc(dev)->xmit(skb, dev);
45
}
46
 
47
 
48
static struct hdlc_proto proto = {
49
        .type_trans     = eth_type_trans,
50
        .ioctl          = raw_eth_ioctl,
51
        .module         = THIS_MODULE,
52
};
53
 
54
 
55
static int raw_eth_ioctl(struct net_device *dev, struct ifreq *ifr)
56
{
57
        raw_hdlc_proto __user *raw_s = ifr->ifr_settings.ifs_ifsu.raw_hdlc;
58
        const size_t size = sizeof(raw_hdlc_proto);
59
        raw_hdlc_proto new_settings;
60
        hdlc_device *hdlc = dev_to_hdlc(dev);
61
        int result;
62
        void *old_ch_mtu;
63
        int old_qlen;
64
 
65
        switch (ifr->ifr_settings.type) {
66
        case IF_GET_PROTO:
67
                if (dev_to_hdlc(dev)->proto != &proto)
68
                        return -EINVAL;
69
                ifr->ifr_settings.type = IF_PROTO_HDLC_ETH;
70
                if (ifr->ifr_settings.size < size) {
71
                        ifr->ifr_settings.size = size; /* data size wanted */
72
                        return -ENOBUFS;
73
                }
74
                if (copy_to_user(raw_s, hdlc->state, size))
75
                        return -EFAULT;
76
                return 0;
77
 
78
        case IF_PROTO_HDLC_ETH:
79
                if (!capable(CAP_NET_ADMIN))
80
                        return -EPERM;
81
 
82
                if (dev->flags & IFF_UP)
83
                        return -EBUSY;
84
 
85
                if (copy_from_user(&new_settings, raw_s, size))
86
                        return -EFAULT;
87
 
88
                if (new_settings.encoding == ENCODING_DEFAULT)
89
                        new_settings.encoding = ENCODING_NRZ;
90
 
91
                if (new_settings.parity == PARITY_DEFAULT)
92
                        new_settings.parity = PARITY_CRC16_PR1_CCITT;
93
 
94
                result = hdlc->attach(dev, new_settings.encoding,
95
                                      new_settings.parity);
96
                if (result)
97
                        return result;
98
 
99
                result = attach_hdlc_protocol(dev, &proto, NULL,
100
                                              sizeof(raw_hdlc_proto));
101
                if (result)
102
                        return result;
103
                memcpy(hdlc->state, &new_settings, size);
104
                dev->hard_start_xmit = eth_tx;
105
                old_ch_mtu = dev->change_mtu;
106
                old_qlen = dev->tx_queue_len;
107
                ether_setup(dev);
108
                dev->change_mtu = old_ch_mtu;
109
                dev->tx_queue_len = old_qlen;
110
                memcpy(dev->dev_addr, "\x00\x01", 2);
111
                get_random_bytes(dev->dev_addr + 2, ETH_ALEN - 2);
112
                netif_dormant_off(dev);
113
                return 0;
114
        }
115
 
116
        return -EINVAL;
117
}
118
 
119
 
120
static int __init mod_init(void)
121
{
122
        register_hdlc_protocol(&proto);
123
        return 0;
124
}
125
 
126
 
127
 
128
static void __exit mod_exit(void)
129
{
130
        unregister_hdlc_protocol(&proto);
131
}
132
 
133
 
134
module_init(mod_init);
135
module_exit(mod_exit);
136
 
137
MODULE_AUTHOR("Krzysztof Halasa <khc@pm.waw.pl>");
138
MODULE_DESCRIPTION("Ethernet encapsulation support for generic HDLC");
139
MODULE_LICENSE("GPL v2");

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.