Commit 94e5a9e0 authored by Krzysztof Halasa's avatar Krzysztof Halasa Committed by Jeff Garzik

A bunch of HDLC (WAN driver) bug fixes, plus much improves

device and protocol attach/detach support.

Overall, this is in preparation for update of HDLC API
parent ac51726a
/* /*
* Moxa C101 synchronous serial card driver for Linux * Moxa C101 synchronous serial card driver for Linux
* *
* Copyright (C) 2000-2001 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 * 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 * under the terms of the GNU General Public License as published by
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
#include "hd64570.h" #include "hd64570.h"
static const char* version = "Moxa C101 driver version: 1.09"; static const char* version = "Moxa C101 driver version: 1.10";
static const char* devname = "C101"; static const char* devname = "C101";
#define C101_PAGE 0x1D00 #define C101_PAGE 0x1D00
...@@ -107,18 +107,13 @@ static inline void openwin(card_t *card, u8 page) ...@@ -107,18 +107,13 @@ static inline void openwin(card_t *card, u8 page)
#include "hd6457x.c" #include "hd6457x.c"
static int c101_set_iface(port_t *port) static void c101_set_iface(port_t *port)
{ {
u8 msci = get_msci(port); u8 msci = get_msci(port);
u8 rxs = port->rxs & CLK_BRG_MASK; u8 rxs = port->rxs & CLK_BRG_MASK;
u8 txs = port->txs & CLK_BRG_MASK; u8 txs = port->txs & CLK_BRG_MASK;
switch(port->settings.clock_type) { switch(port->settings.clock_type) {
case CLOCK_EXT:
rxs |= CLK_LINE_RX; /* RXC input */
txs |= CLK_LINE_TX; /* TXC input */
break;
case CLOCK_INT: case CLOCK_INT:
rxs |= CLK_BRG_RX; /* TX clock */ rxs |= CLK_BRG_RX; /* TX clock */
txs |= CLK_RXCLK_TX; /* BRG output */ txs |= CLK_RXCLK_TX; /* BRG output */
...@@ -134,8 +129,9 @@ static int c101_set_iface(port_t *port) ...@@ -134,8 +129,9 @@ static int c101_set_iface(port_t *port)
txs |= CLK_RXCLK_TX; /* RX clock */ txs |= CLK_RXCLK_TX; /* RX clock */
break; break;
default: default: /* EXTernal clock */
return -EINVAL; rxs |= CLK_LINE_RX; /* RXC input */
txs |= CLK_LINE_TX; /* TXC input */
} }
port->rxs = rxs; port->rxs = rxs;
...@@ -143,7 +139,6 @@ static int c101_set_iface(port_t *port) ...@@ -143,7 +139,6 @@ static int c101_set_iface(port_t *port)
sca_out(rxs, msci + RXS, port); sca_out(rxs, msci + RXS, port);
sca_out(txs, msci + TXS, port); sca_out(txs, msci + TXS, port);
sca_set_port(port); sca_set_port(port);
return 0;
} }
...@@ -159,7 +154,8 @@ static int c101_open(struct net_device *dev) ...@@ -159,7 +154,8 @@ static int c101_open(struct net_device *dev)
writeb(1, port->win0base + C101_DTR); writeb(1, port->win0base + C101_DTR);
sca_out(0, MSCI1_OFFSET + CTL, port); /* RTS uses ch#2 output */ sca_out(0, MSCI1_OFFSET + CTL, port); /* RTS uses ch#2 output */
sca_open(hdlc); sca_open(hdlc);
return c101_set_iface(port); c101_set_iface(port);
return 0;
} }
...@@ -181,6 +177,7 @@ static int c101_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ...@@ -181,6 +177,7 @@ static int c101_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{ {
union line_settings *line = &ifr->ifr_settings->ifs_line; union line_settings *line = &ifr->ifr_settings->ifs_line;
const size_t size = sizeof(sync_serial_settings); const size_t size = sizeof(sync_serial_settings);
sync_serial_settings new_line;
hdlc_device *hdlc = dev_to_hdlc(dev); hdlc_device *hdlc = dev_to_hdlc(dev);
port_t *port = hdlc_to_port(hdlc); port_t *port = hdlc_to_port(hdlc);
...@@ -204,10 +201,21 @@ static int c101_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ...@@ -204,10 +201,21 @@ static int c101_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
if(!capable(CAP_NET_ADMIN)) if(!capable(CAP_NET_ADMIN))
return -EPERM; return -EPERM;
if (copy_from_user(&port->settings, &line->sync, size)) if (copy_from_user(&new_line, &line->sync, size))
return -EFAULT; return -EFAULT;
/* FIXME - put sanity checks here */
return c101_set_iface(port); 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 */
if (new_line.loopback != 0 && new_line.loopback != 1)
return -EINVAL;
memcpy(&port->settings, &new_line, size); /* Update settings */
c101_set_iface(port);
return 0;
default: default:
return hdlc_ioctl(dev, ifr, cmd); return hdlc_ioctl(dev, ifr, cmd);
......
...@@ -291,9 +291,9 @@ static inline void sca_rx(card_t *card, port_t *port, pkt_desc *desc, u8 rxin) ...@@ -291,9 +291,9 @@ static inline void sca_rx(card_t *card, port_t *port, pkt_desc *desc, u8 rxin)
#endif #endif
port->hdlc.stats.rx_packets++; port->hdlc.stats.rx_packets++;
port->hdlc.stats.rx_bytes += skb->len; port->hdlc.stats.rx_bytes += skb->len;
skb->dev->last_rx = jiffies;
skb->mac.raw = skb->data; skb->mac.raw = skb->data;
skb->dev = hdlc_to_dev(&port->hdlc); skb->dev = hdlc_to_dev(&port->hdlc);
skb->dev->last_rx = jiffies;
skb->protocol = htons(ETH_P_HDLC); skb->protocol = htons(ETH_P_HDLC);
netif_rx(skb); netif_rx(skb);
} }
......
...@@ -249,6 +249,7 @@ int hdlc_cisco_ioctl(hdlc_device *hdlc, struct ifreq *ifr) ...@@ -249,6 +249,7 @@ int hdlc_cisco_ioctl(hdlc_device *hdlc, struct ifreq *ifr)
{ {
cisco_proto *cisco_s = &ifr->ifr_settings->ifs_hdlc.cisco; cisco_proto *cisco_s = &ifr->ifr_settings->ifs_hdlc.cisco;
const size_t size = sizeof(cisco_proto); const size_t size = sizeof(cisco_proto);
cisco_proto new_settings;
struct net_device *dev = hdlc_to_dev(hdlc); struct net_device *dev = hdlc_to_dev(hdlc);
int result; int result;
...@@ -266,17 +267,20 @@ int hdlc_cisco_ioctl(hdlc_device *hdlc, struct ifreq *ifr) ...@@ -266,17 +267,20 @@ int hdlc_cisco_ioctl(hdlc_device *hdlc, struct ifreq *ifr)
if(dev->flags & IFF_UP) if(dev->flags & IFF_UP)
return -EBUSY; return -EBUSY;
if (copy_from_user(&hdlc->state.cisco.settings, cisco_s, size)) if (copy_from_user(&new_settings, cisco_s, size))
return -EFAULT; return -EFAULT;
/* FIXME - put sanity checks here */ if (new_settings.interval < 1 ||
hdlc_detach(hdlc); new_settings.timeout < 2)
return -EINVAL;
result=hdlc->attach(hdlc, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); result=hdlc->attach(hdlc, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
if (result) {
hdlc->proto = -1; if (result)
return result; return result;
}
hdlc_proto_detach(hdlc);
memcpy(&hdlc->state.cisco.settings, &new_settings, size);
hdlc->open = cisco_open; hdlc->open = cisco_open;
hdlc->stop = cisco_close; hdlc->stop = cisco_close;
......
...@@ -602,13 +602,15 @@ static void fr_rx(struct sk_buff *skb) ...@@ -602,13 +602,15 @@ static void fr_rx(struct sk_buff *skb)
} }
if (data[3] == FR_PAD && data[4] == NLPID_SNAP && data[5] == FR_PAD) { if (data[3] == FR_PAD && data[4] == NLPID_SNAP && data[5] == FR_PAD) {
u16 oui = ntohl(*(u16*)(data + 6)); u16 oui = ntohs(*(u16*)(data + 6));
u16 pid = ntohl(*(u16*)(data + 8)); u16 pid = ntohs(*(u16*)(data + 8));
skb_pull(skb, 10); skb_pull(skb, 10);
switch ((((u32)oui) << 16) | pid) { switch ((((u32)oui) << 16) | pid) {
case ETH_P_ARP: /* routed frame with SNAP */ case ETH_P_ARP: /* routed frame with SNAP */
case ETH_P_IPX: case ETH_P_IPX:
case ETH_P_IP: /* a long variant */
case ETH_P_IPV6:
skb->protocol = htons(pid); skb->protocol = htons(pid);
break; break;
...@@ -762,7 +764,7 @@ static void fr_destroy(hdlc_device *hdlc) ...@@ -762,7 +764,7 @@ static void fr_destroy(hdlc_device *hdlc)
pvc_device *pvc = hdlc->state.fr.first_pvc; pvc_device *pvc = hdlc->state.fr.first_pvc;
while(pvc) { while(pvc) {
pvc_device *next = pvc->next; pvc_device *next = pvc->next;
unregister_netdevice(&pvc->netdev); unregister_netdev(&pvc->netdev);
kfree(pvc); kfree(pvc);
pvc = next; pvc = next;
} }
...@@ -778,6 +780,7 @@ int hdlc_fr_ioctl(hdlc_device *hdlc, struct ifreq *ifr) ...@@ -778,6 +780,7 @@ int hdlc_fr_ioctl(hdlc_device *hdlc, struct ifreq *ifr)
{ {
fr_proto *fr_s = &ifr->ifr_settings->ifs_hdlc.fr; fr_proto *fr_s = &ifr->ifr_settings->ifs_hdlc.fr;
const size_t size = sizeof(fr_proto); const size_t size = sizeof(fr_proto);
fr_proto new_settings;
struct net_device *dev = hdlc_to_dev(hdlc); struct net_device *dev = hdlc_to_dev(hdlc);
fr_proto_pvc pvc; fr_proto_pvc pvc;
int result; int result;
...@@ -796,26 +799,40 @@ int hdlc_fr_ioctl(hdlc_device *hdlc, struct ifreq *ifr) ...@@ -796,26 +799,40 @@ int hdlc_fr_ioctl(hdlc_device *hdlc, struct ifreq *ifr)
if(dev->flags & IFF_UP) if(dev->flags & IFF_UP)
return -EBUSY; return -EBUSY;
if (copy_from_user(&hdlc->state.fr.settings, fr_s, size)) if (copy_from_user(&new_settings, fr_s, size))
return -EFAULT; return -EFAULT;
/* FIXME - put sanity checks here */ if (new_settings.lmi == LMI_DEFAULT)
if (hdlc->proto != IF_PROTO_FR) { new_settings.lmi = LMI_ANSI;
hdlc_detach(hdlc);
hdlc->state.fr.first_pvc = NULL; if ((new_settings.lmi != LMI_NONE &&
hdlc->state.fr.pvc_count = 0; new_settings.lmi != LMI_ANSI &&
} new_settings.lmi != LMI_CCITT) ||
new_settings.t391 < 1 ||
new_settings.t392 < 2 ||
new_settings.n391 < 1 ||
new_settings.n392 < 1 ||
new_settings.n393 < new_settings.n392 ||
new_settings.n393 > 32 ||
(new_settings.dce != 0 &&
new_settings.dce != 1))
return -EINVAL;
result=hdlc->attach(hdlc, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); result=hdlc->attach(hdlc, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
if (result) { if (result)
hdlc->proto = -1;
return result; return result;
if (hdlc->proto != IF_PROTO_FR) {
hdlc_proto_detach(hdlc);
hdlc->state.fr.first_pvc = NULL;
hdlc->state.fr.pvc_count = 0;
} }
memcpy(&hdlc->state.fr.settings, &new_settings, size);
hdlc->open = fr_open; hdlc->open = fr_open;
hdlc->stop = fr_close; hdlc->stop = fr_close;
hdlc->netif_rx = fr_rx; hdlc->netif_rx = fr_rx;
hdlc->detach = fr_destroy; hdlc->proto_detach = fr_destroy;
hdlc->proto = IF_PROTO_FR; hdlc->proto = IF_PROTO_FR;
dev->hard_start_xmit = hdlc->xmit; dev->hard_start_xmit = hdlc->xmit;
dev->hard_header = fr_hard_header; dev->hard_header = fr_hard_header;
......
...@@ -38,7 +38,7 @@ ...@@ -38,7 +38,7 @@
#include <linux/hdlc.h> #include <linux/hdlc.h>
static const char* version = "HDLC support module revision 1.08"; static const char* version = "HDLC support module revision 1.10";
static int hdlc_change_mtu(struct net_device *dev, int new_mtu) static int hdlc_change_mtu(struct net_device *dev, int new_mtu)
...@@ -66,6 +66,26 @@ static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev, ...@@ -66,6 +66,26 @@ static int hdlc_rcv(struct sk_buff *skb, struct net_device *dev,
} }
#ifndef CONFIG_HDLC_RAW
#define hdlc_raw_ioctl(hdlc, ifr) -ENOSYS
#endif
#ifndef CONFIG_HDLC_PPP
#define hdlc_ppp_ioctl(hdlc, ifr) -ENOSYS
#endif
#ifndef CONFIG_HDLC_CISCO
#define hdlc_cisco_ioctl(hdlc, ifr) -ENOSYS
#endif
#ifndef CONFIG_HDLC_FR
#define hdlc_fr_ioctl(hdlc, ifr) -ENOSYS
#endif
#ifndef CONFIG_HDLC_X25
#define hdlc_x25_ioctl(hdlc, ifr) -ENOSYS
#endif
int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{ {
...@@ -89,22 +109,12 @@ int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ...@@ -89,22 +109,12 @@ int hdlc_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
} }
switch(proto) { switch(proto) {
#ifdef CONFIG_HDLC_RAW
case IF_PROTO_HDLC: return hdlc_raw_ioctl(hdlc, ifr); case IF_PROTO_HDLC: return hdlc_raw_ioctl(hdlc, ifr);
#endif
#ifdef CONFIG_HDLC_PPP
case IF_PROTO_PPP: return hdlc_ppp_ioctl(hdlc, ifr); case IF_PROTO_PPP: return hdlc_ppp_ioctl(hdlc, ifr);
#endif
#ifdef CONFIG_HDLC_CISCO
case IF_PROTO_CISCO: return hdlc_cisco_ioctl(hdlc, ifr); case IF_PROTO_CISCO: return hdlc_cisco_ioctl(hdlc, ifr);
#endif
#ifdef CONFIG_HDLC_FR
case IF_PROTO_FR: return hdlc_fr_ioctl(hdlc, ifr); case IF_PROTO_FR: return hdlc_fr_ioctl(hdlc, ifr);
#endif
#ifdef CONFIG_HDLC_X25
case IF_PROTO_X25: return hdlc_x25_ioctl(hdlc, ifr); case IF_PROTO_X25: return hdlc_x25_ioctl(hdlc, ifr);
#endif default: return -EINVAL;
default: return -ENOSYS;
} }
} }
...@@ -125,7 +135,7 @@ int register_hdlc_device(hdlc_device *hdlc) ...@@ -125,7 +135,7 @@ int register_hdlc_device(hdlc_device *hdlc)
dev->flags = IFF_POINTOPOINT | IFF_NOARP; dev->flags = IFF_POINTOPOINT | IFF_NOARP;
hdlc->proto = -1; hdlc->proto = -1;
hdlc->detach = NULL; hdlc->proto_detach = NULL;
result = dev_alloc_name(dev, "hdlc%d"); result = dev_alloc_name(dev, "hdlc%d");
if (result<0) if (result<0)
...@@ -143,7 +153,7 @@ int register_hdlc_device(hdlc_device *hdlc) ...@@ -143,7 +153,7 @@ int register_hdlc_device(hdlc_device *hdlc)
void unregister_hdlc_device(hdlc_device *hdlc) void unregister_hdlc_device(hdlc_device *hdlc)
{ {
hdlc_detach(hdlc); hdlc_proto_detach(hdlc);
unregister_netdev(hdlc_to_dev(hdlc)); unregister_netdev(hdlc_to_dev(hdlc));
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
......
...@@ -96,13 +96,11 @@ int hdlc_ppp_ioctl(hdlc_device *hdlc, struct ifreq *ifr) ...@@ -96,13 +96,11 @@ int hdlc_ppp_ioctl(hdlc_device *hdlc, struct ifreq *ifr)
/* no settable parameters */ /* no settable parameters */
hdlc_detach(hdlc);
result=hdlc->attach(hdlc, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); result=hdlc->attach(hdlc, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
if (result) { if (result)
hdlc->proto = -1;
return result; return result;
}
hdlc_proto_detach(hdlc);
hdlc->open = ppp_open; hdlc->open = ppp_open;
hdlc->stop = ppp_close; hdlc->stop = ppp_close;
......
...@@ -39,35 +39,40 @@ int hdlc_raw_ioctl(hdlc_device *hdlc, struct ifreq *ifr) ...@@ -39,35 +39,40 @@ int hdlc_raw_ioctl(hdlc_device *hdlc, struct ifreq *ifr)
{ {
raw_hdlc_proto *raw_s = &ifr->ifr_settings->ifs_hdlc.raw_hdlc; raw_hdlc_proto *raw_s = &ifr->ifr_settings->ifs_hdlc.raw_hdlc;
const size_t size = sizeof(raw_hdlc_proto); const size_t size = sizeof(raw_hdlc_proto);
raw_hdlc_proto new_settings;
struct net_device *dev = hdlc_to_dev(hdlc); struct net_device *dev = hdlc_to_dev(hdlc);
int result; int result;
switch (ifr->ifr_settings->type) { switch (ifr->ifr_settings->type) {
case IF_GET_PROTO: case IF_GET_PROTO:
ifr->ifr_settings->type = IF_PROTO_HDLC;
if (copy_to_user(raw_s, &hdlc->state.raw_hdlc.settings, size)) if (copy_to_user(raw_s, &hdlc->state.raw_hdlc.settings, size))
return -EFAULT; return -EFAULT;
return 0; return 0;
case IF_PROTO_HDLC: case IF_PROTO_HDLC:
if(!capable(CAP_NET_ADMIN)) if (!capable(CAP_NET_ADMIN))
return -EPERM; return -EPERM;
if(dev->flags & IFF_UP) if (dev->flags & IFF_UP)
return -EBUSY; return -EBUSY;
if (copy_from_user(&hdlc->state.raw_hdlc.settings, raw_s, size)) if (copy_from_user(&new_settings, raw_s, size))
return -EFAULT; return -EFAULT;
if (new_settings.encoding == ENCODING_DEFAULT)
new_settings.encoding = ENCODING_NRZ;
/* FIXME - put sanity checks here */ if (new_settings.parity == PARITY_DEFAULT)
hdlc_detach(hdlc); new_settings.parity = PARITY_NONE;
result=hdlc->attach(hdlc, hdlc->state.raw_hdlc.settings.encoding, result = hdlc->attach(hdlc, new_settings.encoding,
hdlc->state.raw_hdlc.settings.parity); new_settings.parity);
if (result) { if (result)
hdlc->proto = -1;
return result; return result;
}
hdlc_proto_detach(hdlc);
memcpy(&hdlc->state.raw_hdlc.settings, &new_settings, size);
hdlc->open = NULL; hdlc->open = NULL;
hdlc->stop = NULL; hdlc->stop = NULL;
......
...@@ -196,13 +196,11 @@ int hdlc_x25_ioctl(hdlc_device *hdlc, struct ifreq *ifr) ...@@ -196,13 +196,11 @@ int hdlc_x25_ioctl(hdlc_device *hdlc, struct ifreq *ifr)
if(dev->flags & IFF_UP) if(dev->flags & IFF_UP)
return -EBUSY; return -EBUSY;
hdlc_detach(hdlc);
result=hdlc->attach(hdlc, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT); result=hdlc->attach(hdlc, ENCODING_NRZ,PARITY_CRC16_PR1_CCITT);
if (result) { if (result)
hdlc->proto = -1;
return result; return result;
}
hdlc_proto_detach(hdlc);
hdlc->open = x25_open; hdlc->open = x25_open;
hdlc->stop = x25_close; hdlc->stop = x25_close;
......
/* /*
* SDL Inc. RISCom/N2 synchronous serial card driver for Linux * SDL Inc. RISCom/N2 synchronous serial card driver for Linux
* *
* Copyright (C) 1998-2001 Krzysztof Halasa <khc@pm.waw.pl> * Copyright (C) 1998-2002 Krzysztof Halasa <khc@pm.waw.pl>
* *
* This program is free software; you can redistribute it and/or modify it * 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 * under the terms of the GNU General Public License as published by
...@@ -35,7 +35,7 @@ ...@@ -35,7 +35,7 @@
#include "hd64570.h" #include "hd64570.h"
static const char* version = "SDL RISCom/N2 driver version: 1.09"; static const char* version = "SDL RISCom/N2 driver version: 1.10";
static const char* devname = "RISCom/N2"; static const char* devname = "RISCom/N2";
#define USE_WINDOWSIZE 16384 #define USE_WINDOWSIZE 16384
...@@ -159,7 +159,7 @@ static __inline__ void close_windows(card_t *card) ...@@ -159,7 +159,7 @@ static __inline__ void close_windows(card_t *card)
static int n2_set_iface(port_t *port) static void n2_set_iface(port_t *port)
{ {
card_t *card = port->card; card_t *card = port->card;
int io = card->io; int io = card->io;
...@@ -169,12 +169,6 @@ static int n2_set_iface(port_t *port) ...@@ -169,12 +169,6 @@ static int n2_set_iface(port_t *port)
u8 txs = port->txs & CLK_BRG_MASK; u8 txs = port->txs & CLK_BRG_MASK;
switch(port->settings.clock_type) { switch(port->settings.clock_type) {
case CLOCK_EXT:
mcr &= port->phy_node ? ~CLOCK_OUT_PORT1 : ~CLOCK_OUT_PORT0;
rxs |= CLK_LINE_RX; /* RXC input */
txs |= CLK_LINE_TX; /* TXC input */
break;
case CLOCK_INT: case CLOCK_INT:
mcr |= port->phy_node ? CLOCK_OUT_PORT1 : CLOCK_OUT_PORT0; mcr |= port->phy_node ? CLOCK_OUT_PORT1 : CLOCK_OUT_PORT0;
rxs |= CLK_BRG_RX; /* BRG output */ rxs |= CLK_BRG_RX; /* BRG output */
...@@ -193,8 +187,10 @@ static int n2_set_iface(port_t *port) ...@@ -193,8 +187,10 @@ static int n2_set_iface(port_t *port)
txs |= CLK_RXCLK_TX; /* RX clock */ txs |= CLK_RXCLK_TX; /* RX clock */
break; break;
default: default: /* Clock EXTernal */
return -EINVAL; mcr &= port->phy_node ? ~CLOCK_OUT_PORT1 : ~CLOCK_OUT_PORT0;
rxs |= CLK_LINE_RX; /* RXC input */
txs |= CLK_LINE_TX; /* TXC input */
} }
outb(mcr, io + N2_MCR); outb(mcr, io + N2_MCR);
...@@ -203,7 +199,6 @@ static int n2_set_iface(port_t *port) ...@@ -203,7 +199,6 @@ static int n2_set_iface(port_t *port)
sca_out(rxs, msci + RXS, card); sca_out(rxs, msci + RXS, card);
sca_out(txs, msci + TXS, card); sca_out(txs, msci + TXS, card);
sca_set_port(port); sca_set_port(port);
return 0;
} }
...@@ -226,7 +221,8 @@ static int n2_open(struct net_device *dev) ...@@ -226,7 +221,8 @@ static int n2_open(struct net_device *dev)
outb(inb(io + N2_PCR) | PCR_ENWIN, io + N2_PCR); /* open window */ outb(inb(io + N2_PCR) | PCR_ENWIN, io + N2_PCR); /* open window */
outb(inb(io + N2_PSR) | PSR_DMAEN, io + N2_PSR); /* enable dma */ outb(inb(io + N2_PSR) | PSR_DMAEN, io + N2_PSR); /* enable dma */
sca_open(hdlc); sca_open(hdlc);
return n2_set_iface(port); n2_set_iface(port);
return 0;
} }
...@@ -252,6 +248,7 @@ static int n2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ...@@ -252,6 +248,7 @@ static int n2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
{ {
union line_settings *line = &ifr->ifr_settings->ifs_line; union line_settings *line = &ifr->ifr_settings->ifs_line;
const size_t size = sizeof(sync_serial_settings); const size_t size = sizeof(sync_serial_settings);
sync_serial_settings new_line;
hdlc_device *hdlc = dev_to_hdlc(dev); hdlc_device *hdlc = dev_to_hdlc(dev);
port_t *port = hdlc_to_port(hdlc); port_t *port = hdlc_to_port(hdlc);
...@@ -275,10 +272,21 @@ static int n2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) ...@@ -275,10 +272,21 @@ static int n2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
if(!capable(CAP_NET_ADMIN)) if(!capable(CAP_NET_ADMIN))
return -EPERM; return -EPERM;
if (copy_from_user(&port->settings, &line->sync, size)) if (copy_from_user(&new_line, &line->sync, size))
return -EFAULT; return -EFAULT;
/* FIXME - put sanity checks here */
return n2_set_iface(port); 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 */
if (new_line.loopback != 0 && new_line.loopback != 1)
return -EINVAL;
memcpy(&port->settings, &new_line, size); /* Update settings */
n2_set_iface(port);
return 0;
default: default:
return hdlc_ioctl(dev, ifr, cmd); return hdlc_ioctl(dev, ifr, cmd);
......
...@@ -12,14 +12,16 @@ ...@@ -12,14 +12,16 @@
#ifndef __HDLC_H #ifndef __HDLC_H
#define __HDLC_H #define __HDLC_H
#define CLOCK_DEFAULT 0 /* Default (current) setting */ #define GENERIC_HDLC_VERSION 3 /* For synchronization with sethdlc utility */
#define CLOCK_DEFAULT 0 /* Default setting */
#define CLOCK_EXT 1 /* External TX and RX clock - DTE */ #define CLOCK_EXT 1 /* External TX and RX clock - DTE */
#define CLOCK_INT 2 /* Internal TX and RX clock - DCE */ #define CLOCK_INT 2 /* Internal TX and RX clock - DCE */
#define CLOCK_TXINT 3 /* Internal TX and external RX clock */ #define CLOCK_TXINT 3 /* Internal TX and external RX clock */
#define CLOCK_TXFROMRX 4 /* TX clock derived from external RX clock */ #define CLOCK_TXFROMRX 4 /* TX clock derived from external RX clock */
#define ENCODING_DEFAULT 0 /* Default (current) setting */ #define ENCODING_DEFAULT 0 /* Default setting */
#define ENCODING_NRZ 1 #define ENCODING_NRZ 1
#define ENCODING_NRZI 2 #define ENCODING_NRZI 2
#define ENCODING_FM_MARK 3 #define ENCODING_FM_MARK 3
...@@ -27,7 +29,7 @@ ...@@ -27,7 +29,7 @@
#define ENCODING_MANCHESTER 5 #define ENCODING_MANCHESTER 5
#define PARITY_DEFAULT 0 /* Default (current) setting */ #define PARITY_DEFAULT 0 /* Default setting */
#define PARITY_NONE 1 /* No parity */ #define PARITY_NONE 1 /* No parity */
#define PARITY_CRC16_PR0 2 /* CRC16, initial value 0x0000 */ #define PARITY_CRC16_PR0 2 /* CRC16, initial value 0x0000 */
#define PARITY_CRC16_PR1 3 /* CRC16, initial value 0xFFFF */ #define PARITY_CRC16_PR1 3 /* CRC16, initial value 0xFFFF */
...@@ -36,13 +38,11 @@ ...@@ -36,13 +38,11 @@
#define PARITY_CRC32_PR0_CCITT 6 /* CRC32, initial value 0x00000000 */ #define PARITY_CRC32_PR0_CCITT 6 /* CRC32, initial value 0x00000000 */
#define PARITY_CRC32_PR1_CCITT 7 /* CRC32, initial value 0xFFFFFFFF */ #define PARITY_CRC32_PR1_CCITT 7 /* CRC32, initial value 0xFFFFFFFF */
#define LMI_DEFAULT 0 /* Default (current) setting */ #define LMI_DEFAULT 0 /* Default setting */
#define LMI_NONE 1 /* No LMI, all PVCs are static */ #define LMI_NONE 1 /* No LMI, all PVCs are static */
#define LMI_ANSI 2 /* ANSI Annex D */ #define LMI_ANSI 2 /* ANSI Annex D */
#define LMI_CCITT 3 /* ITU-T Annex A */ #define LMI_CCITT 3 /* ITU-T Annex A */
/* PPP doesn't need any info now - supply length = 0 to ioctl */
#ifdef __KERNEL__ #ifdef __KERNEL__
...@@ -178,7 +178,7 @@ typedef struct hdlc_device_struct { ...@@ -178,7 +178,7 @@ typedef struct hdlc_device_struct {
int (*ioctl)(struct net_device *dev, struct ifreq *ifr, int cmd); int (*ioctl)(struct net_device *dev, struct ifreq *ifr, int cmd);
int (*open)(struct hdlc_device_struct *hdlc); int (*open)(struct hdlc_device_struct *hdlc);
void (*stop)(struct hdlc_device_struct *hdlc); void (*stop)(struct hdlc_device_struct *hdlc);
void (*detach)(struct hdlc_device_struct *hdlc); void (*proto_detach)(struct hdlc_device_struct *hdlc);
void (*netif_rx)(struct sk_buff *skb); void (*netif_rx)(struct sk_buff *skb);
int proto; /* IF_PROTO_HDLC/CISCO/FR/etc. */ int proto; /* IF_PROTO_HDLC/CISCO/FR/etc. */
...@@ -337,11 +337,11 @@ static __inline__ void hdlc_close(hdlc_device *hdlc) ...@@ -337,11 +337,11 @@ static __inline__ void hdlc_close(hdlc_device *hdlc)
/* May be used by hardware driver to gain control over HDLC device */ /* May be used by hardware driver to gain control over HDLC device */
static __inline__ void hdlc_detach(hdlc_device *hdlc) static __inline__ void hdlc_proto_detach(hdlc_device *hdlc)
{ {
if (hdlc->detach) if (hdlc->proto_detach)
hdlc->detach(hdlc); hdlc->proto_detach(hdlc);
hdlc->detach = NULL; hdlc->proto_detach = NULL;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment