1fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams/* 2fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams * adummy.c: a dummy ATM driver 3fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams */ 4fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 5fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams#include <linux/module.h> 6fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams#include <linux/kernel.h> 7fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams#include <linux/skbuff.h> 8fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams#include <linux/errno.h> 9fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams#include <linux/types.h> 10fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams#include <linux/string.h> 11fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams#include <linux/delay.h> 12fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams#include <linux/init.h> 13fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams#include <linux/mm.h> 14fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams#include <linux/timer.h> 15fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams#include <linux/interrupt.h> 165a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 17fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams#include <asm/io.h> 18fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams#include <asm/byteorder.h> 19fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams#include <asm/uaccess.h> 20fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 21fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams#include <linux/atmdev.h> 22fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams#include <linux/atm.h> 23fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams#include <linux/sonet.h> 24fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 25fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams/* version definition */ 26fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 27fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams#define DRV_VERSION "1.0" 28fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 29fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams#define DEV_LABEL "adummy" 30fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 31fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams#define ADUMMY_DEV(dev) ((struct adummy_dev *) (dev)->dev_data) 32fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 33fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williamsstruct adummy_dev { 34fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams struct atm_dev *atm_dev; 35fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 36fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams struct list_head entry; 37fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams}; 38fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 39fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams/* globals */ 40fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 41fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williamsstatic LIST_HEAD(adummy_devs); 42fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 43c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramotostatic ssize_t __set_signal(struct device *dev, 44c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto struct device_attribute *attr, 45c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto const char *buf, size_t len) 46c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto{ 47c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto struct atm_dev *atm_dev = container_of(dev, struct atm_dev, class_dev); 48c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto int signal; 49c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto 50c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto if (sscanf(buf, "%d", &signal) == 1) { 51c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto 52c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto if (signal < ATM_PHY_SIG_LOST || signal > ATM_PHY_SIG_FOUND) 53c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto signal = ATM_PHY_SIG_UNKNOWN; 54c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto 55c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto atm_dev_signal_change(atm_dev, signal); 56c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto return 1; 57c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto } 58c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto return -EINVAL; 59c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto} 60c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto 61c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramotostatic ssize_t __show_signal(struct device *dev, 62c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto struct device_attribute *attr, char *buf) 63c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto{ 64c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto struct atm_dev *atm_dev = container_of(dev, struct atm_dev, class_dev); 65c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto return sprintf(buf, "%d\n", atm_dev->signal); 66c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto} 67c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramotostatic DEVICE_ATTR(signal, 0644, __show_signal, __set_signal); 68c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto 69c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramotostatic struct attribute *adummy_attrs[] = { 70c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto &dev_attr_signal.attr, 71c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto NULL 72c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto}; 73c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto 74c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramotostatic struct attribute_group adummy_group_attrs = { 75c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto .name = NULL, /* We want them in dev's root folder */ 76c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto .attrs = adummy_attrs 77c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto}; 78c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto 79fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williamsstatic int __init 80fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williamsadummy_start(struct atm_dev *dev) 81fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams{ 82fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams dev->ci_range.vpi_bits = 4; 83fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams dev->ci_range.vci_bits = 12; 84fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 85fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams return 0; 86fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams} 87fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 88fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williamsstatic int 89fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williamsadummy_open(struct atm_vcc *vcc) 90fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams{ 91fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams short vpi = vcc->vpi; 92fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams int vci = vcc->vci; 93fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 94fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams if (vci == ATM_VCI_UNSPEC || vpi == ATM_VPI_UNSPEC) 95fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams return 0; 96fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 97fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams set_bit(ATM_VF_ADDR, &vcc->flags); 98fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams set_bit(ATM_VF_READY, &vcc->flags); 99fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 100fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams return 0; 101fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams} 102fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 103fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williamsstatic void 104fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williamsadummy_close(struct atm_vcc *vcc) 105fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams{ 106fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams clear_bit(ATM_VF_READY, &vcc->flags); 107fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams clear_bit(ATM_VF_ADDR, &vcc->flags); 108fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams} 109fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 110fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williamsstatic int 111fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williamsadummy_send(struct atm_vcc *vcc, struct sk_buff *skb) 112fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams{ 113fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams if (vcc->pop) 114fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams vcc->pop(vcc, skb); 115fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams else 116fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams dev_kfree_skb_any(skb); 117fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams atomic_inc(&vcc->stats->tx); 118fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 119fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams return 0; 120fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams} 121fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 122fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williamsstatic int 123fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williamsadummy_proc_read(struct atm_dev *dev, loff_t *pos, char *page) 124fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams{ 125fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams int left = *pos; 126fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 127fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams if (!left--) 128fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams return sprintf(page, "version %s\n", DRV_VERSION); 129fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 130fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams return 0; 131fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams} 132fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 133fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williamsstatic struct atmdev_ops adummy_ops = 134fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams{ 135fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams .open = adummy_open, 136fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams .close = adummy_close, 137fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams .send = adummy_send, 138fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams .proc_read = adummy_proc_read, 139fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams .owner = THIS_MODULE 140fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams}; 141fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 142fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williamsstatic int __init adummy_init(void) 143fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams{ 144fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams struct atm_dev *atm_dev; 145fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams struct adummy_dev *adummy_dev; 146fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams int err = 0; 147fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 148fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams printk(KERN_ERR "adummy: version %s\n", DRV_VERSION); 149fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 1500c1cca1d8e0d58775dad43374f925e6cddf1bebcOm Narasimhan adummy_dev = kzalloc(sizeof(struct adummy_dev), 151fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams GFP_KERNEL); 152fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams if (!adummy_dev) { 1530c1cca1d8e0d58775dad43374f925e6cddf1bebcOm Narasimhan printk(KERN_ERR DEV_LABEL ": kzalloc() failed\n"); 154fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams err = -ENOMEM; 155fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams goto out; 156fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams } 157d9ca676bcb26e1fdff9265a3e70f697cd381c889Dan Williams atm_dev = atm_dev_register(DEV_LABEL, NULL, &adummy_ops, -1, NULL); 158fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams if (!atm_dev) { 159fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams printk(KERN_ERR DEV_LABEL ": atm_dev_register() failed\n"); 160fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams err = -ENODEV; 161fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams goto out_kfree; 162fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams } 163fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 164fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams adummy_dev->atm_dev = atm_dev; 165fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams atm_dev->dev_data = adummy_dev; 166fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 167c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto if (sysfs_create_group(&atm_dev->class_dev.kobj, &adummy_group_attrs)) 168c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto dev_err(&atm_dev->class_dev, "Could not register attrs for adummy\n"); 169c69fb76e8f53b36b81fd7c8a1ed251aaf6bb0386Karl Hiramoto 170fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams if (adummy_start(atm_dev)) { 171fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams printk(KERN_ERR DEV_LABEL ": adummy_start() failed\n"); 172fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams err = -ENODEV; 173fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams goto out_unregister; 174fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams } 175fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 176fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams list_add(&adummy_dev->entry, &adummy_devs); 177fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williamsout: 178fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams return err; 179fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 180fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williamsout_unregister: 181fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams atm_dev_deregister(atm_dev); 182fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williamsout_kfree: 183fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams kfree(adummy_dev); 184fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams goto out; 185fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams} 186fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 187fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williamsstatic void __exit adummy_cleanup(void) 188fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams{ 189fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams struct adummy_dev *adummy_dev, *next; 190fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 191fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams list_for_each_entry_safe(adummy_dev, next, &adummy_devs, entry) { 192fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams atm_dev_deregister(adummy_dev->atm_dev); 193fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams kfree(adummy_dev); 194fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams } 195fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams} 196fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 197fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williamsmodule_init(adummy_init); 198fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williamsmodule_exit(adummy_cleanup); 199fb29644994744a63bc57186cefa79534b5d9b5a9Chas Williams 200fb29644994744a63bc57186cefa79534b5d9b5a9Chas WilliamsMODULE_AUTHOR("chas williams <chas@cmf.nrl.navy.mil>"); 201fb29644994744a63bc57186cefa79534b5d9b5a9Chas WilliamsMODULE_DESCRIPTION("dummy ATM driver"); 202fb29644994744a63bc57186cefa79534b5d9b5a9Chas WilliamsMODULE_LICENSE("GPL"); 203