patch-2.3.25 linux/drivers/net/wan/cycx_x25.c
Next file: linux/drivers/net/wd.c
Previous file: linux/drivers/net/wan/cycx_main.c
Back to the patch index
Back to the overall index
- Lines: 316
- Date:
Sun Oct 31 00:19:22 1999
- Orig file:
v2.3.24/linux/drivers/net/wan/cycx_x25.c
- Orig date:
Fri Oct 15 15:25:13 1999
diff -u --recursive --new-file v2.3.24/linux/drivers/net/wan/cycx_x25.c linux/drivers/net/wan/cycx_x25.c
@@ -1,5 +1,5 @@
/*
-* cycx_x25.c CYCLOM X Multiprotocol WAN Link Driver. X.25 module.
+* cycx_x25.c CYCLOM X WAN Link Driver. X.25 module.
*
* Author: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
* Copyright: (c) 1998, 1999 Arnaldo Carvalho de Melo
@@ -11,6 +11,13 @@
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
* ============================================================================
+* 1999/10/27 acme use ARPHRD_HWX25 so that the x25 stack know
+* that we have a X.25 stack implemented in
+* firmware onboard
+* 1999/10/18 acme support for X.25 sockets in if_send,
+* beware: socket(AF_X25...) IS WORK IN PROGRESS,
+* TCP/IP over X.25 via wanrouter not affected,
+* working.
* 1999/10/09 acme chan_disc renamed to chan_disconnect,
* began adding support for X.25 sockets:
* conf->protocol in new_if
@@ -52,14 +59,14 @@
* memset is put into the unresolved symbols
* instead of using the inline memset functions...
* 1999/01/02 acme began chan_connect, chan_send, x25_send
-* Dec 31, 1998 Arnaldo x25_configure
+* 1998/12/31 acme x25_configure
* this code can be compiled as non module
-* Dec 27, 1998 Arnaldo code cleanup
+* 1998/12/27 acme code cleanup
* IPX code wiped out! let's decrease code
* complexity for now, remember: I'm learning! :)
* bps_to_speed_code OK
-* Dec 26, 1998 Arnaldo Minimal debug code cleanup
-* Aug 08, 1998 Arnaldo Initial version.
+* 1998/12/26 acme Minimal debug code cleanup
+* 1998/08/08 acme Initial version.
*/
#define CYCLOMX_X25_DEBUG 1
@@ -71,7 +78,7 @@
#include <linux/malloc.h> /* kmalloc(), kfree() */
#include <linux/wanrouter.h> /* WAN router definitions */
#include <asm/byteorder.h> /* htons(), etc. */
-#include <linux/if_arp.h> /* ARPHRD_X25 */
+#include <linux/if_arp.h> /* ARPHRD_HWX25 */
#include <linux/cyclomx.h> /* CYCLOM X common user API definitions */
#include <linux/cycx_x25.h> /* X.25 firmware API definitions */
@@ -137,10 +144,11 @@
x25_disconnect_response (cycx_t *card, u8 link, u8 lcn);
/* channel functions */
-int chan_connect (struct net_device *dev),
- chan_send (struct net_device *dev, struct sk_buff *skb);
+static int chan_connect (struct net_device *dev),
+ chan_send (struct net_device *dev, struct sk_buff *skb);
-static void chan_disconnect (struct net_device *dev);
+static void chan_disconnect (struct net_device *dev),
+ chan_x25_send_event(struct net_device *dev, u8 event);
/* Miscellaneous functions */
static void set_chan_state (struct net_device *dev, u8 state),
@@ -288,11 +296,11 @@
card->wandev.interface = conf->interface;
card->wandev.clocking = conf->clocking;
card->wandev.station = conf->station;
- card->isr = &cyx_isr;
+ card->isr = cyx_isr;
card->exec = NULL;
- card->wandev.update = &update;
- card->wandev.new_if = &new_if;
- card->wandev.del_if = &del_if;
+ card->wandev.update = update;
+ card->wandev.new_if = new_if;
+ card->wandev.del_if = del_if;
card->wandev.state = WAN_DISCONNECTED;
return 0;
}
@@ -328,7 +336,7 @@
x25_channel_t *chan;
int err = 0;
- if (conf->name[0] == '\0' || strlen(conf->name) > WAN_IFNAME_SZ) {
+ if (!conf->name[0] || strlen(conf->name) > WAN_IFNAME_SZ) {
printk(KERN_INFO "%s: invalid interface name!\n",card->devname);
return -EINVAL;
}
@@ -403,7 +411,7 @@
/* prepare network device data space for registration */
dev->name = chan->name;
- dev->init = &if_init;
+ dev->init = if_init;
dev->priv = chan;
return 0;
}
@@ -411,11 +419,6 @@
/* Delete logical channel. */
static int del_if (wan_device_t *wandev, struct net_device *dev)
{
- if (!dev) {
- printk(KERN_ERR "cycx_x25:del_if:dev == NULL!\n");
- return 0;
- }
-
if (dev->priv) {
x25_channel_t *chan = dev->priv;
@@ -447,16 +450,16 @@
wan_device_t *wandev = &card->wandev;
/* Initialize device driver entry points */
- dev->open = &if_open;
- dev->stop = &if_close;
- dev->hard_header = &if_header;
- dev->rebuild_header = &if_rebuild_hdr;
- dev->hard_start_xmit = &if_send;
- dev->get_stats = &if_stats;
+ dev->open = if_open;
+ dev->stop = if_close;
+ dev->hard_header = if_header;
+ dev->rebuild_header = if_rebuild_hdr;
+ dev->hard_start_xmit = if_send;
+ dev->get_stats = if_stats;
/* Initialize media-specific parameters */
dev->mtu = X25_CHAN_MTU;
- dev->type = ARPHRD_X25; /* ARP h/w type */
+ dev->type = ARPHRD_HWX25; /* ARP h/w type */
dev->hard_header_len = 0; /* media header length */
dev->addr_len = 0; /* hardware address length */
@@ -577,27 +580,57 @@
"%s: unsupported Ethertype 0x%04X on interface %s!\n",
card->devname, skb->protocol, dev->name);
++chan->ifstats.tx_errors;
- } else switch (chan->state) {
- case WAN_DISCONNECTED:
- if (chan_connect(dev)) {
+ } else if (chan->protocol == ETH_P_IP) {
+ switch (chan->state) {
+ case WAN_DISCONNECTED:
+ if (chan_connect(dev)) {
+ dev->tbusy = 1;
+ return -EBUSY;
+ }
+ /* fall thru */
+ case WAN_CONNECTED:
+ reset_timer(dev);
+ dev->trans_start = jiffies;
dev->tbusy = 1;
- return -EBUSY;
- }
- /* fall thru */
- case WAN_CONNECTED:
- reset_timer(dev);
- dev->trans_start = jiffies;
- dev->tbusy = 1;
- if (chan_send(dev, skb)) {
- return -EBUSY;
- }
- break;
- default:
- ++chan->ifstats.tx_dropped;
- ++card->wandev.stats.tx_dropped;
+ if (chan_send(dev, skb))
+ return -EBUSY;
+
+ break;
+ default:
+ ++chan->ifstats.tx_dropped;
+ ++card->wandev.stats.tx_dropped;
+ }
+ } else { /* chan->protocol == ETH_P_X25 */
+ switch (skb->data[0]) {
+ case 0: break;
+ case 1: /* Connect request */
+ chan_connect(dev);
+ goto free_packet;
+ case 2: /* Disconnect request */
+ chan_disconnect(dev);
+ goto free_packet;
+ default:
+ printk(KERN_INFO
+ "%s: unknown %d x25-iface request on %s!\n",
+ card->devname, skb->data[0], dev->name);
+ ++chan->ifstats.tx_errors;
+ goto free_packet;
+ }
+
+ skb_pull(skb, 1); /* Remove control byte */
+ reset_timer(dev);
+ dev->trans_start = jiffies;
+ dev->tbusy = 1;
+
+ if (chan_send(dev, skb)) {
+ /* prepare for future retransmissions */
+ skb_push(skb, 1);
+ return -EBUSY;
+ }
}
+free_packet:
dev_kfree_skb(skb);
return 0;
}
@@ -733,7 +766,8 @@
/* Allocate new socket buffer */
int bufsize = bitm ? dev->mtu : pktlen;
- if ((skb = dev_alloc_skb(bufsize +
+ if ((skb = dev_alloc_skb((chan->protocol == ETH_P_X25 ? 1 : 0) +
+ bufsize +
dev->hard_header_len)) == NULL) {
printk(KERN_INFO "%s: no socket buffers available!\n",
card->devname);
@@ -742,6 +776,10 @@
return;
}
+ if (chan->protocol == ETH_P_X25) /* X.25 socket layer control */
+ /* 0 = data packet (dev_alloc_skb zeroed skb->data) */
+ skb_put(skb, 1);
+
skb->dev = dev;
skb->protocol = htons(chan->protocol);
chan->rx_skb = skb;
@@ -770,12 +808,11 @@
dev->last_rx = jiffies; /* timestamp */
chan->rx_skb = NULL; /* dequeue packet */
- skb->protocol = htons(chan->protocol);
- skb->dev = dev;
- skb->mac.raw = skb->data;
- netif_rx(skb);
++chan->ifstats.rx_packets;
chan->ifstats.rx_bytes += skb->len;
+
+ skb->mac.raw = skb->data;
+ netif_rx(skb);
}
/* Connect interrupt handler. */
@@ -1236,7 +1273,7 @@
* Return: 0 connected
* >0 connection in progress
* <0 failure */
-int chan_connect (struct net_device *dev)
+static int chan_connect (struct net_device *dev)
{
x25_channel_t *chan = dev->priv;
cycx_t *card = chan->card;
@@ -1307,6 +1344,10 @@
*(u16*)dev->dev_addr = htons(chan->lcn);
dev->tbusy = 0;
reset_timer(dev);
+
+ if (chan->protocol == ETH_P_X25)
+ chan_x25_send_event(dev, 1);
+
break;
case WAN_CONNECTING:
@@ -1329,6 +1370,10 @@
*(unsigned short*)dev->dev_addr = 0;
chan->lcn = 0;
}
+
+ if (chan->protocol == ETH_P_X25)
+ chan_x25_send_event(dev, 2);
+
dev->tbusy = 0;
break;
}
@@ -1352,7 +1397,7 @@
* the packet into 'complete sequence' using M-bit.
* 2. When transmission is complete, an event notification should be issued
* to the router. */
-int chan_send (struct net_device *dev, struct sk_buff *skb)
+static int chan_send (struct net_device *dev, struct sk_buff *skb)
{
x25_channel_t *chan = dev->priv;
cycx_t *card = chan->card;
@@ -1375,6 +1420,29 @@
++chan->ifstats.tx_packets;
chan->ifstats.tx_bytes += len;
return 0;
+}
+
+/* Send event (connection, disconnection, etc) to X.25 socket layer */
+
+static void chan_x25_send_event(struct net_device *dev, u8 event)
+{
+ struct sk_buff *skb;
+ unsigned char *ptr;
+
+ if ((skb = dev_alloc_skb(1)) == NULL) {
+ printk(KERN_ERR __FUNCTION__ ": out of memory\n");
+ return;
+ }
+
+ ptr = skb_put(skb, 1);
+ *ptr = event;
+
+ skb->dev = dev;
+ skb->protocol = htons(ETH_P_X25);
+ skb->mac.raw = skb->data;
+ skb->pkt_type = PACKET_HOST;
+
+ netif_rx(skb);
}
/* Convert line speed in bps to a number used by cyclom 2x code. */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)