summaryrefslogtreecommitdiff
path: root/drivers/dahdi/dahdi_dynamic_eth.c
diff options
context:
space:
mode:
authorShaun Ruffell <sruffell@digium.com>2014-09-03 17:35:52 +0000
committerShaun Ruffell <sruffell@digium.com>2014-09-03 17:35:52 +0000
commit19e5621b53930e912b17d4a81e943ee6cf49f9ad (patch)
tree40a5a2294c4deb8baa63111402a3ac703a8b2602 /drivers/dahdi/dahdi_dynamic_eth.c
parent9df2805ef9a14d731fcaa1325b6b1054c1f2c101 (diff)
Point people to where active development is taking placesvn_trunk
git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@10748 a0bf4364-ded3-4de4-8d8a-66a801d63aff
Diffstat (limited to 'drivers/dahdi/dahdi_dynamic_eth.c')
-rw-r--r--drivers/dahdi/dahdi_dynamic_eth.c466
1 files changed, 0 insertions, 466 deletions
diff --git a/drivers/dahdi/dahdi_dynamic_eth.c b/drivers/dahdi/dahdi_dynamic_eth.c
deleted file mode 100644
index fd3a8cd..0000000
--- a/drivers/dahdi/dahdi_dynamic_eth.c
+++ /dev/null
@@ -1,466 +0,0 @@
-/*
- * Dynamic Span Interface for DAHDI (Ethernet Interface)
- *
- * Written by Mark Spencer <markster@digium.com>
- *
- * Copyright (C) 2001-2012, Digium, Inc.
- *
- * All rights reserved.
- *
- */
-
-/*
- * See http://www.asterisk.org for more information about
- * the Asterisk project. Please do not directly contact
- * any of the maintainers of this project for assistance;
- * the project provides a web site, mailing lists and IRC
- * channels for your use.
- *
- * This program is free software, distributed under the terms of
- * the GNU General Public License Version 2 as published by the
- * Free Software Foundation. See the LICENSE file included with
- * this program for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/slab.h>
-#include <linux/kmod.h>
-#include <linux/netdevice.h>
-#include <linux/notifier.h>
-
-#include <dahdi/kernel.h>
-
-#define ETH_P_DAHDI_DETH 0xd00d
-
-struct ztdeth_header {
- unsigned short subaddr;
-};
-
-/* We take the raw message, put it in an ethernet frame, and add a
- two byte addressing header at the top for future use */
-static DEFINE_SPINLOCK(zlock);
-
-static struct sk_buff_head skbs;
-
-static struct ztdeth {
- unsigned char addr[ETH_ALEN];
- unsigned short subaddr; /* Network byte order */
- struct dahdi_span *span;
- char ethdev[IFNAMSIZ];
- struct net_device *dev;
- struct ztdeth *next;
-} *zdevs = NULL;
-
-static struct dahdi_span *ztdeth_getspan(unsigned char *addr, unsigned short subaddr)
-{
- unsigned long flags;
- struct ztdeth *z;
- struct dahdi_span *span = NULL;
- spin_lock_irqsave(&zlock, flags);
- z = zdevs;
- while(z) {
- if (!memcmp(addr, z->addr, ETH_ALEN) &&
- z->subaddr == subaddr)
- break;
- z = z->next;
- }
- if (z)
- span = z->span;
- spin_unlock_irqrestore(&zlock, flags);
- if (!span || !test_bit(DAHDI_FLAGBIT_REGISTERED, &span->flags))
- return NULL;
- return span;
-}
-
-static int ztdeth_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev)
-{
- struct dahdi_span *span;
- struct ztdeth_header *zh;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
- zh = (struct ztdeth_header *)skb_network_header(skb);
-#else
- zh = (struct ztdeth_header *)skb->nh.raw;
-#endif
- span = ztdeth_getspan(eth_hdr(skb)->h_source, zh->subaddr);
- if (span) {
- skb_pull(skb, sizeof(struct ztdeth_header));
-#ifdef NEW_SKB_LINEARIZE
- if (skb_is_nonlinear(skb))
- skb_linearize(skb);
-#else
- if (skb_is_nonlinear(skb))
- skb_linearize(skb, GFP_KERNEL);
-#endif
- dahdi_dynamic_receive(span, (unsigned char *)skb->data, skb->len);
- }
- kfree_skb(skb);
- return 0;
-}
-
-static int ztdeth_notifier(struct notifier_block *block, unsigned long event, void *ptr)
-{
- struct net_device *dev = ptr;
- struct ztdeth *z;
- unsigned long flags;
- switch(event) {
- case NETDEV_GOING_DOWN:
- case NETDEV_DOWN:
- spin_lock_irqsave(&zlock, flags);
- z = zdevs;
- while(z) {
- /* Note that the device no longer exists */
- if (z->dev == dev)
- z->dev = NULL;
- z = z->next;
- }
- spin_unlock_irqrestore(&zlock, flags);
- break;
- case NETDEV_UP:
- spin_lock_irqsave(&zlock, flags);
- z = zdevs;
- while(z) {
- /* Now that the device exists again, use it */
- if (!strcmp(z->ethdev, dev->name))
- z->dev = dev;
- z = z->next;
- }
- spin_unlock_irqrestore(&zlock, flags);
- break;
- }
- return 0;
-}
-
-static void ztdeth_transmit(struct dahdi_dynamic *dyn, u8 *msg, size_t msglen)
-{
- struct ztdeth *z;
- struct sk_buff *skb;
- struct ztdeth_header *zh;
- unsigned long flags;
- struct net_device *dev;
- unsigned char addr[ETH_ALEN];
- unsigned short subaddr; /* Network byte order */
-
- spin_lock_irqsave(&zlock, flags);
- z = dyn->pvt;
- if (z && z->dev) {
- /* Copy fields to local variables to remove spinlock ASAP */
- dev = z->dev;
- memcpy(addr, z->addr, sizeof(z->addr));
- subaddr = z->subaddr;
- spin_unlock_irqrestore(&zlock, flags);
- skb = dev_alloc_skb(msglen + dev->hard_header_len + sizeof(struct ztdeth_header) + 32);
- if (skb) {
- /* Reserve header space */
- skb_reserve(skb, dev->hard_header_len + sizeof(struct ztdeth_header));
-
- /* Copy message body */
- memcpy(skb_put(skb, msglen), msg, msglen);
-
- /* Throw on header */
- zh = (struct ztdeth_header *)skb_push(skb, sizeof(struct ztdeth_header));
- zh->subaddr = subaddr;
-
- /* Setup protocol and such */
- skb->protocol = __constant_htons(ETH_P_DAHDI_DETH);
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)
- skb_set_network_header(skb, 0);
-#else
- skb->nh.raw = skb->data;
-#endif
- skb->dev = dev;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
- dev_hard_header(skb, dev, ETH_P_DAHDI_DETH, addr, dev->dev_addr, skb->len);
-#else
- if (dev->hard_header)
- dev->hard_header(skb, dev, ETH_P_DAHDI_DETH, addr, dev->dev_addr, skb->len);
-#endif
- skb_queue_tail(&skbs, skb);
- }
- }
- else
- spin_unlock_irqrestore(&zlock, flags);
-}
-
-/**
- * dahdi_dynamic_flush_work_fn - Flush all pending transactions.
- *
- * This function is run in a work queue since we can't guarantee interrupts
- * will be enabled when we're called, and dev_queue_xmit() requires that
- * interrupts be enabled.
- *
- */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
-static void dahdi_dynamic_flush_work_fn(void *data)
-#else
-static void dahdi_dynamic_flush_work_fn(struct work_struct *work)
-#endif
-{
- struct sk_buff *skb;
- /* Handle all transmissions now */
- while ((skb = skb_dequeue(&skbs))) {
- dev_queue_xmit(skb);
- }
-}
-
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20)
-static DECLARE_WORK(dahdi_dynamic_eth_flush_work,
- dahdi_dynamic_flush_work_fn, NULL);
-#else
-static DECLARE_WORK(dahdi_dynamic_eth_flush_work,
- dahdi_dynamic_flush_work_fn);
-#endif
-
-/**
- * ztdeth_flush - Flush all pending transactions.
- *
- * This function is called in interrupt context while processing the master
- * span.
- */
-static int ztdeth_flush(void)
-{
- schedule_work(&dahdi_dynamic_eth_flush_work);
- return 0;
-}
-
-static struct packet_type ztdeth_ptype = {
- .type = __constant_htons(ETH_P_DAHDI_DETH), /* Protocol */
- .dev = NULL, /* Device (NULL = wildcard) */
- .func = ztdeth_rcv, /* Receiver */
-};
-
-static int digit2int(char d)
-{
- switch(d) {
- case 'F':
- case 'E':
- case 'D':
- case 'C':
- case 'B':
- case 'A':
- return d - 'A' + 10;
- case 'f':
- case 'e':
- case 'd':
- case 'c':
- case 'b':
- case 'a':
- return d - 'a' + 10;
- case '9':
- case '8':
- case '7':
- case '6':
- case '5':
- case '4':
- case '3':
- case '2':
- case '1':
- case '0':
- return d - '0';
- }
- return -1;
-}
-
-static int hex2int(char *s)
-{
- int res;
- int tmp;
- /* Gotta be at least one digit */
- if (strlen(s) < 1)
- return -1;
- /* Can't be more than two */
- if (strlen(s) > 2)
- return -1;
- /* Grab the first digit */
- res = digit2int(s[0]);
- if (res < 0)
- return -1;
- tmp = res;
- /* Grab the next */
- if (strlen(s) > 1) {
- res = digit2int(s[1]);
- if (res < 0)
- return -1;
- tmp = tmp * 16 + res;
- }
- return tmp;
-}
-
-static void ztdeth_destroy(struct dahdi_dynamic *dyn)
-{
- struct ztdeth *z = dyn->pvt;
- unsigned long flags;
- struct ztdeth *prev=NULL, *cur;
- spin_lock_irqsave(&zlock, flags);
- cur = zdevs;
- while(cur) {
- if (cur == z) {
- if (prev)
- prev->next = cur->next;
- else
- zdevs = cur->next;
- break;
- }
- prev = cur;
- cur = cur->next;
- }
- if (cur == z) { /* Successfully removed */
- dyn->pvt = NULL;
- printk(KERN_INFO "TDMoE: Removed interface for %s\n", z->span->name);
- kfree(z);
- }
- spin_unlock_irqrestore(&zlock, flags);
-}
-
-static int ztdeth_create(struct dahdi_dynamic *dyn, const char *addr)
-{
- struct ztdeth *z;
- char src[256];
- char tmp[256], *tmp2, *tmp3, *tmp4 = NULL;
- int res,x;
- unsigned long flags;
- struct dahdi_span *const span = &dyn->span;
-
- z = kmalloc(sizeof(struct ztdeth), GFP_KERNEL);
- if (z) {
- /* Zero it out */
- memset(z, 0, sizeof(struct ztdeth));
-
- /* Address should be <dev>/<macaddr>[/subaddr] */
- strlcpy(tmp, addr, sizeof(tmp));
- tmp2 = strchr(tmp, '/');
- if (tmp2) {
- *tmp2 = '\0';
- tmp2++;
- strlcpy(z->ethdev, tmp, sizeof(z->ethdev));
- } else {
- printk(KERN_NOTICE "Invalid TDMoE address (no device) '%s'\n", addr);
- kfree(z);
- return -EINVAL;
- }
- if (tmp2) {
- tmp4 = strchr(tmp2+1, '/');
- if (tmp4) {
- *tmp4 = '\0';
- tmp4++;
- }
- /* We don't have SSCANF :( Gotta do this the hard way */
- tmp3 = strchr(tmp2, ':');
- for (x=0;x<6;x++) {
- if (tmp2) {
- if (tmp3) {
- *tmp3 = '\0';
- tmp3++;
- }
- res = hex2int(tmp2);
- if (res < 0)
- break;
- z->addr[x] = res & 0xff;
- } else
- break;
- if ((tmp2 = tmp3))
- tmp3 = strchr(tmp2, ':');
- }
- if (x != 6) {
- printk(KERN_NOTICE "TDMoE: Invalid MAC address in: %s\n", addr);
- kfree(z);
- return -EINVAL;
- }
- } else {
- printk(KERN_NOTICE "TDMoE: Missing MAC address\n");
- kfree(z);
- return -EINVAL;
- }
- if (tmp4) {
- int sub = 0;
- int mul = 1;
-
- /* We have a subaddr */
- tmp3 = tmp4 + strlen (tmp4) - 1;
- while (tmp3 >= tmp4) {
- if (*tmp3 >= '0' && *tmp3 <= '9') {
- sub += (*tmp3 - '0') * mul;
- } else {
- printk(KERN_NOTICE "TDMoE: Invalid subaddress\n");
- kfree(z);
- return -EINVAL;
- }
- mul *= 10;
- tmp3--;
- }
- z->subaddr = htons(sub);
- }
- z->dev = dev_get_by_name(
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
- &init_net,
-#endif
- z->ethdev);
- if (!z->dev) {
- printk(KERN_NOTICE "TDMoE: Invalid device '%s'\n", z->ethdev);
- kfree(z);
- return -EINVAL;
- }
- z->span = span;
- src[0] ='\0';
- for (x=0;x<5;x++)
- sprintf(src + strlen(src), "%02x:", z->dev->dev_addr[x]);
- sprintf(src + strlen(src), "%02x", z->dev->dev_addr[5]);
- printk(KERN_INFO "TDMoE: Added new interface for %s at %s (addr=%s, src=%s, subaddr=%d)\n", span->name, z->dev->name, addr, src, ntohs(z->subaddr));
-
- spin_lock_irqsave(&zlock, flags);
- z->next = zdevs;
- zdevs = z;
- dyn->pvt = z;
- spin_unlock_irqrestore(&zlock, flags);
- }
- return (z) ? 0 : -ENOMEM;
-}
-
-static struct dahdi_dynamic_driver ztd_eth = {
- .owner = THIS_MODULE,
- .name = "eth",
- .desc = "Ethernet",
- .create = ztdeth_create,
- .destroy = ztdeth_destroy,
- .transmit = ztdeth_transmit,
- .flush = ztdeth_flush,
-};
-
-static struct notifier_block ztdeth_nblock = {
- .notifier_call = ztdeth_notifier,
-};
-
-static int __init ztdeth_init(void)
-{
- skb_queue_head_init(&skbs);
-
- dev_add_pack(&ztdeth_ptype);
- register_netdevice_notifier(&ztdeth_nblock);
- dahdi_dynamic_register_driver(&ztd_eth);
-
- return 0;
-}
-
-static void __exit ztdeth_exit(void)
-{
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 22)
- flush_scheduled_work();
-#else
- cancel_work_sync(&dahdi_dynamic_eth_flush_work);
-#endif
- dahdi_dynamic_unregister_driver(&ztd_eth);
- unregister_netdevice_notifier(&ztdeth_nblock);
- dev_remove_pack(&ztdeth_ptype);
-
- skb_queue_purge(&skbs);
-}
-
-MODULE_DESCRIPTION("DAHDI Dynamic TDMoE Support");
-MODULE_AUTHOR("Mark Spencer <markster@digium.com>");
-MODULE_LICENSE("GPL v2");
-
-module_init(ztdeth_init);
-module_exit(ztdeth_exit);