[ATM]: [adummy] dummy ATM driver (similar to net/dummy)

Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by Chas Williams and committed by David S. Miller fb296449 64bf69dd

+176
+7
drivers/atm/Kconfig
··· 5 5 menu "ATM drivers" 6 6 depends on NETDEVICES && ATM 7 7 8 + config ATM_DUMMY 9 + tristate "Dummy ATM driver" 10 + depends on ATM 11 + help 12 + Dummy ATM driver. Useful for proxy signalling, testing, 13 + and development. If unsure, say N. 14 + 8 15 config ATM_TCP 9 16 tristate "ATM over TCP" 10 17 depends on INET && ATM
+1
drivers/atm/Makefile
··· 31 31 obj-$(CONFIG_ATM_IDT77252) += suni.o 32 32 endif 33 33 34 + obj-$(CONFIG_ATM_DUMMY) += adummy.o 34 35 obj-$(CONFIG_ATM_TCP) += atmtcp.o 35 36 obj-$(CONFIG_ATM_FIRESTREAM) += firestream.o 36 37 obj-$(CONFIG_ATM_LANAI) += lanai.o
+168
drivers/atm/adummy.c
··· 1 + /* 2 + * adummy.c: a dummy ATM driver 3 + */ 4 + 5 + #include <linux/config.h> 6 + #include <linux/module.h> 7 + #include <linux/version.h> 8 + #include <linux/kernel.h> 9 + #include <linux/skbuff.h> 10 + #include <linux/pci.h> 11 + #include <linux/errno.h> 12 + #include <linux/types.h> 13 + #include <linux/string.h> 14 + #include <linux/delay.h> 15 + #include <linux/init.h> 16 + #include <linux/mm.h> 17 + #include <linux/sched.h> 18 + #include <linux/timer.h> 19 + #include <linux/interrupt.h> 20 + #include <asm/io.h> 21 + #include <asm/byteorder.h> 22 + #include <asm/uaccess.h> 23 + 24 + #include <linux/atmdev.h> 25 + #include <linux/atm.h> 26 + #include <linux/sonet.h> 27 + 28 + /* version definition */ 29 + 30 + #define DRV_VERSION "1.0" 31 + 32 + #define DEV_LABEL "adummy" 33 + 34 + #define ADUMMY_DEV(dev) ((struct adummy_dev *) (dev)->dev_data) 35 + 36 + struct adummy_dev { 37 + struct atm_dev *atm_dev; 38 + 39 + struct list_head entry; 40 + }; 41 + 42 + /* globals */ 43 + 44 + static LIST_HEAD(adummy_devs); 45 + 46 + static int __init 47 + adummy_start(struct atm_dev *dev) 48 + { 49 + dev->ci_range.vpi_bits = 4; 50 + dev->ci_range.vci_bits = 12; 51 + 52 + return 0; 53 + } 54 + 55 + static int 56 + adummy_open(struct atm_vcc *vcc) 57 + { 58 + short vpi = vcc->vpi; 59 + int vci = vcc->vci; 60 + 61 + if (vci == ATM_VCI_UNSPEC || vpi == ATM_VPI_UNSPEC) 62 + return 0; 63 + 64 + set_bit(ATM_VF_ADDR, &vcc->flags); 65 + set_bit(ATM_VF_READY, &vcc->flags); 66 + 67 + return 0; 68 + } 69 + 70 + static void 71 + adummy_close(struct atm_vcc *vcc) 72 + { 73 + clear_bit(ATM_VF_READY, &vcc->flags); 74 + clear_bit(ATM_VF_ADDR, &vcc->flags); 75 + } 76 + 77 + static int 78 + adummy_send(struct atm_vcc *vcc, struct sk_buff *skb) 79 + { 80 + if (vcc->pop) 81 + vcc->pop(vcc, skb); 82 + else 83 + dev_kfree_skb_any(skb); 84 + atomic_inc(&vcc->stats->tx); 85 + 86 + return 0; 87 + } 88 + 89 + static int 90 + adummy_proc_read(struct atm_dev *dev, loff_t *pos, char *page) 91 + { 92 + int left = *pos; 93 + 94 + if (!left--) 95 + return sprintf(page, "version %s\n", DRV_VERSION); 96 + 97 + return 0; 98 + } 99 + 100 + static struct atmdev_ops adummy_ops = 101 + { 102 + .open = adummy_open, 103 + .close = adummy_close, 104 + .send = adummy_send, 105 + .proc_read = adummy_proc_read, 106 + .owner = THIS_MODULE 107 + }; 108 + 109 + static int __init adummy_init(void) 110 + { 111 + struct atm_dev *atm_dev; 112 + struct adummy_dev *adummy_dev; 113 + int err = 0; 114 + 115 + printk(KERN_ERR "adummy: version %s\n", DRV_VERSION); 116 + 117 + adummy_dev = (struct adummy_dev *) kmalloc(sizeof(struct adummy_dev), 118 + GFP_KERNEL); 119 + if (!adummy_dev) { 120 + printk(KERN_ERR DEV_LABEL ": kmalloc() failed\n"); 121 + err = -ENOMEM; 122 + goto out; 123 + } 124 + memset(adummy_dev, 0, sizeof(struct adummy_dev)); 125 + 126 + atm_dev = atm_dev_register(DEV_LABEL, &adummy_ops, -1, 0); 127 + if (!atm_dev) { 128 + printk(KERN_ERR DEV_LABEL ": atm_dev_register() failed\n"); 129 + err = -ENODEV; 130 + goto out_kfree; 131 + } 132 + 133 + adummy_dev->atm_dev = atm_dev; 134 + atm_dev->dev_data = adummy_dev; 135 + 136 + if (adummy_start(atm_dev)) { 137 + printk(KERN_ERR DEV_LABEL ": adummy_start() failed\n"); 138 + err = -ENODEV; 139 + goto out_unregister; 140 + } 141 + 142 + list_add(&adummy_dev->entry, &adummy_devs); 143 + out: 144 + return err; 145 + 146 + out_unregister: 147 + atm_dev_deregister(atm_dev); 148 + out_kfree: 149 + kfree(adummy_dev); 150 + goto out; 151 + } 152 + 153 + static void __exit adummy_cleanup(void) 154 + { 155 + struct adummy_dev *adummy_dev, *next; 156 + 157 + list_for_each_entry_safe(adummy_dev, next, &adummy_devs, entry) { 158 + atm_dev_deregister(adummy_dev->atm_dev); 159 + kfree(adummy_dev); 160 + } 161 + } 162 + 163 + module_init(adummy_init); 164 + module_exit(adummy_cleanup); 165 + 166 + MODULE_AUTHOR("chas williams <chas@cmf.nrl.navy.mil>"); 167 + MODULE_DESCRIPTION("dummy ATM driver"); 168 + MODULE_LICENSE("GPL");