[dahdi-commits] tzafrir: branch linux/tzafrir/sysfs r5443 - in /linux/team/tzafrir/sysfs: dri...

SVN commits to the DAHDI project dahdi-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 dahdi-commits mailing list