2 * cycx_x25.c Cyclom 2X WAN Link Driver. X.25 module.
4 * Author: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
6 * Copyright: (c) 1998-2003 Arnaldo Carvalho de Melo
8 * Based on sdla_x25.c by Gene Kozin <genek@compuserve.com>
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version
13 * 2 of the License, or (at your option) any later version.
14 * ============================================================================
15 * 2001/01/12 acme use dev_kfree_skb_irq on interrupt context
16 * 2000/04/02 acme dprintk, cycx_debug
17 * fixed the bug introduced in get_dev_by_lcn and
18 * get_dev_by_dte_addr by the anonymous hacker
19 * that converted this driver to softnet
20 * 2000/01/08 acme cleanup
21 * 1999/10/27 acme use ARPHRD_HWX25 so that the X.25 stack know
22 * that we have a X.25 stack implemented in
24 * 1999/10/18 acme support for X.25 sockets in if_send,
25 * beware: socket(AF_X25...) IS WORK IN PROGRESS,
26 * TCP/IP over X.25 via wanrouter not affected,
28 * 1999/10/09 acme chan_disc renamed to chan_disconnect,
29 * began adding support for X.25 sockets:
30 * conf->protocol in new_if
31 * 1999/10/05 acme fixed return E... to return -E...
32 * 1999/08/10 acme serialized access to the card thru a spinlock
34 * 1999/08/09 acme removed per channel spinlocks
35 * removed references to enable_tx_int
36 * 1999/05/28 acme fixed nibble_to_byte, ackvc now properly treated
38 * 1999/05/25 acme fixed t1, t2, t21 & t23 configuration
39 * use spinlocks instead of cli/sti in some points
40 * 1999/05/24 acme finished the x25_get_stat function
41 * 1999/05/23 acme dev->type = ARPHRD_X25 (tcpdump only works,
42 * AFAIT, with ARPHRD_ETHER). This seems to be
43 * needed to use socket(AF_X25)...
44 * Now the config file must specify a peer media
45 * address for svc channels over a crossover cable.
46 * Removed hold_timeout from x25_channel_t,
48 * A little enhancement in the DEBUG processing
49 * 1999/05/22 acme go to DISCONNECTED in disconnect_confirm_intr,
50 * instead of chan_disc.
51 * 1999/05/16 marcelo fixed timer initialization in SVCs
52 * 1999/01/05 acme x25_configure now get (most of) all
54 * 1999/01/05 acme pktlen now (correctly) uses log2 (value
56 * 1999/01/03 acme judicious use of data types (u8, u16, u32, etc)
57 * 1999/01/03 acme cyx_isr: reset dpmbase to acknowledge
58 * indication (interrupt from cyclom 2x)
59 * 1999/01/02 acme cyx_isr: first hackings...
60 * 1999/01/0203 acme when initializing an array don't give less
61 * elements than declared...
62 * example: char send_cmd[6] = "?\xFF\x10";
63 * you'll gonna lose a couple hours, 'cause your
64 * brain won't admit that there's an error in the
65 * above declaration... the side effect is that
66 * memset is put into the unresolved symbols
67 * instead of using the inline memset functions...
68 * 1999/01/02 acme began chan_connect, chan_send, x25_send
69 * 1998/12/31 acme x25_configure
70 * this code can be compiled as non module
71 * 1998/12/27 acme code cleanup
72 * IPX code wiped out! let's decrease code
73 * complexity for now, remember: I'm learning! :)
74 * bps_to_speed_code OK
75 * 1998/12/26 acme Minimal debug code cleanup
76 * 1998/08/08 acme Initial version.
79 #define CYCLOMX_X25_DEBUG 1
81 #include <linux/ctype.h> /* isdigit() */
82 #include <linux/errno.h> /* return codes */
83 #include <linux/if_arp.h> /* ARPHRD_HWX25 */
84 #include <linux/kernel.h> /* printk(), and other useful stuff */
85 #include <linux/module.h>
86 #include <linux/string.h> /* inline memset(), etc. */
87 #include <linux/slab.h> /* kmalloc(), kfree() */
88 #include <linux/stddef.h> /* offsetof(), etc. */
89 #include <linux/wanrouter.h> /* WAN router definitions */
91 #include <asm/byteorder.h> /* htons(), etc. */
93 #include <linux/cyclomx.h> /* Cyclom 2X common user API definitions */
94 #include <linux/cycx_x25.h> /* X.25 firmware API definitions */
96 #include <net/x25device.h>
98 /* Defines & Macros */
99 #define CYCX_X25_MAX_CMD_RETRY 5
100 #define CYCX_X25_CHAN_MTU 2048 /* unfragmented logical channel MTU */
102 /* Data Structures */
103 /* This is an extension of the 'struct net_device' we create for each network
104 interface to keep the rest of X.25 channel-specific data. */
105 struct cycx_x25_channel {
106 /* This member must be first. */
107 struct net_device *slave; /* WAN slave */
109 char name[WAN_IFNAME_SZ+1]; /* interface name, ASCIIZ */
110 char addr[WAN_ADDRESS_SZ+1]; /* media address, ASCIIZ */
111 char *local_addr; /* local media address, ASCIIZ -
112 svc thru crossover cable */
113 s16 lcn; /* logical channel number/conn.req.key*/
115 struct timer_list timer; /* timer used for svc channel disc. */
116 u16 protocol; /* ethertype, 0 - multiplexed */
117 u8 svc; /* 0 - permanent, 1 - switched */
118 u8 state; /* channel state */
119 u8 drop_sequence; /* mark sequence for dropping */
120 u32 idle_tmout; /* sec, before disconnecting */
121 struct sk_buff *rx_skb; /* receive socket buffer */
122 struct cycx_device *card; /* -> owner */
123 struct net_device_stats ifstats;/* interface statistics */
126 /* Function Prototypes */
127 /* WAN link driver entry points. These are called by the WAN router module. */
128 static int cycx_wan_update(struct wan_device *wandev),
129 cycx_wan_new_if(struct wan_device *wandev, struct net_device *dev,
131 cycx_wan_del_if(struct wan_device *wandev, struct net_device *dev);
133 /* Network device interface */
134 static int cycx_netdevice_init(struct net_device *dev);
135 static int cycx_netdevice_open(struct net_device *dev);
136 static int cycx_netdevice_stop(struct net_device *dev);
137 static int cycx_netdevice_hard_header(struct sk_buff *skb,
138 struct net_device *dev, u16 type,
139 const void *daddr, const void *saddr,
141 static int cycx_netdevice_rebuild_header(struct sk_buff *skb);
142 static int cycx_netdevice_hard_start_xmit(struct sk_buff *skb,
143 struct net_device *dev);
145 static struct net_device_stats *
146 cycx_netdevice_get_stats(struct net_device *dev);
148 /* Interrupt handlers */
149 static void cycx_x25_irq_handler(struct cycx_device *card),
150 cycx_x25_irq_tx(struct cycx_device *card, struct cycx_x25_cmd *cmd),
151 cycx_x25_irq_rx(struct cycx_device *card, struct cycx_x25_cmd *cmd),
152 cycx_x25_irq_log(struct cycx_device *card,
153 struct cycx_x25_cmd *cmd),
154 cycx_x25_irq_stat(struct cycx_device *card,
155 struct cycx_x25_cmd *cmd),
156 cycx_x25_irq_connect_confirm(struct cycx_device *card,
157 struct cycx_x25_cmd *cmd),
158 cycx_x25_irq_disconnect_confirm(struct cycx_device *card,
159 struct cycx_x25_cmd *cmd),
160 cycx_x25_irq_connect(struct cycx_device *card,
161 struct cycx_x25_cmd *cmd),
162 cycx_x25_irq_disconnect(struct cycx_device *card,
163 struct cycx_x25_cmd *cmd),
164 cycx_x25_irq_spurious(struct cycx_device *card,
165 struct cycx_x25_cmd *cmd);
167 /* X.25 firmware interface functions */
168 static int cycx_x25_configure(struct cycx_device *card,
169 struct cycx_x25_config *conf),
170 cycx_x25_get_stats(struct cycx_device *card),
171 cycx_x25_send(struct cycx_device *card, u8 link, u8 lcn, u8 bitm,
173 cycx_x25_connect_response(struct cycx_device *card,
174 struct cycx_x25_channel *chan),
175 cycx_x25_disconnect_response(struct cycx_device *card, u8 link,
178 /* channel functions */
179 static int cycx_x25_chan_connect(struct net_device *dev),
180 cycx_x25_chan_send(struct net_device *dev, struct sk_buff *skb);
182 static void cycx_x25_chan_disconnect(struct net_device *dev),
183 cycx_x25_chan_send_event(struct net_device *dev, u8 event);
185 /* Miscellaneous functions */
186 static void cycx_x25_set_chan_state(struct net_device *dev, u8 state),
187 cycx_x25_chan_timer(unsigned long d);
189 static void nibble_to_byte(u8 *s, u8 *d, u8 len, u8 nibble),
190 reset_timer(struct net_device *dev);
192 static u8 bps_to_speed_code(u32 bps);
193 static u8 cycx_log2(u32 n);
195 static unsigned dec_to_uint(u8 *str, int len);
197 static struct net_device *cycx_x25_get_dev_by_lcn(struct wan_device *wandev,
199 static struct net_device *
200 cycx_x25_get_dev_by_dte_addr(struct wan_device *wandev, char *dte);
202 #ifdef CYCLOMX_X25_DEBUG
203 static void hex_dump(char *msg, unsigned char *p, int len);
204 static void cycx_x25_dump_config(struct cycx_x25_config *conf);
205 static void cycx_x25_dump_stats(struct cycx_x25_stats *stats);
206 static void cycx_x25_dump_devs(struct wan_device *wandev);
208 #define hex_dump(msg, p, len)
209 #define cycx_x25_dump_config(conf)
210 #define cycx_x25_dump_stats(stats)
211 #define cycx_x25_dump_devs(wandev)
213 /* Public Functions */
215 /* X.25 Protocol Initialization routine.
217 * This routine is called by the main Cyclom 2X module during setup. At this
218 * point adapter is completely initialized and X.25 firmware is running.
219 * o configure adapter
220 * o initialize protocol-specific fields of the adapter data space.
224 int cycx_x25_wan_init(struct cycx_device *card, wandev_conf_t *conf)
226 struct cycx_x25_config cfg;
228 /* Verify configuration ID */
229 if (conf->config_id != WANCONFIG_X25) {
230 printk(KERN_INFO "%s: invalid configuration ID %u!\n",
231 card->devname, conf->config_id);
235 /* Initialize protocol-specific fields */
236 card->mbox = card->hw.dpmbase + X25_MBOX_OFFS;
237 card->u.x.connection_keys = 0;
238 spin_lock_init(&card->u.x.lock);
240 /* Configure adapter. Here we set reasonable defaults, then parse
241 * device configuration structure and set configuration options.
242 * Most configuration options are verified and corrected (if
243 * necessary) since we can't rely on the adapter to do so and don't
244 * want it to fail either. */
245 memset(&cfg, 0, sizeof(cfg));
247 cfg.clock = conf->clocking == WANOPT_EXTERNAL ? 8 : 55;
248 cfg.speed = bps_to_speed_code(conf->bps);
254 cfg.flags = 0x02; /* default = V35 */
255 cfg.t1 = 10; /* line carrier timeout */
256 cfg.t2 = 29; /* tx timeout */
257 cfg.t21 = 180; /* CALL timeout */
258 cfg.t23 = 180; /* CLEAR timeout */
261 if (!conf->mtu || conf->mtu >= 512)
262 card->wandev.mtu = 512;
263 else if (conf->mtu >= 256)
264 card->wandev.mtu = 256;
265 else if (conf->mtu >= 128)
266 card->wandev.mtu = 128;
268 card->wandev.mtu = 64;
270 cfg.pktlen = cycx_log2(card->wandev.mtu);
272 if (conf->station == WANOPT_DTE) {
273 cfg.locaddr = 3; /* DTE */
274 cfg.remaddr = 1; /* DCE */
276 cfg.locaddr = 1; /* DCE */
277 cfg.remaddr = 3; /* DTE */
280 if (conf->interface == WANOPT_RS232)
281 cfg.flags = 0; /* FIXME just reset the 2nd bit */
283 if (conf->u.x25.hi_pvc) {
284 card->u.x.hi_pvc = min_t(unsigned int, conf->u.x25.hi_pvc, 4095);
285 card->u.x.lo_pvc = min_t(unsigned int, conf->u.x25.lo_pvc, card->u.x.hi_pvc);
288 if (conf->u.x25.hi_svc) {
289 card->u.x.hi_svc = min_t(unsigned int, conf->u.x25.hi_svc, 4095);
290 card->u.x.lo_svc = min_t(unsigned int, conf->u.x25.lo_svc, card->u.x.hi_svc);
293 if (card->u.x.lo_pvc == 255)
296 cfg.npvc = card->u.x.hi_pvc - card->u.x.lo_pvc + 1;
298 cfg.nvc = card->u.x.hi_svc - card->u.x.lo_svc + 1 + cfg.npvc;
300 if (conf->u.x25.hdlc_window)
301 cfg.n2win = min_t(unsigned int, conf->u.x25.hdlc_window, 7);
303 if (conf->u.x25.pkt_window)
304 cfg.n3win = min_t(unsigned int, conf->u.x25.pkt_window, 7);
307 cfg.t1 = min_t(unsigned int, conf->u.x25.t1, 30);
310 cfg.t2 = min_t(unsigned int, conf->u.x25.t2, 30);
312 if (conf->u.x25.t11_t21)
313 cfg.t21 = min_t(unsigned int, conf->u.x25.t11_t21, 30);
315 if (conf->u.x25.t13_t23)
316 cfg.t23 = min_t(unsigned int, conf->u.x25.t13_t23, 30);
319 cfg.n2 = min_t(unsigned int, conf->u.x25.n2, 30);
321 /* initialize adapter */
322 if (cycx_x25_configure(card, &cfg))
325 /* Initialize protocol-specific fields of adapter data space */
326 card->wandev.bps = conf->bps;
327 card->wandev.interface = conf->interface;
328 card->wandev.clocking = conf->clocking;
329 card->wandev.station = conf->station;
330 card->isr = cycx_x25_irq_handler;
332 card->wandev.update = cycx_wan_update;
333 card->wandev.new_if = cycx_wan_new_if;
334 card->wandev.del_if = cycx_wan_del_if;
335 card->wandev.state = WAN_DISCONNECTED;
340 /* WAN Device Driver Entry Points */
341 /* Update device status & statistics. */
342 static int cycx_wan_update(struct wan_device *wandev)
345 if (!wandev || !wandev->private)
348 if (wandev->state == WAN_UNCONFIGURED)
351 cycx_x25_get_stats(wandev->private);
356 /* Create new logical channel.
357 * This routine is called by the router when ROUTER_IFNEW IOCTL is being
359 * o parse media- and hardware-specific configuration
360 * o make sure that a new channel can be created
361 * o allocate resources, if necessary
362 * o prepare network device structure for registration.
365 * < 0 failure (channel will not be created) */
366 static int cycx_wan_new_if(struct wan_device *wandev, struct net_device *dev,
369 struct cycx_device *card = wandev->private;
370 struct cycx_x25_channel *chan;
373 if (!conf->name[0] || strlen(conf->name) > WAN_IFNAME_SZ) {
374 printk(KERN_INFO "%s: invalid interface name!\n",
379 /* allocate and initialize private data */
380 chan = kzalloc(sizeof(struct cycx_x25_channel), GFP_KERNEL);
384 strcpy(chan->name, conf->name);
386 chan->link = conf->port;
387 chan->protocol = conf->protocol ? ETH_P_X25 : ETH_P_IP;
389 /* only used in svc connected thru crossover cable */
390 chan->local_addr = NULL;
392 if (conf->addr[0] == '@') { /* SVC */
393 int len = strlen(conf->local_addr);
396 if (len > WAN_ADDRESS_SZ) {
397 printk(KERN_ERR "%s: %s local addr too long!\n",
398 wandev->name, chan->name);
402 chan->local_addr = kmalloc(len + 1, GFP_KERNEL);
404 if (!chan->local_addr) {
410 strncpy(chan->local_addr, conf->local_addr,
415 strncpy(chan->addr, &conf->addr[1], WAN_ADDRESS_SZ);
416 init_timer(&chan->timer);
417 chan->timer.function = cycx_x25_chan_timer;
418 chan->timer.data = (unsigned long)dev;
420 /* Set channel timeouts (default if not specified) */
421 chan->idle_tmout = conf->idle_timeout ? conf->idle_timeout : 90;
422 } else if (isdigit(conf->addr[0])) { /* PVC */
423 s16 lcn = dec_to_uint(conf->addr, 0);
425 if (lcn >= card->u.x.lo_pvc && lcn <= card->u.x.hi_pvc)
429 "%s: PVC %u is out of range on interface %s!\n",
430 wandev->name, lcn, chan->name);
434 printk(KERN_ERR "%s: invalid media address on interface %s!\n",
435 wandev->name, chan->name);
440 kfree(chan->local_addr);
445 /* prepare network device data space for registration */
446 strcpy(dev->name, chan->name);
447 dev->init = cycx_netdevice_init;
453 /* Delete logical channel. */
454 static int cycx_wan_del_if(struct wan_device *wandev, struct net_device *dev)
457 struct cycx_x25_channel *chan = dev->priv;
460 kfree(chan->local_addr);
461 if (chan->state == WAN_CONNECTED)
462 del_timer(&chan->timer);
473 /* Network Device Interface */
475 static const struct header_ops cycx_header_ops = {
476 .create = cycx_netdevice_hard_header,
477 .rebuild = cycx_netdevice_rebuild_header,
480 /* Initialize Linux network interface.
482 * This routine is called only once for each interface, during Linux network
483 * interface registration. Returning anything but zero will fail interface
485 static int cycx_netdevice_init(struct net_device *dev)
487 struct cycx_x25_channel *chan = dev->priv;
488 struct cycx_device *card = chan->card;
489 struct wan_device *wandev = &card->wandev;
491 /* Initialize device driver entry points */
492 dev->open = cycx_netdevice_open;
493 dev->stop = cycx_netdevice_stop;
494 dev->header_ops = &cycx_header_ops;
496 dev->hard_start_xmit = cycx_netdevice_hard_start_xmit;
497 dev->get_stats = cycx_netdevice_get_stats;
499 /* Initialize media-specific parameters */
500 dev->mtu = CYCX_X25_CHAN_MTU;
501 dev->type = ARPHRD_HWX25; /* ARP h/w type */
502 dev->hard_header_len = 0; /* media header length */
503 dev->addr_len = 0; /* hardware address length */
506 *(__be16*)dev->dev_addr = htons(chan->lcn);
508 /* Initialize hardware parameters (just for reference) */
509 dev->irq = wandev->irq;
510 dev->dma = wandev->dma;
511 dev->base_addr = wandev->ioport;
512 dev->mem_start = (unsigned long)wandev->maddr;
513 dev->mem_end = (unsigned long)(wandev->maddr +
515 dev->flags |= IFF_NOARP;
517 /* Set transmit buffer queue length */
518 dev->tx_queue_len = 10;
520 /* Initialize socket buffers */
521 cycx_x25_set_chan_state(dev, WAN_DISCONNECTED);
526 /* Open network interface.
527 * o prevent module from unloading by incrementing use count
528 * o if link is disconnected then initiate connection
530 * Return 0 if O.k. or errno. */
531 static int cycx_netdevice_open(struct net_device *dev)
533 if (netif_running(dev))
534 return -EBUSY; /* only one open is allowed */
536 netif_start_queue(dev);
540 /* Close network interface.
542 * o if there's no more open channels then disconnect physical link. */
543 static int cycx_netdevice_stop(struct net_device *dev)
545 struct cycx_x25_channel *chan = dev->priv;
547 netif_stop_queue(dev);
549 if (chan->state == WAN_CONNECTED || chan->state == WAN_CONNECTING)
550 cycx_x25_chan_disconnect(dev);
555 /* Build media header.
556 * o encapsulate packet according to encapsulation type.
558 * The trick here is to put packet type (Ethertype) into 'protocol' field of
559 * the socket buffer, so that we don't forget it. If encapsulation fails,
560 * set skb->protocol to 0 and discard packet later.
562 * Return: media header length. */
563 static int cycx_netdevice_hard_header(struct sk_buff *skb,
564 struct net_device *dev, u16 type,
565 const void *daddr, const void *saddr,
568 skb->protocol = htons(type);
570 return dev->hard_header_len;
573 /* * Re-build media header.
574 * Return: 1 physical address resolved.
575 * 0 physical address not resolved */
576 static int cycx_netdevice_rebuild_header(struct sk_buff *skb)
581 /* Send a packet on a network interface.
582 * o set busy flag (marks start of the transmission).
583 * o check link state. If link is not up, then drop the packet.
584 * o check channel status. If it's down then initiate a call.
585 * o pass a packet to corresponding WAN device.
586 * o free socket buffer
588 * Return: 0 complete (socket buffer must be freed)
589 * non-0 packet may be re-transmitted (tbusy must be set)
592 * 1. This routine is called either by the protocol stack or by the "net
593 * bottom half" (with interrupts enabled).
594 * 2. Setting tbusy flag will inhibit further transmit requests from the
595 * protocol stack and can be used for flow control with protocol layer. */
596 static int cycx_netdevice_hard_start_xmit(struct sk_buff *skb,
597 struct net_device *dev)
599 struct cycx_x25_channel *chan = dev->priv;
600 struct cycx_device *card = chan->card;
603 chan->protocol = ntohs(skb->protocol);
605 if (card->wandev.state != WAN_CONNECTED)
606 ++chan->ifstats.tx_dropped;
607 else if (chan->svc && chan->protocol &&
608 chan->protocol != ntohs(skb->protocol)) {
610 "%s: unsupported Ethertype 0x%04X on interface %s!\n",
611 card->devname, ntohs(skb->protocol), dev->name);
612 ++chan->ifstats.tx_errors;
613 } else if (chan->protocol == ETH_P_IP) {
614 switch (chan->state) {
615 case WAN_DISCONNECTED:
616 if (cycx_x25_chan_connect(dev)) {
617 netif_stop_queue(dev);
623 dev->trans_start = jiffies;
624 netif_stop_queue(dev);
626 if (cycx_x25_chan_send(dev, skb))
631 ++chan->ifstats.tx_dropped;
632 ++card->wandev.stats.tx_dropped;
634 } else { /* chan->protocol == ETH_P_X25 */
635 switch (skb->data[0]) {
637 case 1: /* Connect request */
638 cycx_x25_chan_connect(dev);
640 case 2: /* Disconnect request */
641 cycx_x25_chan_disconnect(dev);
645 "%s: unknown %d x25-iface request on %s!\n",
646 card->devname, skb->data[0], dev->name);
647 ++chan->ifstats.tx_errors;
651 skb_pull(skb, 1); /* Remove control byte */
653 dev->trans_start = jiffies;
654 netif_stop_queue(dev);
656 if (cycx_x25_chan_send(dev, skb)) {
657 /* prepare for future retransmissions */
669 /* Get Ethernet-style interface statistics.
670 * Return a pointer to struct net_device_stats */
671 static struct net_device_stats *cycx_netdevice_get_stats(struct net_device *dev)
673 struct cycx_x25_channel *chan = dev->priv;
675 return chan ? &chan->ifstats : NULL;
678 /* Interrupt Handlers */
679 /* X.25 Interrupt Service Routine. */
680 static void cycx_x25_irq_handler(struct cycx_device *card)
682 struct cycx_x25_cmd cmd;
686 card->buff_int_mode_unbusy = 0;
687 cycx_peek(&card->hw, X25_RXMBOX_OFFS, &cmd, sizeof(cmd));
689 switch (cmd.command) {
690 case X25_DATA_INDICATION:
691 cycx_x25_irq_rx(card, &cmd);
693 case X25_ACK_FROM_VC:
694 cycx_x25_irq_tx(card, &cmd);
697 cycx_x25_irq_log(card, &cmd);
700 cycx_x25_irq_stat(card, &cmd);
702 case X25_CONNECT_CONFIRM:
703 cycx_x25_irq_connect_confirm(card, &cmd);
705 case X25_CONNECT_INDICATION:
706 cycx_x25_irq_connect(card, &cmd);
708 case X25_DISCONNECT_INDICATION:
709 cycx_x25_irq_disconnect(card, &cmd);
711 case X25_DISCONNECT_CONFIRM:
712 cycx_x25_irq_disconnect_confirm(card, &cmd);
715 cycx_set_state(card, WAN_CONNECTED);
718 cycx_set_state(card, WAN_DISCONNECTED);
721 cycx_x25_irq_spurious(card, &cmd);
725 cycx_poke(&card->hw, 0, &z, sizeof(z));
726 cycx_poke(&card->hw, X25_RXMBOX_OFFS, &z, sizeof(z));
730 /* Transmit interrupt handler.
731 * o Release socket buffer
732 * o Clear 'tbusy' flag */
733 static void cycx_x25_irq_tx(struct cycx_device *card, struct cycx_x25_cmd *cmd)
735 struct net_device *dev;
736 struct wan_device *wandev = &card->wandev;
739 cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
741 /* unbusy device and then dev_tint(); */
742 dev = cycx_x25_get_dev_by_lcn(wandev, lcn);
744 card->buff_int_mode_unbusy = 1;
745 netif_wake_queue(dev);
747 printk(KERN_ERR "%s:ackvc for inexistent lcn %d\n",
751 /* Receive interrupt handler.
752 * This routine handles fragmented IP packets using M-bit according to the
754 * o map logical channel number to network interface.
755 * o allocate socket buffer or append received packet to the existing one.
756 * o if M-bit is reset (i.e. it's the last packet in a sequence) then
757 * decapsulate packet and pass socket buffer to the protocol stack.
760 * 1. When allocating a socket buffer, if M-bit is set then more data is
761 * coming and we have to allocate buffer for the maximum IP packet size
762 * expected on this channel.
763 * 2. If something goes wrong and X.25 packet has to be dropped (e.g. no
764 * socket buffers available) the whole packet sequence must be discarded. */
765 static void cycx_x25_irq_rx(struct cycx_device *card, struct cycx_x25_cmd *cmd)
767 struct wan_device *wandev = &card->wandev;
768 struct net_device *dev;
769 struct cycx_x25_channel *chan;
772 int pktlen = cmd->len - 5;
774 cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
775 cycx_peek(&card->hw, cmd->buf + 4, &bitm, sizeof(bitm));
778 dev = cycx_x25_get_dev_by_lcn(wandev, lcn);
780 /* Invalid channel, discard packet */
781 printk(KERN_INFO "%s: receiving on orphaned LCN %d!\n",
789 if (chan->drop_sequence) {
791 chan->drop_sequence = 0;
796 if ((skb = chan->rx_skb) == NULL) {
797 /* Allocate new socket buffer */
798 int bufsize = bitm ? dev->mtu : pktlen;
800 if ((skb = dev_alloc_skb((chan->protocol == ETH_P_X25 ? 1 : 0) +
802 dev->hard_header_len)) == NULL) {
803 printk(KERN_INFO "%s: no socket buffers available!\n",
805 chan->drop_sequence = 1;
806 ++chan->ifstats.rx_dropped;
810 if (chan->protocol == ETH_P_X25) /* X.25 socket layer control */
811 /* 0 = data packet (dev_alloc_skb zeroed skb->data) */
815 skb->protocol = htons(chan->protocol);
819 if (skb_tailroom(skb) < pktlen) {
820 /* No room for the packet. Call off the whole thing! */
821 dev_kfree_skb_irq(skb);
825 chan->drop_sequence = 1;
827 printk(KERN_INFO "%s: unexpectedly long packet sequence "
828 "on interface %s!\n", card->devname, dev->name);
829 ++chan->ifstats.rx_length_errors;
833 /* Append packet to the socket buffer */
834 cycx_peek(&card->hw, cmd->buf + 5, skb_put(skb, pktlen), pktlen);
837 return; /* more data is coming */
839 chan->rx_skb = NULL; /* dequeue packet */
841 ++chan->ifstats.rx_packets;
842 chan->ifstats.rx_bytes += pktlen;
844 skb_reset_mac_header(skb);
848 /* Connect interrupt handler. */
849 static void cycx_x25_irq_connect(struct cycx_device *card,
850 struct cycx_x25_cmd *cmd)
852 struct wan_device *wandev = &card->wandev;
853 struct net_device *dev = NULL;
854 struct cycx_x25_channel *chan;
858 u8 lcn, sizeloc, sizerem;
860 cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
861 cycx_peek(&card->hw, cmd->buf + 5, &sizeloc, sizeof(sizeloc));
862 cycx_peek(&card->hw, cmd->buf + 6, d, cmd->len - 6);
864 sizerem = sizeloc >> 4;
867 loc[0] = rem[0] = '\0';
870 nibble_to_byte(d, loc, sizeloc, 0);
873 nibble_to_byte(d + (sizeloc >> 1), rem, sizerem, sizeloc & 1);
875 dprintk(1, KERN_INFO "%s:lcn=%d, local=%s, remote=%s\n",
876 __func__, lcn, loc, rem);
878 dev = cycx_x25_get_dev_by_dte_addr(wandev, rem);
880 /* Invalid channel, discard packet */
881 printk(KERN_INFO "%s: connect not expected: remote %s!\n",
888 cycx_x25_connect_response(card, chan);
889 cycx_x25_set_chan_state(dev, WAN_CONNECTED);
892 /* Connect confirm interrupt handler. */
893 static void cycx_x25_irq_connect_confirm(struct cycx_device *card,
894 struct cycx_x25_cmd *cmd)
896 struct wan_device *wandev = &card->wandev;
897 struct net_device *dev;
898 struct cycx_x25_channel *chan;
901 cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
902 cycx_peek(&card->hw, cmd->buf + 1, &key, sizeof(key));
903 dprintk(1, KERN_INFO "%s: %s:lcn=%d, key=%d\n",
904 card->devname, __func__, lcn, key);
906 dev = cycx_x25_get_dev_by_lcn(wandev, -key);
908 /* Invalid channel, discard packet */
909 clear_bit(--key, (void*)&card->u.x.connection_keys);
910 printk(KERN_INFO "%s: connect confirm not expected: lcn %d, "
911 "key=%d!\n", card->devname, lcn, key);
915 clear_bit(--key, (void*)&card->u.x.connection_keys);
918 cycx_x25_set_chan_state(dev, WAN_CONNECTED);
921 /* Disconnect confirm interrupt handler. */
922 static void cycx_x25_irq_disconnect_confirm(struct cycx_device *card,
923 struct cycx_x25_cmd *cmd)
925 struct wan_device *wandev = &card->wandev;
926 struct net_device *dev;
929 cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
930 dprintk(1, KERN_INFO "%s: %s:lcn=%d\n",
931 card->devname, __func__, lcn);
932 dev = cycx_x25_get_dev_by_lcn(wandev, lcn);
934 /* Invalid channel, discard packet */
935 printk(KERN_INFO "%s:disconnect confirm not expected!:lcn %d\n",
940 cycx_x25_set_chan_state(dev, WAN_DISCONNECTED);
943 /* disconnect interrupt handler. */
944 static void cycx_x25_irq_disconnect(struct cycx_device *card,
945 struct cycx_x25_cmd *cmd)
947 struct wan_device *wandev = &card->wandev;
948 struct net_device *dev;
951 cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
952 dprintk(1, KERN_INFO "%s:lcn=%d\n", __func__, lcn);
954 dev = cycx_x25_get_dev_by_lcn(wandev, lcn);
956 struct cycx_x25_channel *chan = dev->priv;
958 cycx_x25_disconnect_response(card, chan->link, lcn);
959 cycx_x25_set_chan_state(dev, WAN_DISCONNECTED);
961 cycx_x25_disconnect_response(card, 0, lcn);
964 /* LOG interrupt handler. */
965 static void cycx_x25_irq_log(struct cycx_device *card, struct cycx_x25_cmd *cmd)
967 #if CYCLOMX_X25_DEBUG
969 u16 size, toread, link, msg_code;
972 cycx_peek(&card->hw, cmd->buf, &msg_code, sizeof(msg_code));
973 cycx_peek(&card->hw, cmd->buf + 2, &link, sizeof(link));
974 cycx_peek(&card->hw, cmd->buf + 4, &size, sizeof(size));
975 /* at most 20 bytes are available... thanks to Daniela :) */
976 toread = size < 20 ? size : 20;
977 cycx_peek(&card->hw, cmd->buf + 10, &bf, toread);
978 cycx_peek(&card->hw, cmd->buf + 10 + toread, &code, 1);
979 cycx_peek(&card->hw, cmd->buf + 10 + toread + 1, &routine, 1);
981 printk(KERN_INFO "cycx_x25_irq_handler: X25_LOG (0x4500) indic.:\n");
982 printk(KERN_INFO "cmd->buf=0x%X\n", cmd->buf);
983 printk(KERN_INFO "Log message code=0x%X\n", msg_code);
984 printk(KERN_INFO "Link=%d\n", link);
985 printk(KERN_INFO "log code=0x%X\n", code);
986 printk(KERN_INFO "log routine=0x%X\n", routine);
987 printk(KERN_INFO "Message size=%d\n", size);
988 hex_dump("Message", bf, toread);
992 /* STATISTIC interrupt handler. */
993 static void cycx_x25_irq_stat(struct cycx_device *card,
994 struct cycx_x25_cmd *cmd)
996 cycx_peek(&card->hw, cmd->buf, &card->u.x.stats,
997 sizeof(card->u.x.stats));
998 hex_dump("cycx_x25_irq_stat", (unsigned char*)&card->u.x.stats,
999 sizeof(card->u.x.stats));
1000 cycx_x25_dump_stats(&card->u.x.stats);
1001 wake_up_interruptible(&card->wait_stats);
1004 /* Spurious interrupt handler.
1006 * If number of spurious interrupts exceeded some limit, then ??? */
1007 static void cycx_x25_irq_spurious(struct cycx_device *card,
1008 struct cycx_x25_cmd *cmd)
1010 printk(KERN_INFO "%s: spurious interrupt (0x%X)!\n",
1011 card->devname, cmd->command);
1013 #ifdef CYCLOMX_X25_DEBUG
1014 static void hex_dump(char *msg, unsigned char *p, int len)
1016 unsigned char hex[1024],
1019 if (len >= (sizeof(hex) / 2))
1020 len = (sizeof(hex) / 2) - 1;
1023 sprintf(phex, "%02x", *p++);
1027 printk(KERN_INFO "%s: %s\n", msg, hex);
1031 /* Cyclom 2X Firmware-Specific Functions */
1032 /* Exec X.25 command. */
1033 static int x25_exec(struct cycx_device *card, int command, int link,
1034 void *d1, int len1, void *d2, int len2)
1036 struct cycx_x25_cmd c;
1037 unsigned long flags;
1038 u32 addr = 0x1200 + 0x2E0 * link + 0x1E2;
1039 u8 retry = CYCX_X25_MAX_CMD_RETRY;
1042 c.command = command;
1044 c.len = len1 + len2;
1046 spin_lock_irqsave(&card->u.x.lock, flags);
1049 cycx_poke(&card->hw, X25_MBOX_OFFS, &c, sizeof(c) - sizeof(c.buf));
1051 /* write X.25 data */
1053 cycx_poke(&card->hw, addr, d1, len1);
1057 u32 addr1 = 0xA00 + 0x400 * link;
1059 cycx_poke(&card->hw, addr + len1, d2, 249);
1060 cycx_poke(&card->hw, addr1, ((u8*)d2) + 249,
1063 cycx_poke(&card->hw, addr + len1, d2, len2);
1067 /* generate interruption, executing command */
1068 cycx_intr(&card->hw);
1070 /* wait till card->mbox == 0 */
1072 err = cycx_exec(card->mbox);
1073 } while (retry-- && err);
1075 spin_unlock_irqrestore(&card->u.x.lock, flags);
1080 /* Configure adapter. */
1081 static int cycx_x25_configure(struct cycx_device *card,
1082 struct cycx_x25_config *conf)
1086 struct cycx_x25_config conf[2];
1089 memset(&x25_cmd_conf, 0, sizeof(x25_cmd_conf));
1090 x25_cmd_conf.nlinks = 2;
1091 x25_cmd_conf.conf[0] = *conf;
1092 /* FIXME: we need to find a way in the wanrouter framework
1093 to configure the second link, for now lets use it
1094 with the same config from the first link, fixing
1095 the interface type to RS232, the speed in 38400 and
1096 the clock to external */
1097 x25_cmd_conf.conf[1] = *conf;
1098 x25_cmd_conf.conf[1].link = 1;
1099 x25_cmd_conf.conf[1].speed = 5; /* 38400 */
1100 x25_cmd_conf.conf[1].clock = 8;
1101 x25_cmd_conf.conf[1].flags = 0; /* default = RS232 */
1103 cycx_x25_dump_config(&x25_cmd_conf.conf[0]);
1104 cycx_x25_dump_config(&x25_cmd_conf.conf[1]);
1106 return x25_exec(card, X25_CONFIG, 0,
1107 &x25_cmd_conf, sizeof(x25_cmd_conf), NULL, 0);
1110 /* Get protocol statistics. */
1111 static int cycx_x25_get_stats(struct cycx_device *card)
1113 /* the firmware expects 20 in the size field!!!
1114 thanks to Daniela */
1115 int err = x25_exec(card, X25_STATISTIC, 0, NULL, 20, NULL, 0);
1120 interruptible_sleep_on(&card->wait_stats);
1122 if (signal_pending(current))
1125 card->wandev.stats.rx_packets = card->u.x.stats.n2_rx_frames;
1126 card->wandev.stats.rx_over_errors = card->u.x.stats.rx_over_errors;
1127 card->wandev.stats.rx_crc_errors = card->u.x.stats.rx_crc_errors;
1128 card->wandev.stats.rx_length_errors = 0; /* not available from fw */
1129 card->wandev.stats.rx_frame_errors = 0; /* not available from fw */
1130 card->wandev.stats.rx_missed_errors = card->u.x.stats.rx_aborts;
1131 card->wandev.stats.rx_dropped = 0; /* not available from fw */
1132 card->wandev.stats.rx_errors = 0; /* not available from fw */
1133 card->wandev.stats.tx_packets = card->u.x.stats.n2_tx_frames;
1134 card->wandev.stats.tx_aborted_errors = card->u.x.stats.tx_aborts;
1135 card->wandev.stats.tx_dropped = 0; /* not available from fw */
1136 card->wandev.stats.collisions = 0; /* not available from fw */
1137 card->wandev.stats.tx_errors = 0; /* not available from fw */
1139 cycx_x25_dump_devs(&card->wandev);
1144 /* return the number of nibbles */
1145 static int byte_to_nibble(u8 *s, u8 *d, char *nibble)
1149 if (*nibble && *s) {
1156 d[i] = (*s - '0') << 4;
1158 d[i] |= *(s + 1) - '0';
1170 static void nibble_to_byte(u8 *s, u8 *d, u8 len, u8 nibble)
1173 *d++ = '0' + (*s++ & 0x0F);
1178 *d++ = '0' + (*s >> 4);
1181 *d++ = '0' + (*s & 0x0F);
1191 /* Place X.25 call. */
1192 static int x25_place_call(struct cycx_device *card,
1193 struct cycx_x25_channel *chan)
1199 mylen = chan->local_addr ? strlen(chan->local_addr) : 0,
1200 remotelen = strlen(chan->addr);
1203 if (card->u.x.connection_keys == ~0U) {
1204 printk(KERN_INFO "%s: too many simultaneous connection "
1205 "requests!\n", card->devname);
1209 key = ffz(card->u.x.connection_keys);
1210 set_bit(key, (void*)&card->u.x.connection_keys);
1212 dprintk(1, KERN_INFO "%s:x25_place_call:key=%d\n", card->devname, key);
1213 memset(d, 0, sizeof(d));
1214 d[1] = key; /* user key */
1218 len = byte_to_nibble(chan->addr, d + 6, &nibble);
1220 if (chan->local_addr)
1221 len += byte_to_nibble(chan->local_addr, d + 6 + len, &nibble);
1226 d[5] = mylen << 4 | remotelen;
1227 d[6 + len + 1] = 0xCC; /* TCP/IP over X.25, thanks to Daniela :) */
1229 if ((err = x25_exec(card, X25_CONNECT_REQUEST, chan->link,
1230 &d, 7 + len + 1, NULL, 0)) != 0)
1231 clear_bit(--key, (void*)&card->u.x.connection_keys);
1238 /* Place X.25 CONNECT RESPONSE. */
1239 static int cycx_x25_connect_response(struct cycx_device *card,
1240 struct cycx_x25_channel *chan)
1244 memset(d, 0, sizeof(d));
1245 d[0] = d[3] = chan->lcn;
1248 d[7] = 0xCC; /* TCP/IP over X.25, thanks Daniela */
1250 return x25_exec(card, X25_CONNECT_RESPONSE, chan->link, &d, 8, NULL, 0);
1253 /* Place X.25 DISCONNECT RESPONSE. */
1254 static int cycx_x25_disconnect_response(struct cycx_device *card, u8 link,
1259 memset(d, 0, sizeof(d));
1264 return x25_exec(card, X25_DISCONNECT_RESPONSE, link, &d, 5, NULL, 0);
1267 /* Clear X.25 call. */
1268 static int x25_clear_call(struct cycx_device *card, u8 link, u8 lcn, u8 cause,
1273 memset(d, 0, sizeof(d));
1280 return x25_exec(card, X25_DISCONNECT_REQUEST, link, d, 7, NULL, 0);
1283 /* Send X.25 data packet. */
1284 static int cycx_x25_send(struct cycx_device *card, u8 link, u8 lcn, u8 bitm,
1287 u8 d[] = "?\xFF\x10??";
1292 return x25_exec(card, X25_DATA_REQUEST, link, &d, 5, buf, len);
1296 /* Find network device by its channel number. */
1297 static struct net_device *cycx_x25_get_dev_by_lcn(struct wan_device *wandev,
1300 struct net_device *dev = wandev->dev;
1301 struct cycx_x25_channel *chan;
1304 chan = (struct cycx_x25_channel*)dev->priv;
1306 if (chan->lcn == lcn)
1313 /* Find network device by its remote dte address. */
1314 static struct net_device *
1315 cycx_x25_get_dev_by_dte_addr(struct wan_device *wandev, char *dte)
1317 struct net_device *dev = wandev->dev;
1318 struct cycx_x25_channel *chan;
1321 chan = (struct cycx_x25_channel*)dev->priv;
1323 if (!strcmp(chan->addr, dte))
1330 /* Initiate connection on the logical channel.
1331 * o for PVC we just get channel configuration
1332 * o for SVCs place an X.25 call
1334 * Return: 0 connected
1335 * >0 connection in progress
1337 static int cycx_x25_chan_connect(struct net_device *dev)
1339 struct cycx_x25_channel *chan = dev->priv;
1340 struct cycx_device *card = chan->card;
1344 return -EINVAL; /* no destination address */
1346 dprintk(1, KERN_INFO "%s: placing X.25 call to %s...\n",
1347 card->devname, chan->addr);
1349 if (x25_place_call(card, chan))
1352 cycx_x25_set_chan_state(dev, WAN_CONNECTING);
1355 cycx_x25_set_chan_state(dev, WAN_CONNECTED);
1360 /* Disconnect logical channel.
1361 * o if SVC then clear X.25 call */
1362 static void cycx_x25_chan_disconnect(struct net_device *dev)
1364 struct cycx_x25_channel *chan = dev->priv;
1367 x25_clear_call(chan->card, chan->link, chan->lcn, 0, 0);
1368 cycx_x25_set_chan_state(dev, WAN_DISCONNECTING);
1370 cycx_x25_set_chan_state(dev, WAN_DISCONNECTED);
1373 /* Called by kernel timer */
1374 static void cycx_x25_chan_timer(unsigned long d)
1376 struct net_device *dev = (struct net_device *)d;
1377 struct cycx_x25_channel *chan = dev->priv;
1379 if (chan->state == WAN_CONNECTED)
1380 cycx_x25_chan_disconnect(dev);
1382 printk(KERN_ERR "%s: %s for svc (%s) not connected!\n",
1383 chan->card->devname, __func__, dev->name);
1386 /* Set logical channel state. */
1387 static void cycx_x25_set_chan_state(struct net_device *dev, u8 state)
1389 struct cycx_x25_channel *chan = dev->priv;
1390 struct cycx_device *card = chan->card;
1391 unsigned long flags;
1392 char *string_state = NULL;
1394 spin_lock_irqsave(&card->lock, flags);
1396 if (chan->state != state) {
1397 if (chan->svc && chan->state == WAN_CONNECTED)
1398 del_timer(&chan->timer);
1402 string_state = "connected!";
1403 *(__be16*)dev->dev_addr = htons(chan->lcn);
1404 netif_wake_queue(dev);
1407 if (chan->protocol == ETH_P_X25)
1408 cycx_x25_chan_send_event(dev, 1);
1411 case WAN_CONNECTING:
1412 string_state = "connecting...";
1414 case WAN_DISCONNECTING:
1415 string_state = "disconnecting...";
1417 case WAN_DISCONNECTED:
1418 string_state = "disconnected!";
1421 *(unsigned short*)dev->dev_addr = 0;
1425 if (chan->protocol == ETH_P_X25)
1426 cycx_x25_chan_send_event(dev, 2);
1428 netif_wake_queue(dev);
1432 printk(KERN_INFO "%s: interface %s %s\n", card->devname,
1433 dev->name, string_state);
1434 chan->state = state;
1437 spin_unlock_irqrestore(&card->lock, flags);
1440 /* Send packet on a logical channel.
1441 * When this function is called, tx_skb field of the channel data space
1442 * points to the transmit socket buffer. When transmission is complete,
1443 * release socket buffer and reset 'tbusy' flag.
1445 * Return: 0 - transmission complete
1449 * 1. If packet length is greater than MTU for this channel, we'll fragment
1450 * the packet into 'complete sequence' using M-bit.
1451 * 2. When transmission is complete, an event notification should be issued
1453 static int cycx_x25_chan_send(struct net_device *dev, struct sk_buff *skb)
1455 struct cycx_x25_channel *chan = dev->priv;
1456 struct cycx_device *card = chan->card;
1457 int bitm = 0; /* final packet */
1458 unsigned len = skb->len;
1460 if (skb->len > card->wandev.mtu) {
1461 len = card->wandev.mtu;
1462 bitm = 0x10; /* set M-bit (more data) */
1465 if (cycx_x25_send(card, chan->link, chan->lcn, bitm, len, skb->data))
1473 ++chan->ifstats.tx_packets;
1474 chan->ifstats.tx_bytes += len;
1479 /* Send event (connection, disconnection, etc) to X.25 socket layer */
1481 static void cycx_x25_chan_send_event(struct net_device *dev, u8 event)
1483 struct sk_buff *skb;
1486 if ((skb = dev_alloc_skb(1)) == NULL) {
1487 printk(KERN_ERR "%s: out of memory\n", __func__);
1491 ptr = skb_put(skb, 1);
1494 skb->protocol = x25_type_trans(skb, dev);
1498 /* Convert line speed in bps to a number used by cyclom 2x code. */
1499 static u8 bps_to_speed_code(u32 bps)
1501 u8 number = 0; /* defaults to the lowest (1200) speed ;> */
1503 if (bps >= 512000) number = 8;
1504 else if (bps >= 256000) number = 7;
1505 else if (bps >= 64000) number = 6;
1506 else if (bps >= 38400) number = 5;
1507 else if (bps >= 19200) number = 4;
1508 else if (bps >= 9600) number = 3;
1509 else if (bps >= 4800) number = 2;
1510 else if (bps >= 2400) number = 1;
1516 static u8 cycx_log2(u32 n)
1531 /* Convert decimal string to unsigned integer.
1532 * If len != 0 then only 'len' characters of the string are converted. */
1533 static unsigned dec_to_uint(u8 *str, int len)
1540 for (; len && isdigit(*str); ++str, --len)
1541 val = (val * 10) + (*str - (unsigned) '0');
1546 static void reset_timer(struct net_device *dev)
1548 struct cycx_x25_channel *chan = dev->priv;
1551 mod_timer(&chan->timer, jiffies+chan->idle_tmout*HZ);
1553 #ifdef CYCLOMX_X25_DEBUG
1554 static void cycx_x25_dump_config(struct cycx_x25_config *conf)
1556 printk(KERN_INFO "X.25 configuration\n");
1557 printk(KERN_INFO "-----------------\n");
1558 printk(KERN_INFO "link number=%d\n", conf->link);
1559 printk(KERN_INFO "line speed=%d\n", conf->speed);
1560 printk(KERN_INFO "clock=%sternal\n", conf->clock == 8 ? "Ex" : "In");
1561 printk(KERN_INFO "# level 2 retransm.=%d\n", conf->n2);
1562 printk(KERN_INFO "level 2 window=%d\n", conf->n2win);
1563 printk(KERN_INFO "level 3 window=%d\n", conf->n3win);
1564 printk(KERN_INFO "# logical channels=%d\n", conf->nvc);
1565 printk(KERN_INFO "level 3 pkt len=%d\n", conf->pktlen);
1566 printk(KERN_INFO "my address=%d\n", conf->locaddr);
1567 printk(KERN_INFO "remote address=%d\n", conf->remaddr);
1568 printk(KERN_INFO "t1=%d seconds\n", conf->t1);
1569 printk(KERN_INFO "t2=%d seconds\n", conf->t2);
1570 printk(KERN_INFO "t21=%d seconds\n", conf->t21);
1571 printk(KERN_INFO "# PVCs=%d\n", conf->npvc);
1572 printk(KERN_INFO "t23=%d seconds\n", conf->t23);
1573 printk(KERN_INFO "flags=0x%x\n", conf->flags);
1576 static void cycx_x25_dump_stats(struct cycx_x25_stats *stats)
1578 printk(KERN_INFO "X.25 statistics\n");
1579 printk(KERN_INFO "--------------\n");
1580 printk(KERN_INFO "rx_crc_errors=%d\n", stats->rx_crc_errors);
1581 printk(KERN_INFO "rx_over_errors=%d\n", stats->rx_over_errors);
1582 printk(KERN_INFO "n2_tx_frames=%d\n", stats->n2_tx_frames);
1583 printk(KERN_INFO "n2_rx_frames=%d\n", stats->n2_rx_frames);
1584 printk(KERN_INFO "tx_timeouts=%d\n", stats->tx_timeouts);
1585 printk(KERN_INFO "rx_timeouts=%d\n", stats->rx_timeouts);
1586 printk(KERN_INFO "n3_tx_packets=%d\n", stats->n3_tx_packets);
1587 printk(KERN_INFO "n3_rx_packets=%d\n", stats->n3_rx_packets);
1588 printk(KERN_INFO "tx_aborts=%d\n", stats->tx_aborts);
1589 printk(KERN_INFO "rx_aborts=%d\n", stats->rx_aborts);
1592 static void cycx_x25_dump_devs(struct wan_device *wandev)
1594 struct net_device *dev = wandev->dev;
1596 printk(KERN_INFO "X.25 dev states\n");
1597 printk(KERN_INFO "name: addr: txoff: protocol:\n");
1598 printk(KERN_INFO "---------------------------------------\n");
1601 struct cycx_x25_channel *chan = dev->priv;
1603 printk(KERN_INFO "%-5.5s %-15.15s %d ETH_P_%s\n",
1604 chan->name, chan->addr, netif_queue_stopped(dev),
1605 chan->protocol == ETH_P_IP ? "IP" : "X25");
1610 #endif /* CYCLOMX_X25_DEBUG */