patch-2.4.21 linux-2.4.21/drivers/net/wan/c101.c
Next file: linux-2.4.21/drivers/net/wan/comx-hw-mixcom.c
Previous file: linux-2.4.21/drivers/net/wan/Makefile
Back to the patch index
Back to the overall index
- Lines: 258
- Date:
2003-06-13 07:51:35.000000000 -0700
- Orig file:
linux-2.4.20/drivers/net/wan/c101.c
- Orig date:
2001-09-13 16:04:43.000000000 -0700
diff -urN linux-2.4.20/drivers/net/wan/c101.c linux-2.4.21/drivers/net/wan/c101.c
@@ -1,7 +1,7 @@
/*
* Moxa C101 synchronous serial card driver for Linux
*
- * Copyright (C) 2000 Krzysztof Halasa <khc@pm.waw.pl>
+ * Copyright (C) 2000-2002 Krzysztof Halasa <khc@pm.waw.pl>
*
* 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
@@ -15,6 +15,7 @@
* Moxa C101 User's Manual
*/
+#include <linux/config.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
@@ -29,10 +30,8 @@
#include "hd64570.h"
-#define DEBUG_RINGS
-/* #define DEBUG_PKT */
-static const char* version = "Moxa C101 driver revision: 1.02 for Linux 2.4";
+static const char* version = "Moxa C101 driver version: 1.10";
static const char* devname = "C101";
#define C101_PAGE 0x1D00
@@ -51,12 +50,12 @@
typedef struct card_s {
hdlc_device hdlc; /* HDLC device struct - must be first */
spinlock_t lock; /* TX lock */
- int clkmode; /* clock mode */
- int clkrate; /* clock speed */
- int line; /* loopback only */
u8 *win0base; /* ISA window base address */
u32 phy_winbase; /* ISA physical base address */
u16 buff_offset; /* offset of first buffer of first channel */
+ sync_serial_settings settings;
+ unsigned short encoding;
+ unsigned short parity;
u8 rxs, txs, tmc; /* SCA registers */
u8 irq; /* IRQ (3-15) */
u8 ring_buffers; /* number of buffers in a ring */
@@ -72,6 +71,9 @@
typedef card_t port_t;
+static card_t *first_card;
+static card_t **new_card = &first_card;
+
#define sca_in(reg, card) readb((card)->win0base + C101_SCA + (reg))
#define sca_out(value, reg, card) writeb(value, (card)->win0base + C101_SCA + (reg))
@@ -105,18 +107,13 @@
#include "hd6457x.c"
-static int c101_set_clock(port_t *port, int value)
+static void c101_set_iface(port_t *port)
{
u8 msci = get_msci(port);
u8 rxs = port->rxs & CLK_BRG_MASK;
u8 txs = port->txs & CLK_BRG_MASK;
- switch(value) {
- case CLOCK_EXT:
- rxs |= CLK_LINE_RX; /* RXC input */
- txs |= CLK_LINE_TX; /* TXC input */
- break;
-
+ switch(port->settings.clock_type) {
case CLOCK_INT:
rxs |= CLK_BRG_RX; /* TX clock */
txs |= CLK_RXCLK_TX; /* BRG output */
@@ -132,84 +129,100 @@
txs |= CLK_RXCLK_TX; /* RX clock */
break;
- default:
- return -EINVAL;
+ default: /* EXTernal clock */
+ rxs |= CLK_LINE_RX; /* RXC input */
+ txs |= CLK_LINE_TX; /* TXC input */
}
port->rxs = rxs;
port->txs = txs;
sca_out(rxs, msci + RXS, port);
sca_out(txs, msci + TXS, port);
- port->clkmode = value;
- return 0;
+ sca_set_port(port);
}
-static int c101_open(hdlc_device *hdlc)
+static int c101_open(struct net_device *dev)
{
+ hdlc_device *hdlc = dev_to_hdlc(dev);
port_t *port = hdlc_to_port(hdlc);
+ int result = hdlc_open(hdlc);
+ if (result)
+ return result;
MOD_INC_USE_COUNT;
writeb(1, port->win0base + C101_DTR);
sca_out(0, MSCI1_OFFSET + CTL, port); /* RTS uses ch#2 output */
sca_open(hdlc);
- c101_set_clock(port, port->clkmode);
+ c101_set_iface(port);
return 0;
}
-static void c101_close(hdlc_device *hdlc)
+static int c101_close(struct net_device *dev)
{
+ hdlc_device *hdlc = dev_to_hdlc(dev);
port_t *port = hdlc_to_port(hdlc);
sca_close(hdlc);
writeb(0, port->win0base + C101_DTR);
sca_out(CTL_NORTS, MSCI1_OFFSET + CTL, port);
+ hdlc_close(hdlc);
MOD_DEC_USE_COUNT;
+ return 0;
}
-static int c101_ioctl(hdlc_device *hdlc, struct ifreq *ifr, int cmd)
+static int c101_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{
- int value = ifr->ifr_ifru.ifru_ivalue;
- int result = 0;
+ const size_t size = sizeof(sync_serial_settings);
+ sync_serial_settings new_line, *line = ifr->ifr_settings.ifs_ifsu.sync;
+ hdlc_device *hdlc = dev_to_hdlc(dev);
port_t *port = hdlc_to_port(hdlc);
- if(!capable(CAP_NET_ADMIN))
- return -EPERM;
+#ifdef CONFIG_HDLC_DEBUG_RINGS
+ if (cmd == SIOCDEVPRIVATE) {
+ sca_dump_rings(hdlc);
+ return 0;
+ }
+#endif
+ if (cmd != SIOCWANDEV)
+ return hdlc_ioctl(dev, ifr, cmd);
- switch(cmd) {
- case HDLCSCLOCK:
- result = c101_set_clock(port, value);
- case HDLCGCLOCK:
- value = port->clkmode;
- break;
+ switch(ifr->ifr_settings.type) {
+ case IF_GET_IFACE:
+ ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL;
+ if (ifr->ifr_settings.size < size) {
+ ifr->ifr_settings.size = size; /* data size wanted */
+ return -ENOBUFS;
+ }
+ if (copy_to_user(line, &port->settings, size))
+ return -EFAULT;
+ return 0;
- case HDLCSCLOCKRATE:
- port->clkrate = value;
- sca_set_clock(port);
- case HDLCGCLOCKRATE:
- value = port->clkrate;
- break;
+ case IF_IFACE_SYNC_SERIAL:
+ if(!capable(CAP_NET_ADMIN))
+ return -EPERM;
+
+ if (copy_from_user(&new_line, line, size))
+ return -EFAULT;
+
+ if (new_line.clock_type != CLOCK_EXT &&
+ new_line.clock_type != CLOCK_TXFROMRX &&
+ new_line.clock_type != CLOCK_INT &&
+ new_line.clock_type != CLOCK_TXINT)
+ return -EINVAL; /* No such clock setting */
- case HDLCSLINE:
- result = sca_set_loopback(port, value);
- case HDLCGLINE:
- value = port->line;
- break;
+ if (new_line.loopback != 0 && new_line.loopback != 1)
+ return -EINVAL;
-#ifdef DEBUG_RINGS
- case HDLCRUN:
- sca_dump_rings(hdlc);
+ memcpy(&port->settings, &new_line, size); /* Update settings */
+ c101_set_iface(port);
return 0;
-#endif /* DEBUG_RINGS */
default:
- return -EINVAL;
+ return hdlc_ioctl(dev, ifr, cmd);
}
-
- ifr->ifr_ifru.ifru_ivalue = value;
- return result;
}
@@ -231,6 +244,7 @@
static int c101_run(unsigned long irq, unsigned long winbase)
{
+ struct net_device *dev;
card_t *card;
int result;
@@ -284,15 +298,19 @@
sca_init(card, 0);
+ dev = hdlc_to_dev(&card->hdlc);
+
spin_lock_init(&card->lock);
- hdlc_to_dev(&card->hdlc)->irq = irq;
- hdlc_to_dev(&card->hdlc)->mem_start = winbase;
- hdlc_to_dev(&card->hdlc)->mem_end = winbase + C101_MAPPED_RAM_SIZE - 1;
- hdlc_to_dev(&card->hdlc)->tx_queue_len = 50;
- card->hdlc.ioctl = c101_ioctl;
- card->hdlc.open = c101_open;
- card->hdlc.close = c101_close;
+ dev->irq = irq;
+ dev->mem_start = winbase;
+ dev->mem_end = winbase + C101_MAPPED_RAM_SIZE - 1;
+ dev->tx_queue_len = 50;
+ dev->do_ioctl = c101_ioctl;
+ dev->open = c101_open;
+ dev->stop = c101_close;
+ card->hdlc.attach = sca_attach;
card->hdlc.xmit = sca_xmit;
+ card->settings.clock_type = CLOCK_EXT;
result = register_hdlc_device(&card->hdlc);
if (result) {
@@ -319,7 +337,7 @@
return -ENOSYS; /* no parameters specified, abort */
}
- printk(KERN_INFO "%s\n", version);
+ printk(KERN_INFO "%s (SCA-%s)\n", version, sca_version);
do {
unsigned long irq, ram;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)