[ patch 4/7] drivers/serial/jsm: new serial device driver

From: Wen Xiong
Date: Sun Feb 27 2005 - 18:59:39 EST


This patch is for jsm_proc.c and includes the functions relating to /proc/jsm entry.

Signed-off-by: Wen Xiong <wendyx@xxxxxxxxxxxxxxxxxxxxxxx>

diff -Nuar linux-2.6.9.orig/drivers/serial/jsm/jsm_proc.c linux-2.6.9.new/drivers/serial/jsm/jsm_proc.c
--- linux-2.6.9.orig/drivers/serial/jsm/jsm_proc.c 1969-12-31 18:00:00.000000000 -0600
+++ linux-2.6.9.new/drivers/serial/jsm/jsm_proc.c 2005-02-27 17:13:14.339983544 -0600
@@ -0,0 +1,951 @@
+/*
+ * Copyright 2003 Digi International (www.digi.com)
+ * Scott H Kilau <Scott_Kilau at digi dot com>
+ *
+ * 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; 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.
+ *
+ *
+ * NOTE TO LINUX KERNEL HACKERS: DO NOT REFORMAT THIS CODE!
+ *
+ * This is shared code between Digi's CVS archive and the
+ * Linux Kernel sources.
+ * Changing the source just for reformatting needlessly breaks
+ * our CVS diff history.
+ *
+ * Send any bug fixes/changes to: Eng.Linux at digi dot com.
+ * Thank you.
+ *
+ *
+ * $Id: jsm_proc.c,v 1.38 2004/08/30 21:39:40 scottk Exp $
+ */
+#include <linux/kernel.h>
+#include <linux/version.h>
+#include <linux/sched.h> /* For jiffies, task states */
+#include <linux/interrupt.h> /* For tasklet and interrupt structs/defines */
+#include <linux/module.h>
+#include <linux/ctype.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/serial_reg.h>
+#include <linux/sched.h> /* For in_egroup_p() */
+#include <linux/string.h>
+#include <asm/uaccess.h> /* For copy_from_user/copy_to_user */
+
+#include "jsm_driver.h"
+#include "jsm_mgmt.h"
+
+/* The /proc/jsm directory */
+static struct proc_dir_entry *ProcJSM;
+
+static void *jsm_info_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ if (*pos > 0)
+ return NULL;
+ else
+ return (void *)1;
+}
+
+static void *jsm_info_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ ++*pos;
+ if (*pos > 0)
+ return NULL;
+ else
+ return (void *)1;
+}
+
+static void jsm_info_seq_stop(struct seq_file *seq, void *v)
+{
+
+}
+
+static int jsm_info_seq_show(struct seq_file *seq, void *v)
+{
+
+ seq_printf(seq, "Driver:\t\t%s\n", "jsm - 1.1-1-INKERNEL");
+ seq_printf(seq, "\n");
+ seq_printf(seq, "Debug:\t\t0x%x\n", jsm_debug);
+ seq_printf(seq, "Rawreadok:\t0x%x\n", jsm_rawreadok);
+ seq_printf(seq, "Max Boards:\t%d\n", MAXBOARDS);
+ seq_printf(seq, "Total Boards:\t%d\n", jsm_NumBoards);
+ seq_printf(seq, "Poll counter:\t%ld\n", jsm_poll_counter);
+ seq_printf(seq, "State:\t\t%s\n", jsm_driver_state_text[jsm_driver_state]);
+ return 0;
+
+}
+
+static struct seq_operations jsm_info_seq_ops = {
+ .start = jsm_info_seq_start,
+ .next = jsm_info_seq_next,
+ .stop = jsm_info_seq_stop,
+ .show = jsm_info_seq_show,
+};
+
+static int jsm_info_open(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq;
+ struct proc_dir_entry *proc;
+ int res;
+
+ res = seq_open(file, &jsm_info_seq_ops);
+ if (!res) {
+ /* recover the pointer buried in proc_dir_entry data */
+ seq = file->private_data;
+ proc = PDE(inode);
+ seq->private = proc->data;
+ }
+ return res;
+}
+
+
+static void *jsm_mknod_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ if (*pos > 0)
+ return NULL;
+ else
+ return (void *)1;
+}
+
+static void *jsm_mknod_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ ++*pos;
+ if (*pos > 0)
+ return NULL;
+ else
+ return (void *)1;
+}
+
+static void jsm_mknod_seq_stop(struct seq_file *seq, void *v)
+{
+
+}
+
+static int jsm_mknod_seq_show(struct seq_file *seq, void *v)
+{
+ int i;
+ seq_printf(seq, "#\tCreate the management devices.\n");
+
+ for (i = 0; i < MAXMGMTDEVICES; i++) {
+ char tmp[100];
+ sprintf(tmp, "/dev/jsm/mgmt%d", i);
+ seq_printf(seq, "%s\t%d\t%d\t%d\n",
+ tmp, jsm_Major, i, 1);
+ }
+ return 0;
+}
+
+static struct seq_operations jsm_mknod_seq_ops = {
+ .start = jsm_mknod_seq_start,
+ .next = jsm_mknod_seq_next,
+ .stop = jsm_mknod_seq_stop,
+ .show = jsm_mknod_seq_show,
+};
+
+static int jsm_mknod_open(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq;
+ struct proc_dir_entry *proc;
+ int res;
+
+ res = seq_open(file, &jsm_mknod_seq_ops);
+ if (!res) {
+ /* recover the pointer buried in proc_dir_entry data */
+ seq = file->private_data;
+ proc = PDE(inode);
+ seq->private = proc->data;
+ }
+ return res;
+}
+
+static void *jsm_board_info_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ if (*pos > 0)
+ return NULL;
+ else
+ return (void *)1;
+}
+
+static void *jsm_board_info_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ ++*pos;
+ if (*pos > 0)
+ return NULL;
+ else
+ return (void *)1;
+}
+
+static void jsm_board_info_seq_stop(struct seq_file *seq, void *v)
+{
+
+}
+
+static int jsm_board_info_seq_show(struct seq_file *seq, void *v)
+{
+ struct board_t *brd = (struct board_t *) seq->private;
+ char *name;
+
+ DPR_PROC(("jsm_proc_brd_info\n"));
+
+ if (!brd || (brd->magic != JSM_BOARD_MAGIC))
+ return 0;
+
+ name = brd->name;
+
+ seq_printf(seq, "Board Name = %s\n", name);
+ seq_printf(seq, "Board Type = %d\n", brd->type);
+ seq_printf(seq, "Number of Ports = %d\n", brd->nasync);
+
+ /*
+ * report some things about the PCI bus that are important
+ * to some applications
+ */
+ seq_printf(seq, "Vendor ID = 0x%x\n", brd->vendor);
+ seq_printf(seq, "Device ID = 0x%x\n", brd->device);
+ seq_printf(seq, "Subvendor ID = 0x%x\n", brd->subvendor);
+ seq_printf(seq, "Subdevice ID = 0x%x\n", brd->subdevice);
+ seq_printf(seq, "Bus = %d\n", brd->pci_bus);
+ seq_printf(seq, "Slot = %d\n", brd->pci_slot);
+
+ /*
+ * report the physical addresses assigned to us when we got
+ * registered
+ */
+ seq_printf(seq, "Memory Base Address = 0x%lx\n", brd->membase);
+ seq_printf(seq, "Remapped Memory Base Address = 0x%p\n", brd->re_map_membase);
+
+ seq_printf(seq, "Current state of board = %s\n", jsm_state_text[brd->state]);
+ seq_printf(seq, "Interrupt #: %d. Times interrupted: %ld\n",
+ brd->irq, brd->intr_count);
+ seq_printf(seq, "Majors allocated to board = TTY: %d PR: %d\n",
+ brd->SerialDriver.major, brd->PrintDriver.major);
+
+ return 0;
+}
+
+static struct seq_operations jsm_board_info_seq_ops = {
+ .start = jsm_board_info_seq_start,
+ .next = jsm_board_info_seq_next,
+ .stop = jsm_board_info_seq_stop,
+ .show = jsm_board_info_seq_show,
+};
+
+static int jsm_board_info_open(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq;
+ struct proc_dir_entry *proc;
+ int res;
+
+ res = seq_open(file, &jsm_board_info_seq_ops);
+ if (!res) {
+ /* recover the pointer buried in proc_dir_entry data */
+ seq = file->private_data;
+ proc = PDE(inode);
+ seq->private = proc->data;
+ }
+ return res;
+}
+
+
+static void *jsm_board_stats_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ if (*pos > 0)
+ return NULL;
+ else
+ return (void *)1;
+}
+
+static void *jsm_board_stats_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ ++*pos;
+ if (*pos > 0)
+ return NULL;
+ else
+ return (void *)1;
+}
+
+static void jsm_board_stats_seq_stop(struct seq_file *seq, void *v)
+{
+
+}
+
+static int jsm_board_stats_seq_show(struct seq_file *seq, void *v)
+{
+ struct board_t *brd = (struct board_t *) seq->private;
+ int i = 0;
+
+
+ if (!brd || (brd->magic != JSM_BOARD_MAGIC))
+ return 0;
+
+ /* Prepare the Header Labels */
+ seq_printf(seq, "%2s %10s %23s %10s %9s\n",
+ "Ch", "Chars Rx", " Rx Par--Brk--Frm--Ovr",
+ "Chars Tx", "XON XOFF");
+
+ for (i = 0; i < brd->nasync; i++) {
+
+ struct channel_t *ch = brd->channels[i];
+
+ seq_printf(seq, "%2d ", i);
+ seq_printf(seq, "%10ld ", ch->ch_rxcount);
+ seq_printf(seq, "%4ld %4ld %4ld %4ld ", ch->ch_err_parity,
+ ch->ch_err_break, ch->ch_err_frame, ch->ch_err_overrun);
+ seq_printf(seq, "%10ld ", ch->ch_txcount);
+ seq_printf(seq, "%4ld %4ld ", ch->ch_xon_sends, ch->ch_xoff_sends);
+
+ seq_printf(seq, "\n");
+ }
+
+ return 0;
+}
+
+static struct seq_operations jsm_board_stats_seq_ops = {
+ .start = jsm_board_stats_seq_start,
+ .next = jsm_board_stats_seq_next,
+ .stop = jsm_board_stats_seq_stop,
+ .show = jsm_board_stats_seq_show,
+};
+
+static int jsm_board_stats_open(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq;
+ struct proc_dir_entry *proc;
+ int res;
+
+ res = seq_open(file, &jsm_board_stats_seq_ops);
+ if (!res) {
+ /* recover the pointer buried in proc_dir_entry data */
+ seq = file->private_data;
+ proc = PDE(inode);
+ seq->private = proc->data;
+ }
+
+ return res;
+}
+
+
+static void *jsm_board_flags_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ if (*pos > 0)
+ return NULL;
+ else
+ return (void *)1;
+}
+
+static void *jsm_board_flags_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ ++*pos;
+ if (*pos > 0)
+ return NULL;
+ else
+ return (void *)1;
+}
+
+static void jsm_board_flags_seq_stop(struct seq_file *seq, void *v)
+{
+
+}
+
+static int jsm_board_flags_seq_show(struct seq_file *seq, void *v)
+{
+ struct board_t *brd = (struct board_t *) seq->private;
+ int i = 0;
+
+ DPR_PROC(("jsm_proc_brd_info\n"));
+
+ if (!brd || (brd->magic != JSM_BOARD_MAGIC))
+ return 0;
+
+ /* Prepare the Header Labels */
+ seq_printf(seq, "%2s %5s %5s %5s %5s %5s %10s Line Status Flags\n",
+ "Ch", "CFlag", "IFlag", "OFlag", "LFlag", "DFlag", "Baud");
+
+ for (i = 0; i < brd->nasync; i++) {
+
+ struct channel_t *ch = brd->channels[i];
+
+ seq_printf(seq, "%2d ", i);
+ seq_printf(seq, "%5x ", ch->ch_c_cflag);
+ seq_printf(seq, "%5x ", ch->ch_c_iflag);
+ seq_printf(seq, "%5x ", ch->ch_c_oflag);
+ seq_printf(seq, "%5x ", ch->ch_c_lflag);
+ seq_printf(seq, "%10d ", ch->ch_old_baud);
+
+ if (!ch->ch_open_count)
+ seq_printf(seq, " -- -- -- -- -- -- --") ;
+ else {
+ seq_printf(seq, " op %s %s %s %s %s %s",
+ (ch->ch_mostat & UART_MCR_RTS) ? "rs" : "--",
+ (ch->ch_mistat & UART_MSR_CTS) ? "cs" : "--",
+ (ch->ch_mostat & UART_MCR_DTR) ? "tr" : "--",
+ (ch->ch_mistat & UART_MSR_DSR) ? "mr" : "--",
+ (ch->ch_mistat & UART_MSR_DCD) ? "cd" : "--",
+ (ch->ch_mistat & UART_MSR_RI) ? "ri" : "--");
+ }
+
+ seq_printf(seq, "\n");
+ }
+
+ return 0;
+}
+
+static struct seq_operations jsm_board_flags_seq_ops = {
+ .start = jsm_board_flags_seq_start,
+ .next = jsm_board_flags_seq_next,
+ .stop = jsm_board_flags_seq_stop,
+ .show = jsm_board_flags_seq_show,
+};
+
+static int jsm_board_flags_open(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq;
+ struct proc_dir_entry *proc;
+ int res;
+
+ res = seq_open(file, &jsm_board_flags_seq_ops);
+ if (!res) {
+ /* recover the pointer buried in proc_dir_entry data */
+ seq = file->private_data;
+ proc = PDE(inode);
+ seq->private = proc->data;
+ }
+
+ return res;
+}
+
+
+
+static void *jsm_board_mknod_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ if (*pos > 0)
+ return NULL;
+ else
+ return (void *)1;
+}
+
+static void *jsm_board_mknod_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ ++*pos;
+ if (*pos > 0)
+ return NULL;
+ else
+ return (void *)1;
+}
+
+static void jsm_board_mknod_seq_stop(struct seq_file *seq, void *v)
+{
+
+}
+
+static int jsm_board_mknod_seq_show(struct seq_file *seq, void *v)
+{
+ struct board_t *brd = (struct board_t *) seq->private;
+ char str[MAXTTYNAMELEN];
+
+ DPR_PROC(("jsm_proc_brd_info\n"));
+
+ if (!brd || (brd->magic != JSM_BOARD_MAGIC))
+ return 0;
+
+ /*
+ * For each board, output the device information in
+ * a handy table format...
+ */
+ seq_printf(seq, "# Create the TTY and PR devices\n");
+
+ /* TTY devices */
+ sprintf(str, "ttyn%d%%p", brd->boardnum + 1);
+ seq_printf(seq, "%s\t\t\t%d\t%d\t%d\n", str,
+ brd->jsm_Serial_Major, 0, brd->maxports);
+
+ /* PR devices */
+ sprintf(str, "prn%d%%p", brd->boardnum + 1);
+ seq_printf(seq, "%s\t\t\t%d\t%d\t%d\n", str,
+ brd->jsm_TransparentPrint_Major, 128, brd->maxports);
+
+ return 0;
+}
+
+static struct seq_operations jsm_board_mknod_seq_ops = {
+ .start = jsm_board_mknod_seq_start,
+ .next = jsm_board_mknod_seq_next,
+ .stop = jsm_board_mknod_seq_stop,
+ .show = jsm_board_mknod_seq_show,
+};
+
+static int jsm_board_mknod_open(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq;
+ struct proc_dir_entry *proc;
+ int res;
+
+ res = seq_open(file, &jsm_board_mknod_seq_ops);
+ if (!res) {
+ /* recover the pointer buried in proc_dir_entry data */
+ seq = file->private_data;
+ proc = PDE(inode);
+ seq->private = proc->data;
+ }
+
+ return res;
+}
+
+
+static void *jsm_channel_info_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ if (*pos > 0)
+ return NULL;
+ else
+ return (void *)1;
+}
+
+static void *jsm_channel_info_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ ++*pos;
+ if (*pos > 0)
+ return NULL;
+ else
+ return (void *)1;
+}
+
+static void jsm_channel_info_seq_stop(struct seq_file *seq, void *v)
+{
+
+}
+
+static int jsm_channel_info_seq_show(struct seq_file *seq, void *v)
+{
+ struct channel_t *ch = (struct channel_t *) seq->private;
+
+ DPR_PROC(("jsm_proc_info\n"));
+
+ if (!ch || (ch->magic != JSM_CHANNEL_MAGIC))
+ return 0;
+
+ seq_printf(seq, "Port number:\t\t%d\n", ch->ch_portnum);
+ seq_printf(seq, "\n");
+
+ /* Prepare the Header Labels */
+ seq_printf(seq, "%10s %23s %10s %9s\n",
+ "Chars Rx", " Rx Par--Brk--Frm--Ovr",
+ "Chars Tx", "XON XOFF");
+ seq_printf(seq, "%10ld ", ch->ch_rxcount);
+ seq_printf(seq, "%4ld %4ld %4ld %4ld ", ch->ch_err_parity,
+ ch->ch_err_break, ch->ch_err_frame, ch->ch_err_overrun);
+ seq_printf(seq, "%10ld ", ch->ch_txcount);
+ seq_printf(seq, "%4ld %4ld ", ch->ch_xon_sends, ch->ch_xoff_sends);
+ seq_printf(seq, "\n\n");
+
+ /* Prepare the Header Labels */
+ seq_printf(seq, "%5s %5s %5s %5s %5s %10s Line Status Flags\n",
+ "CFlag", "IFlag", "OFlag", "LFlag", "DFlag", "Baud");
+
+ seq_printf(seq, "%5x ", ch->ch_c_cflag);
+ seq_printf(seq, "%5x ", ch->ch_c_iflag);
+ seq_printf(seq, "%5x ", ch->ch_c_oflag);
+ seq_printf(seq, "%5x ", ch->ch_c_lflag);
+ seq_printf(seq, "%10d ", ch->ch_old_baud);
+ if (!ch->ch_open_count)
+ seq_printf(seq, " -- -- -- -- -- -- --") ;
+ else {
+ seq_printf(seq, " op %s %s %s %s %s %s",
+ (ch->ch_mostat & UART_MCR_RTS) ? "rs" : "--",
+ (ch->ch_mistat & UART_MSR_CTS) ? "cs" : "--",
+ (ch->ch_mostat & UART_MCR_DTR) ? "tr" : "--",
+ (ch->ch_mistat & UART_MSR_DSR) ? "mr" : "--",
+ (ch->ch_mistat & UART_MSR_DCD) ? "cd" : "--",
+ (ch->ch_mistat & UART_MSR_RI) ? "ri" : "--");
+ }
+ seq_printf(seq, "\n\n");
+
+ return 0;
+}
+
+static struct seq_operations jsm_channel_info_seq_ops = {
+ .start = jsm_channel_info_seq_start,
+ .next = jsm_channel_info_seq_next,
+ .stop = jsm_channel_info_seq_stop,
+ .show = jsm_channel_info_seq_show,
+};
+
+static int jsm_channel_info_open(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq;
+ struct proc_dir_entry *proc;
+ int res;
+
+ res = seq_open(file, &jsm_channel_info_seq_ops);
+ if (!res) {
+ /* recover the pointer buried in proc_dir_entry data */
+ seq = file->private_data;
+ proc = PDE(inode);
+ seq->private = proc->data;
+ }
+
+ return res;
+}
+
+
+static void *jsm_channel_sniff_seq_start(struct seq_file *seq, loff_t *pos)
+{
+ ulong lock_flags;
+ struct channel_t *ch = (struct channel_t *) seq->private;
+
+ if (!ch || (ch->magic != JSM_CHANNEL_MAGIC))
+ return NULL;
+
+ ch->ch_sniff_buf = kmalloc(SNIFF_MAX, GFP_KERNEL);
+ memset(ch->ch_sniff_buf, 0, SNIFF_MAX);
+
+ spin_lock_irqsave(&ch->ch_lock, lock_flags);
+ ch->ch_sniff_flags |= SNIFF_OPEN;
+ spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+
+ return (void *)1;
+}
+
+static void *jsm_channel_sniff_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+ ++*pos;
+ if (*pos > 0)
+ return NULL;
+ else
+ return (void *)1;
+}
+
+static void jsm_channel_sniff_seq_stop(struct seq_file *seq, void *v)
+{
+ ulong lock_flags;
+ struct channel_t *ch = (struct channel_t *) seq->private;
+
+ spin_lock_irqsave(&ch->ch_lock, lock_flags);
+ ch->ch_sniff_flags &= ~(SNIFF_OPEN);
+ kfree(ch->ch_sniff_buf);
+ spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+}
+
+
+static int jsm_channel_sniff_seq_show(struct seq_file *seq, void *v)
+{
+
+ struct channel_t *ch = (struct channel_t *) seq->private;
+ int n;
+ int r;
+ int offset = 0;
+ int res = 0;
+ ssize_t rtn = 0;
+ ulong lock_flags;
+ int count;
+ if (!ch || (ch->magic != JSM_CHANNEL_MAGIC)) {
+ rtn = -ENXIO;
+ goto done;
+ }
+
+ /*
+ * Wait for some data to appear in the buffer.
+ */
+ spin_lock_irqsave(&ch->ch_lock, lock_flags);
+
+ for (;;) {
+ n = (ch->ch_sniff_in - ch->ch_sniff_out) & SNIFF_MASK;
+
+ if (n != 0)
+ break;
+
+ ch->ch_sniff_flags |= SNIFF_WAIT_DATA;
+
+ spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+
+ /*
+ * Go to sleep waiting until the condition becomes true.
+ */
+ rtn = wait_event_interruptible(ch->ch_sniff_wait,
+ ((ch->ch_sniff_flags & SNIFF_WAIT_DATA) == 0));
+
+ if (rtn)
+ goto done;
+
+ spin_lock_irqsave(&ch->ch_lock, lock_flags);
+ }
+
+ /*
+ * Read whatever is there.
+ */
+
+ res = n;
+
+ r = SNIFF_MAX - ch->ch_sniff_out;
+
+ if (r <= n) {
+ spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+ if (rtn) {
+ rtn = -EFAULT;
+ goto done;
+ }
+
+ spin_lock_irqsave(&ch->ch_lock, lock_flags);
+
+ ch->ch_sniff_out = 0;
+ n -= r;
+ offset = r;
+ }
+
+ spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+ seq_printf(seq, "in =%d out=%d\n",ch->ch_sniff_in,ch->ch_sniff_out);
+ seq_printf(seq, "first=%x\n",ch->ch_sniff_buf[5]);
+ seq_printf(seq, "first=%x\n",ch->ch_sniff_buf[6]);
+ for (count = 0; count < n; count++) {
+ seq_printf(seq, "%x ",ch->ch_sniff_buf[ch->ch_sniff_out++]);
+ }
+ if (rtn) {
+ rtn = -EFAULT;
+ goto done;
+ }
+ spin_lock_irqsave(&ch->ch_lock, lock_flags);
+
+ seq_printf(seq,"\n");
+ seq_printf(seq, "in =%d out=%d\n",ch->ch_sniff_in,ch->ch_sniff_out);
+
+ /*
+ * Wakeup any thread waiting for buffer space.
+ */
+
+ if (ch->ch_sniff_flags & SNIFF_WAIT_SPACE) {
+ ch->ch_sniff_flags &= ~SNIFF_WAIT_SPACE;
+ wake_up_interruptible(&ch->ch_sniff_wait);
+ }
+
+ spin_unlock_irqrestore(&ch->ch_lock, lock_flags);
+
+done:
+ return rtn;
+}
+
+static struct seq_operations jsm_channel_sniff_seq_ops = {
+ .start = jsm_channel_sniff_seq_start,
+ .next = jsm_channel_sniff_seq_next,
+ .stop = jsm_channel_sniff_seq_stop,
+ .show = jsm_channel_sniff_seq_show,
+};
+
+static int jsm_channel_sniff_open(struct inode *inode, struct file *file)
+{
+ struct seq_file *seq;
+ struct proc_dir_entry *proc;
+ int res;
+
+ res = seq_open(file, &jsm_channel_sniff_seq_ops);
+ if (!res) {
+ /* recover the pointer buried in proc_dir_entry data */
+ seq = file->private_data;
+ proc = PDE(inode);
+ seq->private = proc->data;
+ }
+
+ return res;
+}
+
+
+static struct file_operations jsm_info_operations = {
+ .open = jsm_info_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static struct file_operations jsm_mknod_operations = {
+ .open = jsm_mknod_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static struct file_operations jsm_board_info_operations = {
+ .open = jsm_board_info_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static struct file_operations jsm_board_stats_operations = {
+ .open = jsm_board_stats_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static struct file_operations jsm_board_flags_operations = {
+ .open = jsm_board_flags_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static struct file_operations jsm_board_mknod_operations = {
+ .open = jsm_board_mknod_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static struct file_operations jsm_channel_info_operations =
+{
+ .open = jsm_channel_info_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+static struct file_operations jsm_channel_sniff_operations =
+{
+ .open = jsm_channel_sniff_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
+};
+
+/*
+ * Register the basic /proc/jsm files that appear whenever
+ * the driver is loaded.
+ */
+void jsm_proc_register_basic_prescan(void)
+{
+ /*
+ *Register /proc/jsm
+ */
+
+ struct proc_dir_entry *entry;
+
+ ProcJSM = proc_mkdir("jsm",&proc_root);
+ if (ProcJSM)
+ ProcJSM->owner = THIS_MODULE;
+ else
+ printk(KERN_WARNING "cann't create /proc/net/jsm\n");
+
+ entry = create_proc_entry("info", S_IRUGO, ProcJSM);
+ if (entry)
+ entry->proc_fops = &jsm_info_operations;
+
+ entry = create_proc_entry("mknod", S_IRUGO, ProcJSM);
+ if (entry)
+ entry->proc_fops = &jsm_mknod_operations;
+}
+
+
+/*
+ * Register the basic /proc/jsm files that appear whenever
+ * the driver is loaded.
+ */
+int jsm_proc_register_basic_postscan(int board_num)
+{
+ int i;
+ char board[10];
+ struct proc_dir_entry *e, *board_e, *channel_e;
+ sprintf(board, "%d", board_num);
+
+ /* Set proc board entry pointer */
+ board_e = jsm_Board[board_num]->proc_entry_pointer = proc_mkdir(board, ProcJSM);
+
+ e = create_proc_entry("info", S_IRUGO, board_e);
+ if (!e)
+ return -ENOMEM;
+ e->proc_fops = &jsm_board_info_operations;
+ e->data = jsm_Board[board_num];
+
+
+ e = create_proc_entry("stats", S_IRUGO, board_e);
+ if (!e)
+ return -ENOMEM;
+ e->proc_fops = &jsm_board_stats_operations;
+ e->data = jsm_Board[board_num];
+
+ e = create_proc_entry("flags", S_IRUGO, board_e);
+ if (!e)
+ return -ENOMEM;
+ e->proc_fops = &jsm_board_flags_operations;
+ e->data = jsm_Board[board_num];
+
+ e = create_proc_entry("mknod", S_IRUGO, board_e);
+ if (!e)
+ return -ENOMEM;
+ e->proc_fops = &jsm_board_mknod_operations;
+ e->data = jsm_Board[board_num];
+
+ /*
+ * Add new entries for each port.
+ */
+ for (i = 0; i < jsm_Board[board_num]->nasync; i++) {
+
+ char channel[10];
+ sprintf(channel, "%d", i);
+
+ channel_e = jsm_Board[board_num]->channels[i]->proc_entry_pointer = proc_mkdir(channel,board_e);
+
+ e = create_proc_entry("info", S_IRUGO, channel_e);
+ if (!e)
+ return -ENOMEM;
+ e->proc_fops = &jsm_channel_info_operations;
+ e->data = jsm_Board[board_num]->channels[i];
+
+ e = create_proc_entry("sniff", S_IRUGO, channel_e);
+ if (!e)
+ return -ENOMEM;
+ e->proc_fops = &jsm_channel_sniff_operations;
+ e->data = jsm_Board[board_num]->channels[i];
+
+ }
+
+ return 0;
+}
+
+
+
+void jsm_proc_unregister_brd(int brd_number)
+{
+ int i = 0, j = 0;
+
+ i = brd_number;
+
+ char board_number[16];
+ sprintf(board_number,"%d",i);
+
+
+ for (j = 0; j < jsm_Board[i]->nasync; j++) {
+
+ char channel_number[16];
+ sprintf(channel_number,"%d",j);
+
+ remove_proc_entry("info",jsm_Board[i]->channels[j]->proc_entry_pointer);
+ remove_proc_entry("sniff",jsm_Board[i]->channels[j]->proc_entry_pointer);
+ remove_proc_entry(channel_number,jsm_Board[i]->proc_entry_pointer);
+
+ }
+
+ remove_proc_entry("info",jsm_Board[i]->proc_entry_pointer);
+ remove_proc_entry("mknod",jsm_Board[i]->proc_entry_pointer);
+ remove_proc_entry("flags",jsm_Board[i]->proc_entry_pointer);
+ remove_proc_entry("stats",jsm_Board[i]->proc_entry_pointer);
+ remove_proc_entry(board_number,ProcJSM);
+
+}
+
+void jsm_proc_unregister_all(void)
+{
+
+ /* Blow away the top proc entry */
+ remove_proc_entry("info",ProcJSM);
+ remove_proc_entry("mknod",ProcJSM);
+ remove_proc_entry("jsm", &proc_root);
+}