remarkable-linux/drivers/staging/dgnc/dgnc_mgmt.c
Tobin C. Harding 0053fe0eba staging: dgnc: remove struct member magic numbers
Driver uses magic number members within structs, this is an antiquated
method of catching data errors. We don't do things that way any more.

Remove magic number struct members. Remove all checks to magic
numbers.

Signed-off-by: Tobin C. Harding <me@tobin.cc>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
2017-03-29 09:37:10 +02:00

249 lines
5.2 KiB
C

/*
* 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.
*/
/*
* This file implements the mgmt functionality for the
* Neo and ClassicBoard based product lines.
*/
#include <linux/kernel.h>
#include <linux/ctype.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/serial_reg.h>
#include <linux/termios.h>
#include <linux/uaccess.h>
#include "dgnc_driver.h"
#include "dgnc_pci.h"
#include "dgnc_mgmt.h"
/* Our "in use" variables, to enforce 1 open only */
static int dgnc_mgmt_in_use[MAXMGMTDEVICES];
/**
* dgnc_mgmt_open() - Open the mgmt/downld/dpa device.
*/
int dgnc_mgmt_open(struct inode *inode, struct file *file)
{
unsigned long flags;
unsigned int minor = iminor(inode);
int rc = 0;
spin_lock_irqsave(&dgnc_global_lock, flags);
if (minor >= MAXMGMTDEVICES) {
rc = -ENXIO;
goto out;
}
/* Only allow 1 open at a time on mgmt device */
if (dgnc_mgmt_in_use[minor]) {
rc = -EBUSY;
goto out;
}
dgnc_mgmt_in_use[minor]++;
out:
spin_unlock_irqrestore(&dgnc_global_lock, flags);
return rc;
}
/**
* dgnc_mgmt_close() - Close the mgmt/dpa device
*/
int dgnc_mgmt_close(struct inode *inode, struct file *file)
{
unsigned long flags;
unsigned int minor = iminor(inode);
int rc = 0;
spin_lock_irqsave(&dgnc_global_lock, flags);
if (minor >= MAXMGMTDEVICES) {
rc = -ENXIO;
goto out;
}
dgnc_mgmt_in_use[minor] = 0;
out:
spin_unlock_irqrestore(&dgnc_global_lock, flags);
return rc;
}
/**
* dgnc_mgmt_ioctl() - Ioctl the mgmt/dpa device.
*/
long dgnc_mgmt_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
unsigned long flags;
void __user *uarg = (void __user *)arg;
switch (cmd) {
case DIGI_GETDD:
{
/*
* This returns the total number of boards
* in the system, as well as driver version
* and has space for a reserved entry
*/
struct digi_dinfo ddi;
spin_lock_irqsave(&dgnc_global_lock, flags);
memset(&ddi, 0, sizeof(ddi));
ddi.dinfo_nboards = dgnc_num_boards;
sprintf(ddi.dinfo_version, "%s", DG_PART);
spin_unlock_irqrestore(&dgnc_global_lock, flags);
if (copy_to_user(uarg, &ddi, sizeof(ddi)))
return -EFAULT;
break;
}
case DIGI_GETBD:
{
int brd;
struct digi_info di;
if (copy_from_user(&brd, uarg, sizeof(int)))
return -EFAULT;
if (brd < 0 || brd >= dgnc_num_boards)
return -ENODEV;
memset(&di, 0, sizeof(di));
di.info_bdnum = brd;
spin_lock_irqsave(&dgnc_board[brd]->bd_lock, flags);
di.info_bdtype = dgnc_board[brd]->dpatype;
di.info_bdstate = dgnc_board[brd]->dpastatus;
di.info_ioport = 0;
di.info_physaddr = (ulong)dgnc_board[brd]->membase;
di.info_physsize = (ulong)dgnc_board[brd]->membase
- dgnc_board[brd]->membase_end;
if (dgnc_board[brd]->state != BOARD_FAILED)
di.info_nports = dgnc_board[brd]->nasync;
else
di.info_nports = 0;
spin_unlock_irqrestore(&dgnc_board[brd]->bd_lock, flags);
if (copy_to_user(uarg, &di, sizeof(di)))
return -EFAULT;
break;
}
case DIGI_GET_NI_INFO:
{
struct channel_t *ch;
struct ni_info ni;
unsigned char mstat = 0;
uint board = 0;
uint channel = 0;
if (copy_from_user(&ni, uarg, sizeof(ni)))
return -EFAULT;
board = ni.board;
channel = ni.channel;
if (board >= dgnc_num_boards)
return -ENODEV;
if (channel >= dgnc_board[board]->nasync)
return -ENODEV;
ch = dgnc_board[board]->channels[channel];
if (!ch)
return -ENODEV;
memset(&ni, 0, sizeof(ni));
ni.board = board;
ni.channel = channel;
spin_lock_irqsave(&ch->ch_lock, flags);
mstat = ch->ch_mostat | ch->ch_mistat;
if (mstat & UART_MCR_DTR) {
ni.mstat |= TIOCM_DTR;
ni.dtr = TIOCM_DTR;
}
if (mstat & UART_MCR_RTS) {
ni.mstat |= TIOCM_RTS;
ni.rts = TIOCM_RTS;
}
if (mstat & UART_MSR_CTS) {
ni.mstat |= TIOCM_CTS;
ni.cts = TIOCM_CTS;
}
if (mstat & UART_MSR_RI) {
ni.mstat |= TIOCM_RI;
ni.ri = TIOCM_RI;
}
if (mstat & UART_MSR_DCD) {
ni.mstat |= TIOCM_CD;
ni.dcd = TIOCM_CD;
}
if (mstat & UART_MSR_DSR)
ni.mstat |= TIOCM_DSR;
ni.iflag = ch->ch_c_iflag;
ni.oflag = ch->ch_c_oflag;
ni.cflag = ch->ch_c_cflag;
ni.lflag = ch->ch_c_lflag;
if (ch->ch_digi.digi_flags & CTSPACE ||
ch->ch_c_cflag & CRTSCTS)
ni.hflow = 1;
else
ni.hflow = 0;
if ((ch->ch_flags & CH_STOPI) ||
(ch->ch_flags & CH_FORCED_STOPI))
ni.recv_stopped = 1;
else
ni.recv_stopped = 0;
if ((ch->ch_flags & CH_STOP) || (ch->ch_flags & CH_FORCED_STOP))
ni.xmit_stopped = 1;
else
ni.xmit_stopped = 0;
ni.curtx = ch->ch_txcount;
ni.currx = ch->ch_rxcount;
ni.baud = ch->ch_old_baud;
spin_unlock_irqrestore(&ch->ch_lock, flags);
if (copy_to_user(uarg, &ni, sizeof(ni)))
return -EFAULT;
break;
}
}
return 0;
}