summaryrefslogtreecommitdiffstats
path: root/drivers/char/moxa.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--drivers/char/moxa.c235
1 files changed, 116 insertions, 119 deletions
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index c440ec542686..b2f3de0195c9 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -104,7 +104,7 @@ static struct moxa_board_conf {
int numPorts;
int busType;
- int loadstat;
+ unsigned int ready;
struct moxa_port *ports;
@@ -142,7 +142,6 @@ struct moxa_port {
struct timer_list emptyTimer;
- char chkPort;
char lineCtrl;
void __iomem *tableAddr;
char DCDState;
@@ -162,7 +161,6 @@ struct moxa_port {
#define WAKEUP_CHARS 256
static int ttymajor = MOXAMAJOR;
-static int moxaCard;
/* Variables for insmod */
#ifdef MODULE
static unsigned long baseaddr[MAX_BOARDS];
@@ -218,7 +216,6 @@ static void moxa_receive_data(struct moxa_port *);
static int MoxaDriverIoctl(struct tty_struct *, unsigned int, unsigned long);
static int MoxaDriverPoll(void);
static int MoxaPortsOfCard(int);
-static int MoxaPortIsValid(int);
static void MoxaPortEnable(struct moxa_port *);
static void MoxaPortDisable(struct moxa_port *);
static int MoxaPortSetTermio(struct moxa_port *, struct ktermios *, speed_t);
@@ -263,7 +260,6 @@ static const struct tty_operations moxa_ops = {
};
static struct tty_driver *moxaDriver;
-static struct moxa_port moxa_ports[MAX_PORTS];
static DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0);
static DEFINE_SPINLOCK(moxa_lock);
@@ -480,7 +476,6 @@ static int moxa_real_load_code(struct moxa_board_conf *brd, const void *ptr,
if (readw(baseAddr + Magic_no) != Magic_code)
return -EIO;
}
- moxaCard = 1;
brd->intNdx = baseAddr + IRQindex;
brd->intPend = baseAddr + IRQpending;
brd->intTable = baseAddr + IRQtable;
@@ -511,7 +506,6 @@ static int moxa_load_code(struct moxa_board_conf *brd, const void *ptr,
port = brd->ports;
for (i = 0; i < brd->numPorts; i++, port++) {
port->board = brd;
- port->chkPort = 1;
port->DCDState = 0;
port->tableAddr = baseAddr + Extern_table +
Extern_size * i;
@@ -530,7 +524,6 @@ static int moxa_load_code(struct moxa_board_conf *brd, const void *ptr,
port = brd->ports;
for (i = 0; i < brd->numPorts; i++, port++) {
port->board = brd;
- port->chkPort = 1;
port->DCDState = 0;
port->tableAddr = baseAddr + Extern_table +
Extern_size * i;
@@ -575,7 +568,6 @@ static int moxa_load_code(struct moxa_board_conf *brd, const void *ptr,
}
break;
}
- brd->loadstat = 1;
return 0;
}
@@ -672,8 +664,29 @@ static int moxa_init_board(struct moxa_board_conf *brd, struct device *dev)
{
const struct firmware *fw;
const char *file;
+ struct moxa_port *p;
+ unsigned int i;
int ret;
+ brd->ports = kcalloc(MAX_PORTS_PER_BOARD, sizeof(*brd->ports),
+ GFP_KERNEL);
+ if (brd->ports == NULL) {
+ printk(KERN_ERR "cannot allocate memory for ports\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ for (i = 0, p = brd->ports; i < MAX_PORTS_PER_BOARD; i++, p++) {
+ p->type = PORT_16550A;
+ p->close_delay = 5 * HZ / 10;
+ p->cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
+ init_waitqueue_head(&p->open_wait);
+ init_completion(&p->close_wait);
+
+ setup_timer(&p->emptyTimer, moxa_check_xmit_empty,
+ (unsigned long)p);
+ }
+
switch (brd->boardType) {
case MOXA_BOARD_C218_ISA:
case MOXA_BOARD_C218_PCI:
@@ -690,16 +703,38 @@ static int moxa_init_board(struct moxa_board_conf *brd, struct device *dev)
ret = request_firmware(&fw, file, dev);
if (ret) {
printk(KERN_ERR "request_firmware failed\n");
- goto end;
+ goto err_free;
}
ret = moxa_load_fw(brd, fw);
release_firmware(fw);
-end:
+
+ if (ret)
+ goto err_free;
+
+ brd->ready = 1;
+
+ return 0;
+err_free:
+ kfree(brd->ports);
+err:
return ret;
}
+static void moxa_board_deinit(struct moxa_board_conf *brd)
+{
+ unsigned int i;
+
+ brd->ready = 0;
+ for (i = 0; i < MAX_PORTS_PER_BOARD; i++)
+ del_timer_sync(&brd->ports[i].emptyTimer);
+
+ iounmap(brd->basemem);
+ brd->basemem = NULL;
+ kfree(brd->ports);
+}
+
#ifdef CONFIG_PCI
static int __devinit moxa_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
@@ -727,7 +762,6 @@ static int __devinit moxa_pci_probe(struct pci_dev *pdev,
}
board = &moxa_boards[i];
- board->ports = &moxa_ports[i * MAX_PORTS_PER_BOARD];
retval = pci_request_region(pdev, 2, "moxa-base");
if (retval) {
@@ -777,8 +811,8 @@ static void __devexit moxa_pci_remove(struct pci_dev *pdev)
{
struct moxa_board_conf *brd = pci_get_drvdata(pdev);
- iounmap(brd->basemem);
- brd->basemem = NULL;
+ moxa_board_deinit(brd);
+
pci_release_region(pdev, 2);
}
@@ -792,8 +826,7 @@ static struct pci_driver moxa_pci_driver = {
static int __init moxa_init(void)
{
- struct moxa_port *ch;
- unsigned int i, isabrds = 0;
+ unsigned int isabrds = 0;
int retval = 0;
printk(KERN_INFO "MOXA Intellio family driver version %s\n",
@@ -815,17 +848,6 @@ static int __init moxa_init(void)
moxaDriver->flags = TTY_DRIVER_REAL_RAW;
tty_set_operations(moxaDriver, &moxa_ops);
- for (i = 0, ch = moxa_ports; i < MAX_PORTS; i++, ch++) {
- ch->type = PORT_16550A;
- ch->close_delay = 5 * HZ / 10;
- ch->cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
- init_waitqueue_head(&ch->open_wait);
- init_completion(&ch->close_wait);
-
- setup_timer(&ch->emptyTimer, moxa_check_xmit_empty,
- (unsigned long)ch);
- }
-
pr_debug("Moxa tty devices major number = %d\n", ttymajor);
if (tty_register_driver(moxaDriver)) {
@@ -840,6 +862,7 @@ static int __init moxa_init(void)
#ifdef MODULE
{
struct moxa_board_conf *brd = moxa_boards;
+ unsigned int i;
for (i = 0; i < MAX_BOARDS; i++) {
if (!baseaddr[i])
break;
@@ -849,7 +872,6 @@ static int __init moxa_init(void)
isabrds + 1, moxa_brdname[type[i] - 1],
baseaddr[i]);
brd->boardType = type[i];
- brd->ports = &moxa_ports[isabrds * MAX_PORTS_PER_BOARD];
brd->numPorts = type[i] == MOXA_BOARD_C218_ISA ? 8 :
numports[i];
brd->busType = MOXA_BUS_TYPE_ISA;
@@ -890,9 +912,6 @@ static void __exit moxa_exit(void)
del_timer_sync(&moxaTimer);
- for (i = 0; i < MAX_PORTS; i++)
- del_timer_sync(&moxa_ports[i].emptyTimer);
-
if (tty_unregister_driver(moxaDriver))
printk(KERN_ERR "Couldn't unregister MOXA Intellio family "
"serial driver\n");
@@ -902,9 +921,9 @@ static void __exit moxa_exit(void)
pci_unregister_driver(&moxa_pci_driver);
#endif
- for (i = 0; i < MAX_BOARDS; i++)
- if (moxa_boards[i].basemem)
- iounmap(moxa_boards[i].basemem);
+ for (i = 0; i < MAX_BOARDS; i++) /* ISA boards */
+ if (moxa_boards[i].ready)
+ moxa_board_deinit(&moxa_boards[i]);
}
module_init(moxa_init);
@@ -912,6 +931,7 @@ module_exit(moxa_exit);
static int moxa_open(struct tty_struct *tty, struct file *filp)
{
+ struct moxa_board_conf *brd;
struct moxa_port *ch;
int port;
int retval;
@@ -920,12 +940,11 @@ static int moxa_open(struct tty_struct *tty, struct file *filp)
if (port == MAX_PORTS) {
return (0);
}
- if (!MoxaPortIsValid(port)) {
- tty->driver_data = NULL;
- return (-ENODEV);
- }
+ brd = &moxa_boards[port / MAX_PORTS_PER_BOARD];
+ if (!brd->ready)
+ return -ENODEV;
- ch = &moxa_ports[port];
+ ch = &brd->ports[port % MAX_PORTS_PER_BOARD];
ch->count++;
tty->driver_data = ch;
ch->tty = tty;
@@ -958,11 +977,6 @@ static void moxa_close(struct tty_struct *tty, struct file *filp)
if (port == MAX_PORTS) {
return;
}
- if (!MoxaPortIsValid(port)) {
- pr_debug("Invalid portno in moxa_close\n");
- tty->driver_data = NULL;
- return;
- }
if (tty->driver_data == NULL) {
return;
}
@@ -1285,7 +1299,7 @@ static void moxa_poll(unsigned long ignored)
for (card = 0; card < MAX_BOARDS; card++) {
if ((ports = MoxaPortsOfCard(card)) <= 0)
continue;
- ch = &moxa_ports[card * MAX_PORTS_PER_BOARD];
+ ch = moxa_boards[card].ports;
for (i = 0; i < ports; i++, ch++) {
if ((ch->asyncflags & ASYNC_INITIALIZED) == 0)
continue;
@@ -1589,17 +1603,22 @@ static int MoxaDriverIoctl(struct tty_struct *tty, unsigned int cmd,
case MOXA_GET_IOQUEUE: {
struct moxaq_str __user *argm = argp;
struct moxaq_str tmp;
-
- for (i = 0; i < MAX_PORTS; i++, argm++) {
- memset(&tmp, 0, sizeof(tmp));
- if (moxa_ports[i].chkPort) {
- tmp.inq = MoxaPortRxQueue(&moxa_ports[i]);
- tmp.outq = MoxaPortTxQueue(&moxa_ports[i]);
+ struct moxa_port *p;
+ unsigned int j;
+
+ for (i = 0; i < MAX_BOARDS; i++) {
+ p = moxa_boards[i].ports;
+ for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) {
+ memset(&tmp, 0, sizeof(tmp));
+ if (moxa_boards[i].ready) {
+ tmp.inq = MoxaPortRxQueue(p);
+ tmp.outq = MoxaPortTxQueue(p);
+ }
+ if (copy_to_user(argm, &tmp, sizeof(tmp)))
+ return -EFAULT;
}
- if (copy_to_user(argm, &tmp, sizeof(tmp)))
- return -EFAULT;
}
- return (0);
+ return 0;
} case MOXA_GET_OQUEUE:
i = MoxaPortTxQueue(port);
return put_user(i, (unsigned long __user *)argp);
@@ -1619,13 +1638,15 @@ static int MoxaDriverIoctl(struct tty_struct *tty, unsigned int cmd,
struct mxser_mstatus __user *argm = argp;
struct mxser_mstatus tmp;
struct moxa_port *p;
+ unsigned int j;
+
+ for (i = 0; i < MAX_BOARDS; i++) {
+ p = moxa_boards[i].ports;
+ for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) {
+ memset(&tmp, 0, sizeof(tmp));
+ if (!moxa_boards[i].ready)
+ goto copy;
- for (i = 0; i < MAX_PORTS; i++, argm++) {
- p = &moxa_ports[i];
- memset(&tmp, 0, sizeof(tmp));
- if (!p->chkPort) {
- goto copy;
- } else {
status = MoxaPortLineStatus(p);
if (status & 1)
tmp.cts = 1;
@@ -1633,15 +1654,15 @@ static int MoxaDriverIoctl(struct tty_struct *tty, unsigned int cmd,
tmp.dsr = 1;
if (status & 4)
tmp.dcd = 1;
- }
- if (!p->tty || !p->tty->termios)
- tmp.cflag = p->cflag;
- else
- tmp.cflag = p->tty->termios->c_cflag;
+ if (!p->tty || !p->tty->termios)
+ tmp.cflag = p->cflag;
+ else
+ tmp.cflag = p->tty->termios->c_cflag;
copy:
- if (copy_to_user(argm, &tmp, sizeof(tmp)))
- return -EFAULT;
+ if (copy_to_user(argm, &tmp, sizeof(tmp)))
+ return -EFAULT;
+ }
}
return 0;
}
@@ -1653,53 +1674,55 @@ copy:
int MoxaDriverPoll(void)
{
struct moxa_board_conf *brd;
+ struct moxa_port *p;
register ushort temp;
register int card;
void __iomem *ofsAddr;
void __iomem *ip;
- int port, p, ports;
+ int port, ports;
- if (moxaCard == 0)
- return (-1);
for (card = 0; card < MAX_BOARDS; card++) {
brd = &moxa_boards[card];
- if (brd->loadstat == 0)
+ if (brd->ready == 0)
continue;
if ((ports = brd->numPorts) == 0)
continue;
if (readb(brd->intPend) == 0xff) {
ip = brd->intTable + readb(brd->intNdx);
- p = card * MAX_PORTS_PER_BOARD;
+ p = brd->ports;
ports <<= 1;
for (port = 0; port < ports; port += 2, p++) {
- if ((temp = readw(ip + port)) != 0) {
- writew(0, ip + port);
- ofsAddr = moxa_ports[p].tableAddr;
- if (temp & IntrTx)
- writew(readw(ofsAddr + HostStat) & ~WakeupTx, ofsAddr + HostStat);
- if (temp & IntrBreak) {
- moxa_ports[p].breakCnt++;
- }
- if (temp & IntrLine) {
- if (readb(ofsAddr + FlagStat) & DCD_state) {
- if ((moxa_ports[p].DCDState & DCD_oldstate) == 0)
- moxa_ports[p].DCDState = (DCD_oldstate |
- DCD_changed);
- } else {
- if (moxa_ports[p].DCDState & DCD_oldstate)
- moxa_ports[p].DCDState = DCD_changed;
- }
+ temp = readw(ip + port);
+ if (temp == 0)
+ continue;
+
+ writew(0, ip + port);
+ ofsAddr = p->tableAddr;
+ if (temp & IntrTx)
+ writew(readw(ofsAddr + HostStat) &
+ ~WakeupTx, ofsAddr + HostStat);
+ if (temp & IntrBreak)
+ p->breakCnt++;
+
+ if (temp & IntrLine) {
+ if (readb(ofsAddr + FlagStat) & DCD_state) {
+ if ((p->DCDState & DCD_oldstate) == 0)
+ p->DCDState = (DCD_oldstate |
+ DCD_changed);
+ } else {
+ if (p->DCDState & DCD_oldstate)
+ p->DCDState = DCD_changed;
}
}
}
writeb(0, brd->intPend);
}
if (moxaLowWaterChk) {
- p = card * MAX_PORTS_PER_BOARD;
+ p = brd->ports;
for (port = 0; port < ports; port++, p++) {
- if (moxa_ports[p].lowChkFlag) {
- moxa_ports[p].lowChkFlag = 0;
- ofsAddr = moxa_ports[p].tableAddr;
+ if (p->lowChkFlag) {
+ p->lowChkFlag = 0;
+ ofsAddr = p->tableAddr;
moxa_low_water_check(ofsAddr);
}
}
@@ -1723,7 +1746,6 @@ int MoxaPortsOfCard(int cardno)
/*****************************************************************************
* Port level functions: *
- * 1. MoxaPortIsValid(int port); *
* 2. MoxaPortEnable(int port); *
* 3. MoxaPortDisable(int port); *
* 4. MoxaPortGetMaxBaud(int port); *
@@ -1800,15 +1822,6 @@ int MoxaPortsOfCard(int cardno)
* 8/16/24/32
*
*
- * Function 5: Check this port is valid or invalid
- * Syntax:
- * int MoxaPortIsValid(int port);
- * int port : port number (0 - 127, ref port description)
- *
- * return: 0 : this port is invalid
- * 1 : this port is valid
- *
- *
* Function 6: Enable this port to start Tx/Rx data.
* Syntax:
* void MoxaPortEnable(int port);
@@ -2000,14 +2013,6 @@ int MoxaPortsOfCard(int cardno)
* send out a about 250 ms BREAK signal.
*
*/
-static int MoxaPortIsValid(int port)
-{
- if (moxaCard == 0)
- return (0);
- if (moxa_ports[port].chkPort == 0)
- return (0);
- return (1);
-}
static void MoxaPortEnable(struct moxa_port *port)
{
@@ -2081,8 +2086,6 @@ static int MoxaPortSetTermio(struct moxa_port *port, struct ktermios *termio,
tcflag_t cflag;
tcflag_t mode = 0;
- if (port->chkPort == 0 || termio == 0)
- return (-1);
ofsAddr = port->tableAddr;
cflag = termio->c_cflag; /* termio->c_cflag */
@@ -2135,8 +2138,6 @@ static int MoxaPortGetLineOut(struct moxa_port *port, int *dtrState,
int *rtsState)
{
- if (!MoxaPortIsValid(port->tty->index))
- return (-1);
if (dtrState)
*dtrState = !!(port->lineCtrl & DTR_ON);
if (rtsState)
@@ -2205,8 +2206,6 @@ static int MoxaPortDCDChange(struct moxa_port *port)
{
int n;
- if (port->chkPort == 0)
- return (0);
n = port->DCDState;
port->DCDState &= ~DCD_changed;
n &= DCD_changed;
@@ -2217,8 +2216,6 @@ static int MoxaPortDCDON(struct moxa_port *port)
{
int n;
- if (port->chkPort == 0)
- return (0);
if (port->DCDState & DCD_oldstate)
n = 1;
else