538118b94f
Casting the return value which is a void pointer is redundant. The conversion from void pointer to any other pointer type is guaranteed by the C programming language. Signed-off-by: Jingoo Han <jg1.han@samsung.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
794 lines
21 KiB
C
794 lines
21 KiB
C
/*
|
|
* Copyright 2004 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: dgap_sysfs.c,v 1.1 2009/10/23 14:01:57 markh Exp $
|
|
*/
|
|
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/ctype.h>
|
|
#include <linux/string.h>
|
|
#include <linux/serial_reg.h>
|
|
#include <linux/device.h>
|
|
#include <linux/pci.h>
|
|
#include <linux/kdev_t.h>
|
|
|
|
#include "dgap_driver.h"
|
|
#include "dgap_conf.h"
|
|
#include "dgap_parse.h"
|
|
|
|
|
|
static ssize_t dgap_driver_version_show(struct device_driver *ddp, char *buf)
|
|
{
|
|
return snprintf(buf, PAGE_SIZE, "%s\n", DG_PART);
|
|
}
|
|
static DRIVER_ATTR(version, S_IRUSR, dgap_driver_version_show, NULL);
|
|
|
|
|
|
static ssize_t dgap_driver_boards_show(struct device_driver *ddp, char *buf)
|
|
{
|
|
return snprintf(buf, PAGE_SIZE, "%d\n", dgap_NumBoards);
|
|
}
|
|
static DRIVER_ATTR(boards, S_IRUSR, dgap_driver_boards_show, NULL);
|
|
|
|
|
|
static ssize_t dgap_driver_maxboards_show(struct device_driver *ddp, char *buf)
|
|
{
|
|
return snprintf(buf, PAGE_SIZE, "%d\n", MAXBOARDS);
|
|
}
|
|
static DRIVER_ATTR(maxboards, S_IRUSR, dgap_driver_maxboards_show, NULL);
|
|
|
|
|
|
static ssize_t dgap_driver_pollcounter_show(struct device_driver *ddp, char *buf)
|
|
{
|
|
return snprintf(buf, PAGE_SIZE, "%ld\n", dgap_poll_counter);
|
|
}
|
|
static DRIVER_ATTR(pollcounter, S_IRUSR, dgap_driver_pollcounter_show, NULL);
|
|
|
|
|
|
static ssize_t dgap_driver_state_show(struct device_driver *ddp, char *buf)
|
|
{
|
|
return snprintf(buf, PAGE_SIZE, "%s\n", dgap_driver_state_text[dgap_driver_state]);
|
|
}
|
|
static DRIVER_ATTR(state, S_IRUSR, dgap_driver_state_show, NULL);
|
|
|
|
|
|
static ssize_t dgap_driver_debug_show(struct device_driver *ddp, char *buf)
|
|
{
|
|
return snprintf(buf, PAGE_SIZE, "0x%x\n", dgap_debug);
|
|
}
|
|
|
|
static ssize_t dgap_driver_debug_store(struct device_driver *ddp, const char *buf, size_t count)
|
|
{
|
|
sscanf(buf, "0x%x\n", &dgap_debug);
|
|
return count;
|
|
}
|
|
static DRIVER_ATTR(debug, (S_IRUSR | S_IWUSR), dgap_driver_debug_show, dgap_driver_debug_store);
|
|
|
|
|
|
static ssize_t dgap_driver_rawreadok_show(struct device_driver *ddp, char *buf)
|
|
{
|
|
return snprintf(buf, PAGE_SIZE, "0x%x\n", dgap_rawreadok);
|
|
}
|
|
|
|
static ssize_t dgap_driver_rawreadok_store(struct device_driver *ddp, const char *buf, size_t count)
|
|
{
|
|
sscanf(buf, "0x%x\n", &dgap_rawreadok);
|
|
return count;
|
|
}
|
|
static DRIVER_ATTR(rawreadok, (S_IRUSR | S_IWUSR), dgap_driver_rawreadok_show, dgap_driver_rawreadok_store);
|
|
|
|
|
|
static ssize_t dgap_driver_pollrate_show(struct device_driver *ddp, char *buf)
|
|
{
|
|
return snprintf(buf, PAGE_SIZE, "%dms\n", dgap_poll_tick);
|
|
}
|
|
|
|
static ssize_t dgap_driver_pollrate_store(struct device_driver *ddp, const char *buf, size_t count)
|
|
{
|
|
sscanf(buf, "%d\n", &dgap_poll_tick);
|
|
return count;
|
|
}
|
|
static DRIVER_ATTR(pollrate, (S_IRUSR | S_IWUSR), dgap_driver_pollrate_show, dgap_driver_pollrate_store);
|
|
|
|
|
|
void dgap_create_driver_sysfiles(struct pci_driver *dgap_driver)
|
|
{
|
|
int rc = 0;
|
|
struct device_driver *driverfs = &dgap_driver->driver;
|
|
|
|
rc |= driver_create_file(driverfs, &driver_attr_version);
|
|
rc |= driver_create_file(driverfs, &driver_attr_boards);
|
|
rc |= driver_create_file(driverfs, &driver_attr_maxboards);
|
|
rc |= driver_create_file(driverfs, &driver_attr_debug);
|
|
rc |= driver_create_file(driverfs, &driver_attr_rawreadok);
|
|
rc |= driver_create_file(driverfs, &driver_attr_pollrate);
|
|
rc |= driver_create_file(driverfs, &driver_attr_pollcounter);
|
|
rc |= driver_create_file(driverfs, &driver_attr_state);
|
|
if (rc) {
|
|
printk(KERN_ERR "DGAP: sysfs driver_create_file failed!\n");
|
|
}
|
|
}
|
|
|
|
|
|
void dgap_remove_driver_sysfiles(struct pci_driver *dgap_driver)
|
|
{
|
|
struct device_driver *driverfs = &dgap_driver->driver;
|
|
driver_remove_file(driverfs, &driver_attr_version);
|
|
driver_remove_file(driverfs, &driver_attr_boards);
|
|
driver_remove_file(driverfs, &driver_attr_maxboards);
|
|
driver_remove_file(driverfs, &driver_attr_debug);
|
|
driver_remove_file(driverfs, &driver_attr_rawreadok);
|
|
driver_remove_file(driverfs, &driver_attr_pollrate);
|
|
driver_remove_file(driverfs, &driver_attr_pollcounter);
|
|
driver_remove_file(driverfs, &driver_attr_state);
|
|
}
|
|
|
|
|
|
#define DGAP_VERIFY_BOARD(p, bd) \
|
|
if (!p) \
|
|
return (0); \
|
|
\
|
|
bd = dev_get_drvdata(p); \
|
|
if (!bd || bd->magic != DGAP_BOARD_MAGIC) \
|
|
return (0); \
|
|
if (bd->state != BOARD_READY) \
|
|
return (0); \
|
|
|
|
|
|
static ssize_t dgap_ports_state_show(struct device *p, struct device_attribute *attr, char *buf)
|
|
{
|
|
struct board_t *bd;
|
|
int count = 0;
|
|
int i = 0;
|
|
|
|
DGAP_VERIFY_BOARD(p, bd);
|
|
|
|
for (i = 0; i < bd->nasync; i++) {
|
|
count += snprintf(buf + count, PAGE_SIZE - count,
|
|
"%d %s\n", bd->channels[i]->ch_portnum,
|
|
bd->channels[i]->ch_open_count ? "Open" : "Closed");
|
|
}
|
|
return count;
|
|
}
|
|
static DEVICE_ATTR(ports_state, S_IRUSR, dgap_ports_state_show, NULL);
|
|
|
|
|
|
static ssize_t dgap_ports_baud_show(struct device *p, struct device_attribute *attr, char *buf)
|
|
{
|
|
struct board_t *bd;
|
|
int count = 0;
|
|
int i = 0;
|
|
|
|
DGAP_VERIFY_BOARD(p, bd);
|
|
|
|
for (i = 0; i < bd->nasync; i++) {
|
|
count += snprintf(buf + count, PAGE_SIZE - count,
|
|
"%d %d\n", bd->channels[i]->ch_portnum, bd->channels[i]->ch_baud_info);
|
|
}
|
|
return count;
|
|
}
|
|
static DEVICE_ATTR(ports_baud, S_IRUSR, dgap_ports_baud_show, NULL);
|
|
|
|
|
|
static ssize_t dgap_ports_msignals_show(struct device *p, struct device_attribute *attr, char *buf)
|
|
{
|
|
struct board_t *bd;
|
|
int count = 0;
|
|
int i = 0;
|
|
|
|
DGAP_VERIFY_BOARD(p, bd);
|
|
|
|
for (i = 0; i < bd->nasync; i++) {
|
|
if (bd->channels[i]->ch_open_count) {
|
|
count += snprintf(buf + count, PAGE_SIZE - count,
|
|
"%d %s %s %s %s %s %s\n", bd->channels[i]->ch_portnum,
|
|
(bd->channels[i]->ch_mostat & UART_MCR_RTS) ? "RTS" : "",
|
|
(bd->channels[i]->ch_mistat & UART_MSR_CTS) ? "CTS" : "",
|
|
(bd->channels[i]->ch_mostat & UART_MCR_DTR) ? "DTR" : "",
|
|
(bd->channels[i]->ch_mistat & UART_MSR_DSR) ? "DSR" : "",
|
|
(bd->channels[i]->ch_mistat & UART_MSR_DCD) ? "DCD" : "",
|
|
(bd->channels[i]->ch_mistat & UART_MSR_RI) ? "RI" : "");
|
|
} else {
|
|
count += snprintf(buf + count, PAGE_SIZE - count,
|
|
"%d\n", bd->channels[i]->ch_portnum);
|
|
}
|
|
}
|
|
return count;
|
|
}
|
|
static DEVICE_ATTR(ports_msignals, S_IRUSR, dgap_ports_msignals_show, NULL);
|
|
|
|
|
|
static ssize_t dgap_ports_iflag_show(struct device *p, struct device_attribute *attr, char *buf)
|
|
{
|
|
struct board_t *bd;
|
|
int count = 0;
|
|
int i = 0;
|
|
|
|
DGAP_VERIFY_BOARD(p, bd);
|
|
|
|
for (i = 0; i < bd->nasync; i++) {
|
|
count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
|
|
bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_iflag);
|
|
}
|
|
return count;
|
|
}
|
|
static DEVICE_ATTR(ports_iflag, S_IRUSR, dgap_ports_iflag_show, NULL);
|
|
|
|
|
|
static ssize_t dgap_ports_cflag_show(struct device *p, struct device_attribute *attr, char *buf)
|
|
{
|
|
struct board_t *bd;
|
|
int count = 0;
|
|
int i = 0;
|
|
|
|
DGAP_VERIFY_BOARD(p, bd);
|
|
|
|
for (i = 0; i < bd->nasync; i++) {
|
|
count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
|
|
bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_cflag);
|
|
}
|
|
return count;
|
|
}
|
|
static DEVICE_ATTR(ports_cflag, S_IRUSR, dgap_ports_cflag_show, NULL);
|
|
|
|
|
|
static ssize_t dgap_ports_oflag_show(struct device *p, struct device_attribute *attr, char *buf)
|
|
{
|
|
struct board_t *bd;
|
|
int count = 0;
|
|
int i = 0;
|
|
|
|
DGAP_VERIFY_BOARD(p, bd);
|
|
|
|
for (i = 0; i < bd->nasync; i++) {
|
|
count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
|
|
bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_oflag);
|
|
}
|
|
return count;
|
|
}
|
|
static DEVICE_ATTR(ports_oflag, S_IRUSR, dgap_ports_oflag_show, NULL);
|
|
|
|
|
|
static ssize_t dgap_ports_lflag_show(struct device *p, struct device_attribute *attr, char *buf)
|
|
{
|
|
struct board_t *bd;
|
|
int count = 0;
|
|
int i = 0;
|
|
|
|
DGAP_VERIFY_BOARD(p, bd);
|
|
|
|
for (i = 0; i < bd->nasync; i++) {
|
|
count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
|
|
bd->channels[i]->ch_portnum, bd->channels[i]->ch_c_lflag);
|
|
}
|
|
return count;
|
|
}
|
|
static DEVICE_ATTR(ports_lflag, S_IRUSR, dgap_ports_lflag_show, NULL);
|
|
|
|
|
|
static ssize_t dgap_ports_digi_flag_show(struct device *p, struct device_attribute *attr, char *buf)
|
|
{
|
|
struct board_t *bd;
|
|
int count = 0;
|
|
int i = 0;
|
|
|
|
DGAP_VERIFY_BOARD(p, bd);
|
|
|
|
for (i = 0; i < bd->nasync; i++) {
|
|
count += snprintf(buf + count, PAGE_SIZE - count, "%d %x\n",
|
|
bd->channels[i]->ch_portnum, bd->channels[i]->ch_digi.digi_flags);
|
|
}
|
|
return count;
|
|
}
|
|
static DEVICE_ATTR(ports_digi_flag, S_IRUSR, dgap_ports_digi_flag_show, NULL);
|
|
|
|
|
|
static ssize_t dgap_ports_rxcount_show(struct device *p, struct device_attribute *attr, char *buf)
|
|
{
|
|
struct board_t *bd;
|
|
int count = 0;
|
|
int i = 0;
|
|
|
|
DGAP_VERIFY_BOARD(p, bd);
|
|
|
|
for (i = 0; i < bd->nasync; i++) {
|
|
count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n",
|
|
bd->channels[i]->ch_portnum, bd->channels[i]->ch_rxcount);
|
|
}
|
|
return count;
|
|
}
|
|
static DEVICE_ATTR(ports_rxcount, S_IRUSR, dgap_ports_rxcount_show, NULL);
|
|
|
|
|
|
static ssize_t dgap_ports_txcount_show(struct device *p, struct device_attribute *attr, char *buf)
|
|
{
|
|
struct board_t *bd;
|
|
int count = 0;
|
|
int i = 0;
|
|
|
|
DGAP_VERIFY_BOARD(p, bd);
|
|
|
|
for (i = 0; i < bd->nasync; i++) {
|
|
count += snprintf(buf + count, PAGE_SIZE - count, "%d %ld\n",
|
|
bd->channels[i]->ch_portnum, bd->channels[i]->ch_txcount);
|
|
}
|
|
return count;
|
|
}
|
|
static DEVICE_ATTR(ports_txcount, S_IRUSR, dgap_ports_txcount_show, NULL);
|
|
|
|
|
|
/* this function creates the sys files that will export each signal status
|
|
* to sysfs each value will be put in a separate filename
|
|
*/
|
|
void dgap_create_ports_sysfiles(struct board_t *bd)
|
|
{
|
|
int rc = 0;
|
|
|
|
dev_set_drvdata(&bd->pdev->dev, bd);
|
|
rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_state);
|
|
rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_baud);
|
|
rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_msignals);
|
|
rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_iflag);
|
|
rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_cflag);
|
|
rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_oflag);
|
|
rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_lflag);
|
|
rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_digi_flag);
|
|
rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_rxcount);
|
|
rc |= device_create_file(&(bd->pdev->dev), &dev_attr_ports_txcount);
|
|
if (rc) {
|
|
printk(KERN_ERR "DGAP: sysfs device_create_file failed!\n");
|
|
}
|
|
}
|
|
|
|
|
|
/* removes all the sys files created for that port */
|
|
void dgap_remove_ports_sysfiles(struct board_t *bd)
|
|
{
|
|
device_remove_file(&(bd->pdev->dev), &dev_attr_ports_state);
|
|
device_remove_file(&(bd->pdev->dev), &dev_attr_ports_baud);
|
|
device_remove_file(&(bd->pdev->dev), &dev_attr_ports_msignals);
|
|
device_remove_file(&(bd->pdev->dev), &dev_attr_ports_iflag);
|
|
device_remove_file(&(bd->pdev->dev), &dev_attr_ports_cflag);
|
|
device_remove_file(&(bd->pdev->dev), &dev_attr_ports_oflag);
|
|
device_remove_file(&(bd->pdev->dev), &dev_attr_ports_lflag);
|
|
device_remove_file(&(bd->pdev->dev), &dev_attr_ports_digi_flag);
|
|
device_remove_file(&(bd->pdev->dev), &dev_attr_ports_rxcount);
|
|
device_remove_file(&(bd->pdev->dev), &dev_attr_ports_txcount);
|
|
}
|
|
|
|
|
|
static ssize_t dgap_tty_state_show(struct device *d, struct device_attribute *attr, char *buf)
|
|
{
|
|
struct board_t *bd;
|
|
struct channel_t *ch;
|
|
struct un_t *un;
|
|
|
|
if (!d)
|
|
return (0);
|
|
un = dev_get_drvdata(d);
|
|
if (!un || un->magic != DGAP_UNIT_MAGIC)
|
|
return (0);
|
|
ch = un->un_ch;
|
|
if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
|
|
return (0);
|
|
bd = ch->ch_bd;
|
|
if (!bd || bd->magic != DGAP_BOARD_MAGIC)
|
|
return (0);
|
|
if (bd->state != BOARD_READY)
|
|
return (0);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%s", un->un_open_count ? "Open" : "Closed");
|
|
}
|
|
static DEVICE_ATTR(state, S_IRUSR, dgap_tty_state_show, NULL);
|
|
|
|
|
|
static ssize_t dgap_tty_baud_show(struct device *d, struct device_attribute *attr, char *buf)
|
|
{
|
|
struct board_t *bd;
|
|
struct channel_t *ch;
|
|
struct un_t *un;
|
|
|
|
if (!d)
|
|
return (0);
|
|
un = dev_get_drvdata(d);
|
|
if (!un || un->magic != DGAP_UNIT_MAGIC)
|
|
return (0);
|
|
ch = un->un_ch;
|
|
if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
|
|
return (0);
|
|
bd = ch->ch_bd;
|
|
if (!bd || bd->magic != DGAP_BOARD_MAGIC)
|
|
return (0);
|
|
if (bd->state != BOARD_READY)
|
|
return (0);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%d\n", ch->ch_baud_info);
|
|
}
|
|
static DEVICE_ATTR(baud, S_IRUSR, dgap_tty_baud_show, NULL);
|
|
|
|
|
|
static ssize_t dgap_tty_msignals_show(struct device *d, struct device_attribute *attr, char *buf)
|
|
{
|
|
struct board_t *bd;
|
|
struct channel_t *ch;
|
|
struct un_t *un;
|
|
|
|
if (!d)
|
|
return (0);
|
|
un = dev_get_drvdata(d);
|
|
if (!un || un->magic != DGAP_UNIT_MAGIC)
|
|
return (0);
|
|
ch = un->un_ch;
|
|
if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
|
|
return (0);
|
|
bd = ch->ch_bd;
|
|
if (!bd || bd->magic != DGAP_BOARD_MAGIC)
|
|
return (0);
|
|
if (bd->state != BOARD_READY)
|
|
return (0);
|
|
|
|
if (ch->ch_open_count) {
|
|
return snprintf(buf, PAGE_SIZE, "%s %s %s %s %s %s\n",
|
|
(ch->ch_mostat & UART_MCR_RTS) ? "RTS" : "",
|
|
(ch->ch_mistat & UART_MSR_CTS) ? "CTS" : "",
|
|
(ch->ch_mostat & UART_MCR_DTR) ? "DTR" : "",
|
|
(ch->ch_mistat & UART_MSR_DSR) ? "DSR" : "",
|
|
(ch->ch_mistat & UART_MSR_DCD) ? "DCD" : "",
|
|
(ch->ch_mistat & UART_MSR_RI) ? "RI" : "");
|
|
}
|
|
return 0;
|
|
}
|
|
static DEVICE_ATTR(msignals, S_IRUSR, dgap_tty_msignals_show, NULL);
|
|
|
|
|
|
static ssize_t dgap_tty_iflag_show(struct device *d, struct device_attribute *attr, char *buf)
|
|
{
|
|
struct board_t *bd;
|
|
struct channel_t *ch;
|
|
struct un_t *un;
|
|
|
|
if (!d)
|
|
return (0);
|
|
un = dev_get_drvdata(d);
|
|
if (!un || un->magic != DGAP_UNIT_MAGIC)
|
|
return (0);
|
|
ch = un->un_ch;
|
|
if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
|
|
return (0);
|
|
bd = ch->ch_bd;
|
|
if (!bd || bd->magic != DGAP_BOARD_MAGIC)
|
|
return (0);
|
|
if (bd->state != BOARD_READY)
|
|
return (0);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_iflag);
|
|
}
|
|
static DEVICE_ATTR(iflag, S_IRUSR, dgap_tty_iflag_show, NULL);
|
|
|
|
|
|
static ssize_t dgap_tty_cflag_show(struct device *d, struct device_attribute *attr, char *buf)
|
|
{
|
|
struct board_t *bd;
|
|
struct channel_t *ch;
|
|
struct un_t *un;
|
|
|
|
if (!d)
|
|
return (0);
|
|
un = dev_get_drvdata(d);
|
|
if (!un || un->magic != DGAP_UNIT_MAGIC)
|
|
return (0);
|
|
ch = un->un_ch;
|
|
if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
|
|
return (0);
|
|
bd = ch->ch_bd;
|
|
if (!bd || bd->magic != DGAP_BOARD_MAGIC)
|
|
return (0);
|
|
if (bd->state != BOARD_READY)
|
|
return (0);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_cflag);
|
|
}
|
|
static DEVICE_ATTR(cflag, S_IRUSR, dgap_tty_cflag_show, NULL);
|
|
|
|
|
|
static ssize_t dgap_tty_oflag_show(struct device *d, struct device_attribute *attr, char *buf)
|
|
{
|
|
struct board_t *bd;
|
|
struct channel_t *ch;
|
|
struct un_t *un;
|
|
|
|
if (!d)
|
|
return (0);
|
|
un = dev_get_drvdata(d);
|
|
if (!un || un->magic != DGAP_UNIT_MAGIC)
|
|
return (0);
|
|
ch = un->un_ch;
|
|
if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
|
|
return (0);
|
|
bd = ch->ch_bd;
|
|
if (!bd || bd->magic != DGAP_BOARD_MAGIC)
|
|
return (0);
|
|
if (bd->state != BOARD_READY)
|
|
return (0);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_oflag);
|
|
}
|
|
static DEVICE_ATTR(oflag, S_IRUSR, dgap_tty_oflag_show, NULL);
|
|
|
|
|
|
static ssize_t dgap_tty_lflag_show(struct device *d, struct device_attribute *attr, char *buf)
|
|
{
|
|
struct board_t *bd;
|
|
struct channel_t *ch;
|
|
struct un_t *un;
|
|
|
|
if (!d)
|
|
return (0);
|
|
un = dev_get_drvdata(d);
|
|
if (!un || un->magic != DGAP_UNIT_MAGIC)
|
|
return (0);
|
|
ch = un->un_ch;
|
|
if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
|
|
return (0);
|
|
bd = ch->ch_bd;
|
|
if (!bd || bd->magic != DGAP_BOARD_MAGIC)
|
|
return (0);
|
|
if (bd->state != BOARD_READY)
|
|
return (0);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_c_lflag);
|
|
}
|
|
static DEVICE_ATTR(lflag, S_IRUSR, dgap_tty_lflag_show, NULL);
|
|
|
|
|
|
static ssize_t dgap_tty_digi_flag_show(struct device *d, struct device_attribute *attr, char *buf)
|
|
{
|
|
struct board_t *bd;
|
|
struct channel_t *ch;
|
|
struct un_t *un;
|
|
|
|
if (!d)
|
|
return (0);
|
|
un = dev_get_drvdata(d);
|
|
if (!un || un->magic != DGAP_UNIT_MAGIC)
|
|
return (0);
|
|
ch = un->un_ch;
|
|
if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
|
|
return (0);
|
|
bd = ch->ch_bd;
|
|
if (!bd || bd->magic != DGAP_BOARD_MAGIC)
|
|
return (0);
|
|
if (bd->state != BOARD_READY)
|
|
return (0);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%x\n", ch->ch_digi.digi_flags);
|
|
}
|
|
static DEVICE_ATTR(digi_flag, S_IRUSR, dgap_tty_digi_flag_show, NULL);
|
|
|
|
|
|
static ssize_t dgap_tty_rxcount_show(struct device *d, struct device_attribute *attr, char *buf)
|
|
{
|
|
struct board_t *bd;
|
|
struct channel_t *ch;
|
|
struct un_t *un;
|
|
|
|
if (!d)
|
|
return (0);
|
|
un = dev_get_drvdata(d);
|
|
if (!un || un->magic != DGAP_UNIT_MAGIC)
|
|
return (0);
|
|
ch = un->un_ch;
|
|
if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
|
|
return (0);
|
|
bd = ch->ch_bd;
|
|
if (!bd || bd->magic != DGAP_BOARD_MAGIC)
|
|
return (0);
|
|
if (bd->state != BOARD_READY)
|
|
return (0);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_rxcount);
|
|
}
|
|
static DEVICE_ATTR(rxcount, S_IRUSR, dgap_tty_rxcount_show, NULL);
|
|
|
|
|
|
static ssize_t dgap_tty_txcount_show(struct device *d, struct device_attribute *attr, char *buf)
|
|
{
|
|
struct board_t *bd;
|
|
struct channel_t *ch;
|
|
struct un_t *un;
|
|
|
|
if (!d)
|
|
return (0);
|
|
un = dev_get_drvdata(d);
|
|
if (!un || un->magic != DGAP_UNIT_MAGIC)
|
|
return (0);
|
|
ch = un->un_ch;
|
|
if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
|
|
return (0);
|
|
bd = ch->ch_bd;
|
|
if (!bd || bd->magic != DGAP_BOARD_MAGIC)
|
|
return (0);
|
|
if (bd->state != BOARD_READY)
|
|
return (0);
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%ld\n", ch->ch_txcount);
|
|
}
|
|
static DEVICE_ATTR(txcount, S_IRUSR, dgap_tty_txcount_show, NULL);
|
|
|
|
|
|
static ssize_t dgap_tty_name_show(struct device *d, struct device_attribute *attr, char *buf)
|
|
{
|
|
struct board_t *bd;
|
|
struct channel_t *ch;
|
|
struct un_t *un;
|
|
int cn;
|
|
int bn;
|
|
struct cnode *cptr = NULL;
|
|
int found = FALSE;
|
|
int ncount = 0;
|
|
int starto = 0;
|
|
int i = 0;
|
|
|
|
if (!d)
|
|
return (0);
|
|
un = dev_get_drvdata(d);
|
|
if (!un || un->magic != DGAP_UNIT_MAGIC)
|
|
return (0);
|
|
ch = un->un_ch;
|
|
if (!ch || ch->magic != DGAP_CHANNEL_MAGIC)
|
|
return (0);
|
|
bd = ch->ch_bd;
|
|
if (!bd || bd->magic != DGAP_BOARD_MAGIC)
|
|
return (0);
|
|
if (bd->state != BOARD_READY)
|
|
return (0);
|
|
|
|
bn = bd->boardnum;
|
|
cn = ch->ch_portnum;
|
|
|
|
for (cptr = bd->bd_config; cptr; cptr = cptr->next) {
|
|
|
|
if ((cptr->type == BNODE) &&
|
|
((cptr->u.board.type == APORT2_920P) || (cptr->u.board.type == APORT4_920P) ||
|
|
(cptr->u.board.type == APORT8_920P) || (cptr->u.board.type == PAPORT4) ||
|
|
(cptr->u.board.type == PAPORT8))) {
|
|
|
|
found = TRUE;
|
|
if (cptr->u.board.v_start)
|
|
starto = cptr->u.board.start;
|
|
else
|
|
starto = 1;
|
|
}
|
|
|
|
if (cptr->type == TNODE && found == TRUE) {
|
|
char *ptr1;
|
|
if (strstr(cptr->u.ttyname, "tty")) {
|
|
ptr1 = cptr->u.ttyname;
|
|
ptr1 += 3;
|
|
}
|
|
else {
|
|
ptr1 = cptr->u.ttyname;
|
|
}
|
|
|
|
for (i = 0; i < dgap_config_get_number_of_ports(bd); i++) {
|
|
if (cn == i) {
|
|
return snprintf(buf, PAGE_SIZE, "%s%s%02d\n",
|
|
(un->un_type == DGAP_PRINT) ? "pr" : "tty",
|
|
ptr1, i + starto);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (cptr->type == CNODE) {
|
|
|
|
for (i = 0; i < cptr->u.conc.nport; i++) {
|
|
if (cn == (i + ncount)) {
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%s%s%02d\n",
|
|
(un->un_type == DGAP_PRINT) ? "pr" : "tty",
|
|
cptr->u.conc.id,
|
|
i + (cptr->u.conc.v_start ? cptr->u.conc.start : 1));
|
|
}
|
|
}
|
|
|
|
ncount += cptr->u.conc.nport;
|
|
}
|
|
|
|
if (cptr->type == MNODE) {
|
|
|
|
for (i = 0; i < cptr->u.module.nport; i++) {
|
|
if (cn == (i + ncount)) {
|
|
return snprintf(buf, PAGE_SIZE, "%s%s%02d\n",
|
|
(un->un_type == DGAP_PRINT) ? "pr" : "tty",
|
|
cptr->u.module.id,
|
|
i + (cptr->u.module.v_start ? cptr->u.module.start : 1));
|
|
}
|
|
}
|
|
|
|
ncount += cptr->u.module.nport;
|
|
|
|
}
|
|
}
|
|
|
|
return snprintf(buf, PAGE_SIZE, "%s_dgap_%d_%d\n",
|
|
(un->un_type == DGAP_PRINT) ? "pr" : "tty", bn, cn);
|
|
|
|
}
|
|
static DEVICE_ATTR(custom_name, S_IRUSR, dgap_tty_name_show, NULL);
|
|
|
|
|
|
static struct attribute *dgap_sysfs_tty_entries[] = {
|
|
&dev_attr_state.attr,
|
|
&dev_attr_baud.attr,
|
|
&dev_attr_msignals.attr,
|
|
&dev_attr_iflag.attr,
|
|
&dev_attr_cflag.attr,
|
|
&dev_attr_oflag.attr,
|
|
&dev_attr_lflag.attr,
|
|
&dev_attr_digi_flag.attr,
|
|
&dev_attr_rxcount.attr,
|
|
&dev_attr_txcount.attr,
|
|
&dev_attr_custom_name.attr,
|
|
NULL
|
|
};
|
|
|
|
|
|
static struct attribute_group dgap_tty_attribute_group = {
|
|
.name = NULL,
|
|
.attrs = dgap_sysfs_tty_entries,
|
|
};
|
|
|
|
|
|
|
|
|
|
void dgap_create_tty_sysfs(struct un_t *un, struct device *c)
|
|
{
|
|
int ret;
|
|
|
|
ret = sysfs_create_group(&c->kobj, &dgap_tty_attribute_group);
|
|
if (ret) {
|
|
printk(KERN_ERR "dgap: failed to create sysfs tty device attributes.\n");
|
|
sysfs_remove_group(&c->kobj, &dgap_tty_attribute_group);
|
|
return;
|
|
}
|
|
|
|
dev_set_drvdata(c, un);
|
|
|
|
}
|
|
|
|
|
|
void dgap_remove_tty_sysfs(struct device *c)
|
|
{
|
|
sysfs_remove_group(&c->kobj, &dgap_tty_attribute_group);
|
|
}
|