[svn-commits] tzafrir: branch linux/tzafrir/sysfs r5443 - in /linux/team/tzafrir/sysfs: dri...
SVN commits to the Digium repositories
svn-commits at lists.digium.com
Fri Dec 5 11:19:39 CST 2008
Author: tzafrir
Date: Fri Dec 5 11:19:38 2008
New Revision: 5443
URL: http://svn.digium.com/view/dahdi?view=rev&rev=5443
Log:
Spans and Channels under /sys/bus/dahdi
Spans show up as: /sys/devices/dahdi/span-XXX
Channels show up as: /sys/devices/dahdi/span-XXX/XXX:YY
Current extra span attributes: desc, devicetype, manufacturer, name,
spantype.
No extra channel attributes yet.
Added:
linux/team/tzafrir/sysfs/drivers/dahdi/dahdi-sysfs.c (with props)
linux/team/tzafrir/sysfs/drivers/dahdi/dahdi-sysfs.h (with props)
Modified:
linux/team/tzafrir/sysfs/drivers/dahdi/Kbuild
linux/team/tzafrir/sysfs/drivers/dahdi/dahdi-base.c
linux/team/tzafrir/sysfs/include/dahdi/kernel.h
Modified: linux/team/tzafrir/sysfs/drivers/dahdi/Kbuild
URL: http://svn.digium.com/view/dahdi/linux/team/tzafrir/sysfs/drivers/dahdi/Kbuild?view=diff&rev=5443&r1=5442&r2=5443
==============================================================================
--- linux/team/tzafrir/sysfs/drivers/dahdi/Kbuild (original)
+++ linux/team/tzafrir/sysfs/drivers/dahdi/Kbuild Fri Dec 5 11:19:38 2008
@@ -56,7 +56,7 @@
EXTRA_CFLAGS+=-Drw_lock_t=rwlock_t
endif
-dahdi-objs := dahdi-base.o
+dahdi-objs := dahdi-base.o dahdi-sysfs.o
dahdi_echocan_hpec-objs := hpec/dahdi_echocan_hpec.o
CFLAGS_dahdi_echocan_hpec.o := -I$(src)/hpec
Modified: linux/team/tzafrir/sysfs/drivers/dahdi/dahdi-base.c
URL: http://svn.digium.com/view/dahdi/linux/team/tzafrir/sysfs/drivers/dahdi/dahdi-base.c?view=diff&rev=5443&r1=5442&r2=5443
==============================================================================
--- linux/team/tzafrir/sysfs/drivers/dahdi/dahdi-base.c (original)
+++ linux/team/tzafrir/sysfs/drivers/dahdi/dahdi-base.c Fri Dec 5 11:19:38 2008
@@ -83,6 +83,8 @@
#define FAST_HDLC_NEED_TABLES
#include <dahdi/kernel.h>
+#include "dahdi-sysfs.h"
+
#include "hpec/hpec_user.h"
/* Get helper arithmetic */
@@ -200,7 +202,7 @@
static int deftaps = 64;
-static int debug;
+int debug;
/*!
* \brief states for transmit signalling
@@ -5349,6 +5351,7 @@
int dahdi_register(struct dahdi_span *span, int prefmaster)
{
int x;
+ int res = 0;
if (!span)
return -EINVAL;
@@ -5402,6 +5405,13 @@
dahdi_chan_reg(span->chans[x]);
}
+ res = span_sysfs_create(span);
+ if (res != 0) {
+ module_printk(KERN_ERR, "Span %s sysfs initialization failed\n",
+ span->name);
+ goto err_sysfs_span;
+ }
+
#ifdef CONFIG_PROC_FS
{
char tempfile[17];
@@ -5435,6 +5445,14 @@
}
return 0;
+
+err_sysfs_span:
+ for (x = 0; x < span->channels; x++) {
+ dahdi_chan_unreg(span->chans[x]);
+ //span->chans[x]->span = NULL; /* FIXME: Required? */
+ }
+ span->flags &= DAHDI_FLAG_REGISTERED;
+ return res;
}
int dahdi_unregister(struct dahdi_span *span)
@@ -5477,6 +5495,7 @@
span->flags &= ~DAHDI_FLAG_REGISTERED;
for (x=0;x<span->channels;x++)
dahdi_chan_unreg(span->chans[x]);
+ span_sysfs_remove(span);
new_maxspans = 0;
new_master = master; /* FIXME: locking */
if (master == span)
@@ -7881,6 +7900,14 @@
return res;
}
+ res = dahdi_driver_init();
+ if (res != 0) {
+ // TODO: Remove this. dahdi_driver_init should report
+ // errors.
+ module_printk(KERN_ERR, "Error starting sysfs: %d\n", res);
+ return res;
+ }
+
dahdi_class = class_create(THIS_MODULE, "dahdi");
CLASS_DEV_CREATE(dahdi_class, MKDEV(DAHDI_MAJOR, 253), NULL, "dahdi!timer");
CLASS_DEV_CREATE(dahdi_class, MKDEV(DAHDI_MAJOR, 254), NULL, "dahdi!channel");
@@ -7919,6 +7946,7 @@
if (tone_zones[x])
kfree(tone_zones[x]);
}
+ dahdi_driver_exit();
#ifdef CONFIG_DAHDI_WATCHDOG
watchdog_cleanup();
Added: linux/team/tzafrir/sysfs/drivers/dahdi/dahdi-sysfs.c
URL: http://svn.digium.com/view/dahdi/linux/team/tzafrir/sysfs/drivers/dahdi/dahdi-sysfs.c?view=auto&rev=5443
==============================================================================
--- linux/team/tzafrir/sysfs/drivers/dahdi/dahdi-sysfs.c (added)
+++ linux/team/tzafrir/sysfs/drivers/dahdi/dahdi-sysfs.c Fri Dec 5 11:19:38 2008
@@ -1,0 +1,782 @@
+/*
+ * Written by Oron Peled <oron at actcom.co.il>
+ * Copyright (C) 2004-2006, Xorcom
+ *
+ * All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/version.h>
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
+# warning "This module is tested only with 2.6 kernels"
+#endif
+
+#define dev_to_span(dev) container_of(dev, struct dahdi_span, span_device)
+#define dev_to_chan(dev) container_of(dev, struct dahdi_chan, chan_device)
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/proc_fs.h>
+#include <linux/workqueue.h>
+//#include <linux/device.h>
+#include <linux/delay.h> /* for msleep() to debug */
+#include <dahdi/kernel.h>
+
+/*
+ * Hotplug replaced with uevent in 2.6.16
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,16)
+#define OLD_HOTPLUG_SUPPORT // for older kernels
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
+#define DEVICE_ATTR_READER(name,dev,buf) \
+ ssize_t name(struct device *dev, struct device_attribute *attr, char *buf)
+#define DEVICE_ATTR_WRITER(name,dev,buf, count) \
+ ssize_t name(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
+#else
+#define DEVICE_ATTR_READER(name,dev,buf) \
+ ssize_t name(struct device *dev, char *buf)
+#define DEVICE_ATTR_WRITER(name,dev,buf, count) \
+ ssize_t name(struct device *dev, const char *buf, size_t count)
+#endif
+
+static const char rcsid[] = "$Id$";
+
+/* Command line parameters */
+extern int debug;
+#ifndef BIT /* added in 2.6.24 */
+#define BIT(i) (1UL << (i))
+#endif
+#define DBG_GENERAL BIT(0)
+#define DBG_DEVICES BIT(7) /* instantiation/destruction etc. */
+#define PRINTK(level, category, fmt, ...) \
+ printk(KERN_ ## level "%s%s-%s: " fmt, #level, category, THIS_MODULE->name, ## __VA_ARGS__)
+#define SPAN_PRINTK(level, category, span, fmt, ...) \
+ printk(KERN_ ## level "%s%s-%s: %d: " fmt, #level, \
+ category, THIS_MODULE->name, (span)->spanno, ## __VA_ARGS__)
+#define CHAN_PRINTK(level, category, chan, fmt, ...) \
+ printk(KERN_ ## level "%s%s-%s: %d: " fmt, #level, \
+ category, THIS_MODULE->name, (chan)->channo, ## __VA_ARGS__)
+#define DBG(bits, fmt, ...) \
+ ((void)((debug & (DBG_ ## bits)) && PRINTK(DEBUG, "-" #bits, "%s: " fmt, __func__, ## __VA_ARGS__)))
+#define ERR(fmt, ...) PRINTK(ERR, "", fmt, ## __VA_ARGS__)
+#define SPAN_DBG(bits, span, fmt, ...) \
+ ((void)((debug & (DBG_ ## bits)) && SPAN_PRINTK(DEBUG, "-" #bits, span, "%s: " fmt, __func__, ## __VA_ARGS__)))
+#define SPAN_INFO(span, fmt, ...) SPAN_PRINTK(INFO, "", span, fmt, ## __VA_ARGS__)
+#define SPAN_ERR(span, fmt, ...) SPAN_PRINTK(ERR, "", span, fmt, ## __VA_ARGS__)
+#define CHAN_DBG(bits, chan, fmt, ...) \
+ ((void)((debug & (DBG_ ## bits)) && CHAN_PRINTK(DEBUG, "-" #bits, chan, "%s: " fmt, __func__, ## __VA_ARGS__)))
+#define CHAN_ERR(chan, fmt, ...) CHAN_PRINTK(ERR, "", chan, fmt, ## __VA_ARGS__)
+
+/*--------- Sysfs Bus handling ----*/
+#if 0
+static DEVICE_ATTR_READER(span_state_show, dev, buf)
+{
+ struct dahdi_span *span;
+ int res;
+
+ span = dev_to_span(dev);
+ res = XBUS_STATE(span);
+ res = snprintf(buf, PAGE_SIZE, "%s (%d)\n",
+ xbus_statename(res), res);
+ return res;
+}
+
+static DEVICE_ATTR_WRITER(xbus_state_store, dev, buf, count)
+{
+ xbus_t *xbus;
+
+ xbus = dev_to_xbus(dev);
+ XBUS_DBG(GENERAL, xbus, "%s\n", buf);
+ if(strncmp(buf, "stop", 4) == 0)
+ xbus_deactivate(xbus, 0);
+ else if(XBUS_IS(xbus, IDLE) && strncmp(buf, "start", 5) == 0)
+ xbus_activate(xbus);
+ else {
+ XBUS_NOTICE(xbus, "%s: Illegal action %s in state %s. Ignored.\n",
+ __func__, buf,
+ xbus_statename(XBUS_STATE(xbus)));
+ return -EINVAL;
+ }
+ return count;
+}
+
+static DEVICE_ATTR_READER(status_show, dev, buf)
+{
+ xbus_t *xbus;
+ int res;
+
+ xbus = dev_to_xbus(dev);
+ res = snprintf(buf, PAGE_SIZE, "%s\n", (!XBUS_IS(xbus, DISCONNECTED))?"connected":"missing");
+ return res;
+}
+
+static DEVICE_ATTR_READER(timing_show, dev, buf)
+{
+ xbus_t *xbus;
+ struct xpp_drift *driftinfo;
+ int len = 0;
+ struct timeval now;
+
+ do_gettimeofday(&now);
+ xbus = dev_to_xbus(dev);
+ driftinfo = &xbus->drift;
+ len += snprintf(buf + len, PAGE_SIZE - len, "DRIFT: %-3s", sync_mode_name(xbus->sync_mode));
+ if(xbus->sync_mode == SYNC_MODE_PLL) {
+ len += snprintf(buf + len, PAGE_SIZE - len,
+ " %5d: jitter %4d median %4d calc_drift %3d lost (%4d,%4d) : ",
+ xbus->ticker.cycle,
+ driftinfo->jitter, driftinfo->median,
+ driftinfo->calc_drift,
+ driftinfo->lost_ticks, driftinfo->lost_tick_count);
+ len += snprintf(buf + len, PAGE_SIZE - len,
+ "DRIFT %3d %ld sec ago",
+ xbus->sync_adjustment,
+ (xbus->pll_updated_at == 0) ? 0 : now.tv_sec - xbus->pll_updated_at);
+ }
+ len += snprintf(buf + len, PAGE_SIZE - len, "\n");
+ return len;
+}
+
+#ifdef SAMPLE_TICKS
+/*
+ * tick sampling: Measure offset from reference ticker:
+ * - Recording start when writing to:
+ * /sys/bus/astribanks/devices/xbus-??/samples
+ * - Recording ends when filling SAMPLE_SIZE ticks
+ * - Results are read from the same sysfs file.
+ * - Trying to read/write during recording, returns -EBUSY.
+ */
+static DEVICE_ATTR_READER(samples_show, dev, buf)
+{
+ xbus_t *xbus;
+ int len = 0;
+ int i;
+
+ xbus = dev_to_xbus(dev);
+ if(xbus->sample_running)
+ return -EBUSY;
+ for(i = 0; i < SAMPLE_SIZE; i++) {
+ if(len > PAGE_SIZE - 20)
+ break;
+ len += snprintf(buf + len, PAGE_SIZE - len, "%d\n", xbus->sample_ticks[i]);
+ }
+ return len;
+}
+
+static DEVICE_ATTR_WRITER(samples_store, dev, buf, count)
+{
+ xbus_t *xbus;
+
+ xbus = dev_to_xbus(dev);
+ if(xbus->sample_running)
+ return -EBUSY;
+ memset(xbus->sample_ticks, 0, sizeof(*xbus->sample_ticks));
+ xbus->sample_pos = 0;
+ xbus->sample_running = 1;
+ return count;
+}
+#endif
+
+/*
+ * Clear statistics
+ */
+static DEVICE_ATTR_WRITER(cls_store, dev, buf, count)
+{
+ xbus_t *xbus;
+ struct xpp_drift *driftinfo;
+
+ xbus = dev_to_xbus(dev);
+ driftinfo = &xbus->drift;
+ driftinfo->lost_ticks = 0;
+ driftinfo->lost_tick_count = 0;
+ xbus->min_tx_sync = INT_MAX;
+ xbus->max_tx_sync = 0;
+ xbus->min_rx_sync = INT_MAX;
+ xbus->max_rx_sync = 0;
+#ifdef SAMPLE_TICKS
+ memset(xbus->sample_ticks, 0, sizeof(*xbus->sample_ticks));
+#endif
+ return count;
+}
+
+static DEVICE_ATTR_READER(waitfor_xpds_show, dev, buf)
+{
+ xbus_t *xbus;
+ int len;
+
+ xbus = dev_to_xbus(dev);
+ len = waitfor_xpds(xbus, buf);
+ return len;
+}
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
+#define xbus_attr(field, format_string) \
+static ssize_t \
+field##_show(struct device *dev, struct device_attribute *attr, char *buf) \
+{ \
+ struct dahdi_span *span; \
+ \
+ span = dev_to_span(dev); \
+ return sprintf (buf, format_string, span->field); \
+}
+#else
+#define xbus_attr(field, format_string) \
+static ssize_t \
+field##_show(struct device *dev, char *buf) \
+{ \
+ struct dahdi_span *span; \
+ \
+ span = dev_to_span(dev); \
+ return sprintf (buf, format_string, span->field); \
+}
+#endif
+
+xbus_attr(name, "%s\n");
+xbus_attr(desc, "%s\n");
+xbus_attr(spantype, "%s\n");
+xbus_attr(manufacturer, "%s\n");
+xbus_attr(devicetype, "%s\n");
+xbus_attr(location, "%s\n");
+
+static struct device_attribute span_dev_attrs[] = {
+ __ATTR_RO(name),
+ __ATTR_RO(desc),
+ __ATTR_RO(spantype),
+ __ATTR_RO(manufacturer),
+ __ATTR_RO(devicetype),
+ __ATTR_RO(location),
+#if 0
+ __ATTR(cls, S_IWUSR, NULL, cls_store),
+ __ATTR(xbus_state, S_IRUGO | S_IWUSR, xbus_state_show, xbus_state_store),
+#ifdef SAMPLE_TICKS
+ __ATTR(samples, S_IWUSR | S_IRUGO, samples_show, samples_store),
+#endif
+#endif
+ __ATTR_NULL,
+};
+
+
+/* We have just one handler, and thus we match all spans that register
+ * to our bus */
+static int span_match(struct device *dev, struct device_driver *driver)
+{
+ DBG(DEVICES, "SYSFS MATCH: dev->bus_id = %s, driver->name = %s\n",
+ dev->bus_id, driver->name);
+ return 1;
+}
+
+#ifdef OLD_HOTPLUG_SUPPORT
+static int span_hotplug(struct device *dev, char **envp, int envnum, char *buff, int bufsize)
+{
+ struct dahdi_span *span;
+
+ if(!dev)
+ return -ENODEV;
+ span = dev_to_span(dev);
+ envp[0] = buff;
+ //if(snprintf(buff, bufsize, "SPAN_NAME=%s", span->name) >= bufsize)
+ // return -ENOMEM;
+ envp[1] = NULL;
+ return 0;
+}
+#else
+
+#define XBUS_VAR_BLOCK \
+ do { \
+ XBUS_ADD_UEVENT_VAR("XPP_INIT_DIR=%s", initdir); \
+ XBUS_ADD_UEVENT_VAR("XBUS_NUM=%02d", xbus->num); \
+ XBUS_ADD_UEVENT_VAR("XBUS_NAME=%s", xbus->busname); \
+ } while(0)
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,24)
+#define XBUS_ADD_UEVENT_VAR(fmt, val...) \
+ do { \
+ int err = add_uevent_var(envp, num_envp, &i, \
+ buffer, buffer_size, &len, \
+ fmt, val); \
+ if (err) \
+ return err; \
+ } while (0)
+
+static int span_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size)
+{
+ struct dahdi_span *span;
+ int i = 0;
+ //int len = 0;
+ //extern char *initdir;
+
+ if(!dev)
+ return -ENODEV;
+ span = dev_to_span(dev);
+ DBG(GENERAL, "SYFS bus_id=%s span=%s\n", dev->bus_id, span->name);
+ //XBUS_VAR_BLOCK;
+ envp[i] = NULL;
+ return 0;
+}
+
+#else
+#define XBUS_ADD_UEVENT_VAR(fmt, val...) \
+ do { \
+ int err = add_uevent_var(kenv, fmt, val); \
+ if (err) \
+ return err; \
+ } while (0)
+
+static int span_uevent(struct device *dev, struct kobj_uevent_env *kenv)
+{
+ struct dahdi_span *span;
+ //extern char *initdir;
+
+ if(!dev)
+ return -ENODEV;
+ span = dev_to_span(dev);
+ DBG(GENERAL, "SYFS bus_id=%s span=%s\n", dev->bus_id, span->name);
+ //XBUS_VAR_BLOCK;
+ return 0;
+}
+
+#endif
+
+#endif /* OLD_HOTPLUG_SUPPORT */
+
+#if 0
+void span_uevent_send(xbus_t *xbus, enum kobject_action act)
+{
+ struct kobject *kobj;
+
+ kobj = &xbus->astribank.kobj;
+ XBUS_DBG(DEVICES, xbus, "SYFS bus_id=%s action=%d\n",
+ xbus->astribank.bus_id, act);
+
+#ifdef OLD_HOTPLUG_SUPPORT
+ {
+ /* Copy from new kernels lib/kobject_uevent.c */
+ static const char *str[] = {
+ [KOBJ_ADD] "add",
+ [KOBJ_REMOVE] "remove",
+ [KOBJ_CHANGE] "change",
+ [KOBJ_MOUNT] "mount",
+ [KOBJ_UMOUNT] "umount",
+ [KOBJ_OFFLINE] "offline",
+ [KOBJ_ONLINE] "online"
+ };
+ kobject_hotplug(str[act], kobj);
+ }
+#else
+ kobject_uevent(kobj, act);
+#endif
+}
+
+#endif
+static void dahdi_release(struct device *dev)
+{
+ DBG(DEVICES, "SYSFS %s\n", dev->bus_id);
+}
+
+static void span_release(struct device *dev)
+{
+ //struct dahdi_span *span;
+
+ //BUG_ON(!dev);
+ //span = dev_to_xbus(dev);
+ //if(!XBUS_IS(xbus, DISCONNECTED)) {
+ // XBUS_ERR(xbus, "Try to release in state %s\n",
+ // xbus_statename(XBUS_STATE(xbus)));
+ // BUG();
+ //}
+ //XBUS_INFO(xbus, "[%s] Astribank Release\n", xbus->label);
+ //xbus_free(xbus);
+}
+
+static struct bus_type toplevel_bus_type = {
+ .name = "spans",
+ .match = span_match,
+#ifdef OLD_HOTPLUG_SUPPORT
+ .hotplug = span_hotplug,
+#else
+ .uevent = span_uevent,
+#endif
+ .dev_attrs = span_dev_attrs,
+};
+
+static struct device toplevel_device = {
+ .bus_id = "dahdi",
+ .release = dahdi_release
+};
+
+static int span_probe(struct device *dev)
+{
+ struct dahdi_span *span;
+
+ span = dev_to_span(dev);
+ SPAN_DBG(DEVICES, span, "SYSFS\n");
+ return 0;
+}
+
+static int span_remove(struct device *dev)
+{
+ struct dahdi_span *span;
+
+ span = dev_to_span(dev);
+ SPAN_INFO(span, "[%s] Atribank Remove\n", span->name);
+ return 0;
+}
+
+static struct device_driver span_driver = {
+ .name = "spandrv",
+ .bus = &toplevel_bus_type,
+ .probe = span_probe,
+ .remove = span_remove,
+#ifndef OLD_HOTPLUG_SUPPORT
+ .owner = THIS_MODULE
+#endif
+};
+
+/*--------- Sysfs channel handling ----*/
+#if 0
+static DEVICE_ATTR_READER(chipregs_show, dev, buf)
+{
+ xpd_t *xpd;
+ unsigned long flags;
+ reg_cmd_t *regs;
+ bool do_datah;
+ char datah_str[50];
+ int len = 0;
+
+ BUG_ON(!dev);
+ xpd = dev_to_xpd(dev);
+ if(!xpd)
+ return -ENODEV;
+ spin_lock_irqsave(&xpd->lock, flags);
+ regs = &xpd->last_reply;
+ len += sprintf(buf + len, "# Writing bad data into this file may damage your hardware!\n");
+ len += sprintf(buf + len, "# Consult firmware docs first\n");
+ len += sprintf(buf + len, "#\n");
+ do_datah = REG_FIELD(regs, do_datah) ? 1 : 0;
+ if(do_datah) {
+ snprintf(datah_str, ARRAY_SIZE(datah_str), "\t%02X",
+ REG_FIELD(regs, data_high));
+ } else
+ datah_str[0] = '\0';
+ if(REG_FIELD(regs, do_subreg)) {
+ len += sprintf(buf + len, "#CH\tOP\tReg.\tSub\tDL%s\n",
+ (do_datah) ? "\tDH" : "");
+ len += sprintf(buf + len, "%2d\tRS\t%02X\t%02X\t%02X%s\n",
+ regs->portnum,
+ REG_FIELD(regs, regnum), REG_FIELD(regs, subreg),
+ REG_FIELD(regs, data_low), datah_str);
+ } else {
+ len += sprintf(buf + len, "#CH\tOP\tReg.\tDL%s\n",
+ (do_datah) ? "\tDH" : "");
+ len += sprintf(buf + len, "%2d\tRD\t%02X\t%02X%s\n",
+ regs->portnum,
+ REG_FIELD(regs, regnum),
+ REG_FIELD(regs, data_low), datah_str);
+ }
+ spin_unlock_irqrestore(&xpd->lock, flags);
+ return len;
+}
+
+static DEVICE_ATTR_WRITER(chipregs_store, dev, buf, count)
+{
+ xpd_t *xpd;
+ const char *p;
+ char tmp[MAX_PROC_WRITE];
+ int i;
+ int res;
+
+ BUG_ON(!dev);
+ xpd = dev_to_xpd(dev);
+ //XPD_DBG(GENERAL, xpd, "%s\n", buf);
+ if(!xpd)
+ return -ENODEV;
+ p = buf;
+ while((p - buf) < count) {
+ i = strcspn(p, "\r\n");
+ if(i > 0) {
+ if(i >= MAX_PROC_WRITE) {
+ XPD_NOTICE(xpd, "Command too long (%d chars)\n", i);
+ return -E2BIG;
+ }
+ memcpy(tmp, p, i);
+ tmp[i] = '\0';
+ res = parse_chip_command(xpd, tmp);
+ if(res < 0) {
+ XPD_NOTICE(xpd, "Failed writing command: '%s'\n", tmp);
+ return res;
+ }
+ }
+ p += i + 1;
+ }
+ return count;
+}
+
+static DEVICE_ATTR_READER(blink_show, dev, buf)
+{
+ xpd_t *xpd;
+ unsigned long flags;
+ int len = 0;
+
+ BUG_ON(!dev);
+ xpd = dev_to_xpd(dev);
+ if(!xpd)
+ return -ENODEV;
+ spin_lock_irqsave(&xpd->lock, flags);
+ len += sprintf(buf, "0x%lX\n", xpd->blink_mode);
+ spin_unlock_irqrestore(&xpd->lock, flags);
+ return len;
+}
+
+static DEVICE_ATTR_WRITER(blink_store, dev, buf, count)
+{
+ xpd_t *xpd;
+ char *endp;
+ unsigned long blink;
+
+ BUG_ON(!dev);
+ xpd = dev_to_xpd(dev);
+ //XPD_DBG(GENERAL, xpd, "%s\n", buf);
+ if(!xpd)
+ return -ENODEV;
+ blink = simple_strtoul(buf, &endp, 0);
+ if(*endp != '\0' && *endp != '\n' && *endp != '\r')
+ return -EINVAL;
+ if(blink > 0xFFFF)
+ return -EINVAL;
+ XPD_DBG(GENERAL, xpd, "BLINK channels: 0x%lX\n", blink);
+ xpd->blink_mode = blink;
+ return count;
+}
+
+static DEVICE_ATTR_READER(span_show, dev, buf)
+{
+ xpd_t *xpd;
+ unsigned long flags;
+ int len = 0;
+
+ BUG_ON(!dev);
+ xpd = dev_to_xpd(dev);
+ if(!xpd)
+ return -ENODEV;
+ spin_lock_irqsave(&xpd->lock, flags);
+ len += sprintf(buf, "%d\n", SPAN_REGISTERED(xpd) ? xpd->span.spanno : 0);
+ spin_unlock_irqrestore(&xpd->lock, flags);
+ return len;
+}
+
+static DEVICE_ATTR_WRITER(span_store, dev, buf, count)
+{
+ xpd_t *xpd;
+ int dahdi_reg;
+ int res;
+
+ BUG_ON(!dev);
+ xpd = dev_to_xpd(dev);
+ if(!xpd)
+ return -ENODEV;
+ res = sscanf(buf, "%d", &dahdi_reg);
+ if(res != 1)
+ return -EINVAL;
+ if(!XBUS_IS(xpd->xbus, READY))
+ return -ENODEV;
+ XPD_DBG(GENERAL, xpd, "%s\n", (dahdi_reg) ? "register" : "unregister");
+ if(dahdi_reg)
+ res = dahdi_register_xpd(xpd);
+ else
+ res = dahdi_unregister_xpd(xpd);
+ return (res < 0) ? res : count;
+}
+#endif
+
+static int chan_match(struct device *dev, struct device_driver *driver)
+{
+ return 1;
+}
+
+static struct device_attribute chan_dev_attrs[] = {
+#if 0
+ __ATTR(chipregs, S_IRUGO | S_IWUSR, chipregs_show, chipregs_store),
+ __ATTR(blink, S_IRUGO | S_IWUSR, blink_show, blink_store),
+ __ATTR(span, S_IRUGO | S_IWUSR, span_show, span_store),
+#endif
+ __ATTR_NULL,
+};
+
+static struct bus_type dahdi_chan_type = {
+ .name = "dahdi_chans",
+ .match = chan_match,
+ .dev_attrs = chan_dev_attrs,
+};
+
+static void chan_release(struct device *dev)
+{
+ struct dahdi_chan *chan;
+
+ BUG_ON(!dev);
+ chan = dev_to_chan(dev);
+ CHAN_DBG(DEVICES, chan, "SYSFS\n");
+ //chan_remove(chan);
+}
+
+static int chan_device_register(struct dahdi_chan *chan)
+{
+ struct device *dev = &chan->chan_device;
+ struct dahdi_span *span;
+ int res;
+
+ BUG_ON(!chan);
+ span = chan->span;
+ BUG_ON(!span);
+ CHAN_DBG(DEVICES, chan, "SYSFS\n");
+ dev = &chan->chan_device;
+ dev->bus = &dahdi_chan_type;
+ dev->parent = &span->span_device;
+ snprintf(dev->bus_id, BUS_ID_SIZE, "%03d:%02d",
+ span->spanno, chan->channo);
+ dev->driver_data = chan;
+ dev->release = chan_release;
+ res = device_register(dev);
+ if(res) {
+ CHAN_ERR(chan, "%s: device_register failed: %d\n", __func__, res);
+ return res;
+ }
+ // FIXME: reference counting.
+ //get_xpd(__func__, xpd);
+ return 0;
+}
+
+static void chan_device_unregister(struct dahdi_chan *chan)
+{
+ struct device *dev = &chan->chan_device;
+
+ CHAN_DBG(DEVICES, chan, "SYSFS\n");
+ dev = &chan->chan_device;
+ if(!dev->driver_data)
+ return;
+ BUG_ON(dev->driver_data != chan);
+ device_unregister(dev);
+ dev->driver_data = NULL;
+}
+
+/*--------- Sysfs Device handling ----*/
+
+void span_sysfs_remove(struct dahdi_span *span)
+{
+ struct device *span_device;
+ int x;
+
+ BUG_ON(!span);
+ SPAN_DBG(DEVICES, span, "\n");
+ for (x = 0; x < span->channels; x++) {
+ struct dahdi_chan *chan = span->chans[x];
+ chan_device_unregister(chan);
+ }
+ span_device = &span->span_device;
+ BUG_ON(!span_device);
+ if(!span_device->driver_data)
+ return;
+ BUG_ON(span_device->driver_data != span);
+ device_unregister(&span->span_device);
+}
+EXPORT_SYMBOL(span_sysfs_remove);
+
+int span_sysfs_create(struct dahdi_span *span)
+{
+ struct device *span_device;
+ int res = 0;
+ int x;
+
+ BUG_ON(!span);
+ span_device = &span->span_device;
+ BUG_ON(!span_device);
+ SPAN_DBG(DEVICES, span, "\n");
+ span_device->bus = &toplevel_bus_type;
+ span_device->parent = &toplevel_device;
+ snprintf(span_device->bus_id, BUS_ID_SIZE, "span-%03d", span->spanno);
+ span_device->driver_data = span;
+ span_device->release = span_release;
+ res = device_register(span_device);
+ if(res) {
+ SPAN_ERR(span, "%s: device_register failed: %d\n", __func__, res);
+ span_device->driver_data = NULL;
+ return res;
+ }
+
+ for (x = 0; x < span->channels; x++) {
+ struct dahdi_chan *chan = span->chans[x];
+ res = chan_device_register(chan);
+ if (res) {
+ CHAN_ERR(chan, "Failed registering in sysfs: %d.\n",
+ res);
+ CHAN_ERR(chan, "And nobody wrote error handling yet.\n");
+ return res;
+ }
+ }
+ return res;
+}
+EXPORT_SYMBOL(span_sysfs_create);
+
+int __init dahdi_driver_init(void)
+{
+ int res;
+
+ DBG(DEVICES, "SYSFS\n");
+ if((res = bus_register(&toplevel_bus_type)) < 0) {
+ ERR("%s: bus_register(%s) failed. Error number %d",
+ __func__, toplevel_bus_type.name, res);
+ goto failed_bus;
+ }
+ if((res = device_register(&toplevel_device)) < 0) {
+ ERR("%s: device_register(%s) failed. Error number %d",
+ __func__, toplevel_device.bus_id, res);
+ goto failed_busdevice;
+ }
+ if((res = driver_register(&span_driver)) < 0) {
+ ERR("%s: driver_register(%s) failed. Error number %d",
+ __func__, span_driver.name, res);
+ goto failed_span_driver;
+ }
+ if((res = bus_register(&dahdi_chan_type)) < 0) {
+ ERR("%s: bus_register(%s) failed. Error number %d",
+ __func__, dahdi_chan_type.name, res);
+ goto failed_chan_bus;
+ }
+ return 0;
+failed_chan_bus:
+ driver_unregister(&span_driver);
+failed_span_driver:
+ device_unregister(&toplevel_device);
+failed_busdevice:
+ bus_unregister(&toplevel_bus_type);
+failed_bus:
+ return res;
+}
+//EXPORT_SYMBOL(dahdi_driver_init);
+
+void dahdi_driver_exit(void)
+{
+ DBG(DEVICES, "SYSFS\n");
+ bus_unregister(&dahdi_chan_type);
+ driver_unregister(&span_driver);
+ device_unregister(&toplevel_device);
+ bus_unregister(&toplevel_bus_type);
+}
+EXPORT_SYMBOL(dahdi_driver_exit);
Propchange: linux/team/tzafrir/sysfs/drivers/dahdi/dahdi-sysfs.c
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: linux/team/tzafrir/sysfs/drivers/dahdi/dahdi-sysfs.c
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: linux/team/tzafrir/sysfs/drivers/dahdi/dahdi-sysfs.c
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: linux/team/tzafrir/sysfs/drivers/dahdi/dahdi-sysfs.h
URL: http://svn.digium.com/view/dahdi/linux/team/tzafrir/sysfs/drivers/dahdi/dahdi-sysfs.h?view=auto&rev=5443
==============================================================================
--- linux/team/tzafrir/sysfs/drivers/dahdi/dahdi-sysfs.h (added)
+++ linux/team/tzafrir/sysfs/drivers/dahdi/dahdi-sysfs.h Fri Dec 5 11:19:38 2008
@@ -1,0 +1,7 @@
+/* Global */
+int __init dahdi_driver_init(void);
+void dahdi_driver_exit(void);
+
+/* per-span */
+int span_sysfs_create(struct dahdi_span *span);
+void span_sysfs_remove(struct dahdi_span *span);
Propchange: linux/team/tzafrir/sysfs/drivers/dahdi/dahdi-sysfs.h
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: linux/team/tzafrir/sysfs/drivers/dahdi/dahdi-sysfs.h
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: linux/team/tzafrir/sysfs/drivers/dahdi/dahdi-sysfs.h
------------------------------------------------------------------------------
svn:mime-type = text/plain
Modified: linux/team/tzafrir/sysfs/include/dahdi/kernel.h
URL: http://svn.digium.com/view/dahdi/linux/team/tzafrir/sysfs/include/dahdi/kernel.h?view=diff&rev=5443&r1=5442&r2=5443
==============================================================================
--- linux/team/tzafrir/sysfs/include/dahdi/kernel.h (original)
+++ linux/team/tzafrir/sysfs/include/dahdi/kernel.h Fri Dec 5 11:19:38 2008
@@ -53,6 +53,7 @@
#include <linux/skbuff.h>
#include <linux/interrupt.h>
#endif
+#include <linux/device.h>
#include <linux/poll.h>
@@ -333,6 +334,7 @@
#else
unsigned char *lin2x;
#endif
+ struct device chan_device; /*!< Kernel object for this span (TODO: rename) */
};
#ifdef CONFIG_DAHDI_NET
@@ -603,6 +605,7 @@
void (*hdlc_hard_xmit)(struct dahdi_chan *chan);
/* Used by DAHDI only -- no user servicable parts inside */
+ struct device span_device; /*!< Kernel object for this span (TODO: rename) */
int spanno; /*!< Span number for DAHDI */
int offset; /*!< Offset within a given card */
int lastalarms; /*!< Previous alarms */
More information about the svn-commits
mailing list