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 static void cycx_x25_chan_setup(struct net_device *dev);
204 #ifdef CYCLOMX_X25_DEBUG
205 static void hex_dump(char *msg, unsigned char *p, int len);
206 static void cycx_x25_dump_config(struct cycx_x25_config *conf);
207 static void cycx_x25_dump_stats(struct cycx_x25_stats *stats);
208 static void cycx_x25_dump_devs(struct wan_device *wandev);
210 #define hex_dump(msg, p, len)
211 #define cycx_x25_dump_config(conf)
212 #define cycx_x25_dump_stats(stats)
213 #define cycx_x25_dump_devs(wandev)
215 /* Public Functions */
217 /* X.25 Protocol Initialization routine.
219 * This routine is called by the main Cyclom 2X module during setup. At this
220 * point adapter is completely initialized and X.25 firmware is running.
221 * o configure adapter
222 * o initialize protocol-specific fields of the adapter data space.
226 int cycx_x25_wan_init(struct cycx_device *card, wandev_conf_t *conf)
228 struct cycx_x25_config cfg;
230 /* Verify configuration ID */
231 if (conf->config_id != WANCONFIG_X25) {
232 printk(KERN_INFO "%s: invalid configuration ID %u!\n",
233 card->devname, conf->config_id);
237 /* Initialize protocol-specific fields */
238 card->mbox = card->hw.dpmbase + X25_MBOX_OFFS;
239 card->u.x.connection_keys = 0;
240 spin_lock_init(&card->u.x.lock);
242 /* Configure adapter. Here we set reasonable defaults, then parse
243 * device configuration structure and set configuration options.
244 * Most configuration options are verified and corrected (if
245 * necessary) since we can't rely on the adapter to do so and don't
246 * want it to fail either. */
247 memset(&cfg, 0, sizeof(cfg));
249 cfg.clock = conf->clocking == WANOPT_EXTERNAL ? 8 : 55;
250 cfg.speed = bps_to_speed_code(conf->bps);
256 cfg.flags = 0x02; /* default = V35 */
257 cfg.t1 = 10; /* line carrier timeout */
258 cfg.t2 = 29; /* tx timeout */
259 cfg.t21 = 180; /* CALL timeout */
260 cfg.t23 = 180; /* CLEAR timeout */
263 if (!conf->mtu || conf->mtu >= 512)
264 card->wandev.mtu = 512;
265 else if (conf->mtu >= 256)
266 card->wandev.mtu = 256;
267 else if (conf->mtu >= 128)
268 card->wandev.mtu = 128;
270 card->wandev.mtu = 64;
272 cfg.pktlen = cycx_log2(card->wandev.mtu);
274 if (conf->station == WANOPT_DTE) {
275 cfg.locaddr = 3; /* DTE */
276 cfg.remaddr = 1; /* DCE */
278 cfg.locaddr = 1; /* DCE */
279 cfg.remaddr = 3; /* DTE */
282 if (conf->interface == WANOPT_RS232)
283 cfg.flags = 0; /* FIXME just reset the 2nd bit */
285 if (conf->u.x25.hi_pvc) {
286 card->u.x.hi_pvc = min_t(unsigned int, conf->u.x25.hi_pvc, 4095);
287 card->u.x.lo_pvc = min_t(unsigned int, conf->u.x25.lo_pvc, card->u.x.hi_pvc);
290 if (conf->u.x25.hi_svc) {
291 card->u.x.hi_svc = min_t(unsigned int, conf->u.x25.hi_svc, 4095);
292 card->u.x.lo_svc = min_t(unsigned int, conf->u.x25.lo_svc, card->u.x.hi_svc);
295 if (card->u.x.lo_pvc == 255)
298 cfg.npvc = card->u.x.hi_pvc - card->u.x.lo_pvc + 1;
300 cfg.nvc = card->u.x.hi_svc - card->u.x.lo_svc + 1 + cfg.npvc;
302 if (conf->u.x25.hdlc_window)
303 cfg.n2win = min_t(unsigned int, conf->u.x25.hdlc_window, 7);
305 if (conf->u.x25.pkt_window)
306 cfg.n3win = min_t(unsigned int, conf->u.x25.pkt_window, 7);
309 cfg.t1 = min_t(unsigned int, conf->u.x25.t1, 30);
312 cfg.t2 = min_t(unsigned int, conf->u.x25.t2, 30);
314 if (conf->u.x25.t11_t21)
315 cfg.t21 = min_t(unsigned int, conf->u.x25.t11_t21, 30);
317 if (conf->u.x25.t13_t23)
318 cfg.t23 = min_t(unsigned int, conf->u.x25.t13_t23, 30);
321 cfg.n2 = min_t(unsigned int, conf->u.x25.n2, 30);
323 /* initialize adapter */
324 if (cycx_x25_configure(card, &cfg))
327 /* Initialize protocol-specific fields of adapter data space */
328 card->wandev.bps = conf->bps;
329 card->wandev.interface = conf->interface;
330 card->wandev.clocking = conf->clocking;
331 card->wandev.station = conf->station;
332 card->isr = cycx_x25_irq_handler;
334 card->wandev.update = cycx_wan_update;
335 card->wandev.new_if = cycx_wan_new_if;
336 card->wandev.del_if = cycx_wan_del_if;
337 card->wandev.state = WAN_DISCONNECTED;
342 /* WAN Device Driver Entry Points */
343 /* Update device status & statistics. */
344 static int cycx_wan_update(struct wan_device *wandev)
347 if (!wandev || !wandev->private)
350 if (wandev->state == WAN_UNCONFIGURED)
353 cycx_x25_get_stats(wandev->private);
358 /* callback to initialize device */
359 static void cycx_x25_chan_setup(struct net_device *dev)
361 dev->init = cycx_netdevice_init;
364 /* Create new logical channel.
365 * This routine is called by the router when ROUTER_IFNEW IOCTL is being
367 * o parse media- and hardware-specific configuration
368 * o make sure that a new channel can be created
369 * o allocate resources, if necessary
370 * o prepare network device structure for registration.
373 * < 0 failure (channel will not be created) */
374 static int cycx_wan_new_if(struct wan_device *wandev, struct net_device *dev,
377 struct cycx_device *card = wandev->private;
378 struct cycx_x25_channel *chan;
381 if (!conf->name[0] || strlen(conf->name) > WAN_IFNAME_SZ) {
382 printk(KERN_INFO "%s: invalid interface name!\n",
387 dev = alloc_netdev(sizeof(struct cycx_x25_channel), conf->name,
388 cycx_x25_chan_setup);
392 chan = netdev_priv(dev);
393 strcpy(chan->name, conf->name);
395 chan->link = conf->port;
396 chan->protocol = conf->protocol ? ETH_P_X25 : ETH_P_IP;
398 /* only used in svc connected thru crossover cable */
399 chan->local_addr = NULL;
401 if (conf->addr[0] == '@') { /* SVC */
402 int len = strlen(conf->local_addr);
405 if (len > WAN_ADDRESS_SZ) {
406 printk(KERN_ERR "%s: %s local addr too long!\n",
407 wandev->name, chan->name);
411 chan->local_addr = kmalloc(len + 1, GFP_KERNEL);
413 if (!chan->local_addr) {
419 strncpy(chan->local_addr, conf->local_addr,
424 strncpy(chan->addr, &conf->addr[1], WAN_ADDRESS_SZ);
425 init_timer(&chan->timer);
426 chan->timer.function = cycx_x25_chan_timer;
427 chan->timer.data = (unsigned long)dev;
429 /* Set channel timeouts (default if not specified) */
430 chan->idle_tmout = conf->idle_timeout ? conf->idle_timeout : 90;
431 } else if (isdigit(conf->addr[0])) { /* PVC */
432 s16 lcn = dec_to_uint(conf->addr, 0);
434 if (lcn >= card->u.x.lo_pvc && lcn <= card->u.x.hi_pvc)
438 "%s: PVC %u is out of range on interface %s!\n",
439 wandev->name, lcn, chan->name);
444 printk(KERN_ERR "%s: invalid media address on interface %s!\n",
445 wandev->name, chan->name);
457 /* Delete logical channel. */
458 static int cycx_wan_del_if(struct wan_device *wandev, struct net_device *dev)
460 struct cycx_x25_channel *chan = netdev_priv(dev);
463 kfree(chan->local_addr);
464 if (chan->state == WAN_CONNECTED)
465 del_timer(&chan->timer);
472 /* Network Device Interface */
474 static const struct header_ops cycx_header_ops = {
475 .create = cycx_netdevice_hard_header,
476 .rebuild = cycx_netdevice_rebuild_header,
479 /* Initialize Linux network interface.
481 * This routine is called only once for each interface, during Linux network
482 * interface registration. Returning anything but zero will fail interface
484 static int cycx_netdevice_init(struct net_device *dev)
486 struct cycx_x25_channel *chan = netdev_priv(dev);
487 struct cycx_device *card = chan->card;
488 struct wan_device *wandev = &card->wandev;
490 /* Initialize device driver entry points */
491 dev->open = cycx_netdevice_open;
492 dev->stop = cycx_netdevice_stop;
493 dev->header_ops = &cycx_header_ops;
495 dev->hard_start_xmit = cycx_netdevice_hard_start_xmit;
496 dev->get_stats = cycx_netdevice_get_stats;
498 /* Initialize media-specific parameters */
499 dev->mtu = CYCX_X25_CHAN_MTU;
500 dev->type = ARPHRD_HWX25; /* ARP h/w type */
501 dev->hard_header_len = 0; /* media header length */
502 dev->addr_len = 0; /* hardware address length */
505 *(__be16*)dev->dev_addr = htons(chan->lcn);
507 /* Initialize hardware parameters (just for reference) */
508 dev->irq = wandev->irq;
509 dev->dma = wandev->dma;
510 dev->base_addr = wandev->ioport;
511 dev->mem_start = (unsigned long)wandev->maddr;
512 dev->mem_end = (unsigned long)(wandev->maddr +
514 dev->flags |= IFF_NOARP;
516 /* Set transmit buffer queue length */
517 dev->tx_queue_len = 10;
519 /* Initialize socket buffers */
520 cycx_x25_set_chan_state(dev, WAN_DISCONNECTED);
525 /* Open network interface.
526 * o prevent module from unloading by incrementing use count
527 * o if link is disconnected then initiate connection
529 * Return 0 if O.k. or errno. */
530 static int cycx_netdevice_open(struct net_device *dev)
532 if (netif_running(dev))
533 return -EBUSY; /* only one open is allowed */
535 netif_start_queue(dev);
539 /* Close network interface.
541 * o if there's no more open channels then disconnect physical link. */
542 static int cycx_netdevice_stop(struct net_device *dev)
544 struct cycx_x25_channel *chan = netdev_priv(dev);
546 netif_stop_queue(dev);
548 if (chan->state == WAN_CONNECTED || chan->state == WAN_CONNECTING)
549 cycx_x25_chan_disconnect(dev);
554 /* Build media header.
555 * o encapsulate packet according to encapsulation type.
557 * The trick here is to put packet type (Ethertype) into 'protocol' field of
558 * the socket buffer, so that we don't forget it. If encapsulation fails,
559 * set skb->protocol to 0 and discard packet later.
561 * Return: media header length. */
562 static int cycx_netdevice_hard_header(struct sk_buff *skb,
563 struct net_device *dev, u16 type,
564 const void *daddr, const void *saddr,
567 skb->protocol = htons(type);
569 return dev->hard_header_len;
572 /* * Re-build media header.
573 * Return: 1 physical address resolved.
574 * 0 physical address not resolved */
575 static int cycx_netdevice_rebuild_header(struct sk_buff *skb)
580 /* Send a packet on a network interface.
581 * o set busy flag (marks start of the transmission).
582 * o check link state. If link is not up, then drop the packet.
583 * o check channel status. If it's down then initiate a call.
584 * o pass a packet to corresponding WAN device.
585 * o free socket buffer
587 * Return: 0 complete (socket buffer must be freed)
588 * non-0 packet may be re-transmitted (tbusy must be set)
591 * 1. This routine is called either by the protocol stack or by the "net
592 * bottom half" (with interrupts enabled).
593 * 2. Setting tbusy flag will inhibit further transmit requests from the
594 * protocol stack and can be used for flow control with protocol layer. */
595 static int cycx_netdevice_hard_start_xmit(struct sk_buff *skb,
596 struct net_device *dev)
598 struct cycx_x25_channel *chan = netdev_priv(dev);
599 struct cycx_device *card = chan->card;
602 chan->protocol = ntohs(skb->protocol);
604 if (card->wandev.state != WAN_CONNECTED)
605 ++chan->ifstats.tx_dropped;
606 else if (chan->svc && chan->protocol &&
607 chan->protocol != ntohs(skb->protocol)) {
609 "%s: unsupported Ethertype 0x%04X on interface %s!\n",
610 card->devname, ntohs(skb->protocol), dev->name);
611 ++chan->ifstats.tx_errors;
612 } else if (chan->protocol == ETH_P_IP) {
613 switch (chan->state) {
614 case WAN_DISCONNECTED:
615 if (cycx_x25_chan_connect(dev)) {
616 netif_stop_queue(dev);
622 dev->trans_start = jiffies;
623 netif_stop_queue(dev);
625 if (cycx_x25_chan_send(dev, skb))
630 ++chan->ifstats.tx_dropped;
631 ++card->wandev.stats.tx_dropped;
633 } else { /* chan->protocol == ETH_P_X25 */
634 switch (skb->data[0]) {
636 case 1: /* Connect request */
637 cycx_x25_chan_connect(dev);
639 case 2: /* Disconnect request */
640 cycx_x25_chan_disconnect(dev);
644 "%s: unknown %d x25-iface request on %s!\n",
645 card->devname, skb->data[0], dev->name);
646 ++chan->ifstats.tx_errors;
650 skb_pull(skb, 1); /* Remove control byte */
652 dev->trans_start = jiffies;
653 netif_stop_queue(dev);
655 if (cycx_x25_chan_send(dev, skb)) {
656 /* prepare for future retransmissions */
668 /* Get Ethernet-style interface statistics.
669 * Return a pointer to struct net_device_stats */
670 static struct net_device_stats *cycx_netdevice_get_stats(struct net_device *dev)
672 struct cycx_x25_channel *chan = netdev_priv(dev);
674 return chan ? &chan->ifstats : NULL;
677 /* Interrupt Handlers */
678 /* X.25 Interrupt Service Routine. */
679 static void cycx_x25_irq_handler(struct cycx_device *card)
681 struct cycx_x25_cmd cmd;
685 card->buff_int_mode_unbusy = 0;
686 cycx_peek(&card->hw, X25_RXMBOX_OFFS, &cmd, sizeof(cmd));
688 switch (cmd.command) {
689 case X25_DATA_INDICATION:
690 cycx_x25_irq_rx(card, &cmd);
692 case X25_ACK_FROM_VC:
693 cycx_x25_irq_tx(card, &cmd);
696 cycx_x25_irq_log(card, &cmd);
699 cycx_x25_irq_stat(card, &cmd);
701 case X25_CONNECT_CONFIRM:
702 cycx_x25_irq_connect_confirm(card, &cmd);
704 case X25_CONNECT_INDICATION:
705 cycx_x25_irq_connect(card, &cmd);
707 case X25_DISCONNECT_INDICATION:
708 cycx_x25_irq_disconnect(card, &cmd);
710 case X25_DISCONNECT_CONFIRM:
711 cycx_x25_irq_disconnect_confirm(card, &cmd);
714 cycx_set_state(card, WAN_CONNECTED);
717 cycx_set_state(card, WAN_DISCONNECTED);
720 cycx_x25_irq_spurious(card, &cmd);
724 cycx_poke(&card->hw, 0, &z, sizeof(z));
725 cycx_poke(&card->hw, X25_RXMBOX_OFFS, &z, sizeof(z));
729 /* Transmit interrupt handler.
730 * o Release socket buffer
731 * o Clear 'tbusy' flag */
732 static void cycx_x25_irq_tx(struct cycx_device *card, struct cycx_x25_cmd *cmd)
734 struct net_device *dev;
735 struct wan_device *wandev = &card->wandev;
738 cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
740 /* unbusy device and then dev_tint(); */
741 dev = cycx_x25_get_dev_by_lcn(wandev, lcn);
743 card->buff_int_mode_unbusy = 1;
744 netif_wake_queue(dev);
746 printk(KERN_ERR "%s:ackvc for inexistent lcn %d\n",
750 /* Receive interrupt handler.
751 * This routine handles fragmented IP packets using M-bit according to the
753 * o map logical channel number to network interface.
754 * o allocate socket buffer or append received packet to the existing one.
755 * o if M-bit is reset (i.e. it's the last packet in a sequence) then
756 * decapsulate packet and pass socket buffer to the protocol stack.
759 * 1. When allocating a socket buffer, if M-bit is set then more data is
760 * coming and we have to allocate buffer for the maximum IP packet size
761 * expected on this channel.
762 * 2. If something goes wrong and X.25 packet has to be dropped (e.g. no
763 * socket buffers available) the whole packet sequence must be discarded. */
764 static void cycx_x25_irq_rx(struct cycx_device *card, struct cycx_x25_cmd *cmd)
766 struct wan_device *wandev = &card->wandev;
767 struct net_device *dev;
768 struct cycx_x25_channel *chan;
771 int pktlen = cmd->len - 5;
773 cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
774 cycx_peek(&card->hw, cmd->buf + 4, &bitm, sizeof(bitm));
777 dev = cycx_x25_get_dev_by_lcn(wandev, lcn);
779 /* Invalid channel, discard packet */
780 printk(KERN_INFO "%s: receiving on orphaned LCN %d!\n",
785 chan = netdev_priv(dev);
788 if (chan->drop_sequence) {
790 chan->drop_sequence = 0;
795 if ((skb = chan->rx_skb) == NULL) {
796 /* Allocate new socket buffer */
797 int bufsize = bitm ? dev->mtu : pktlen;
799 if ((skb = dev_alloc_skb((chan->protocol == ETH_P_X25 ? 1 : 0) +
801 dev->hard_header_len)) == NULL) {
802 printk(KERN_INFO "%s: no socket buffers available!\n",
804 chan->drop_sequence = 1;
805 ++chan->ifstats.rx_dropped;
809 if (chan->protocol == ETH_P_X25) /* X.25 socket layer control */
810 /* 0 = data packet (dev_alloc_skb zeroed skb->data) */
814 skb->protocol = htons(chan->protocol);
818 if (skb_tailroom(skb) < pktlen) {
819 /* No room for the packet. Call off the whole thing! */
820 dev_kfree_skb_irq(skb);
824 chan->drop_sequence = 1;
826 printk(KERN_INFO "%s: unexpectedly long packet sequence "
827 "on interface %s!\n", card->devname, dev->name);
828 ++chan->ifstats.rx_length_errors;
832 /* Append packet to the socket buffer */
833 cycx_peek(&card->hw, cmd->buf + 5, skb_put(skb, pktlen), pktlen);
836 return; /* more data is coming */
838 chan->rx_skb = NULL; /* dequeue packet */
840 ++chan->ifstats.rx_packets;
841 chan->ifstats.rx_bytes += pktlen;
843 skb_reset_mac_header(skb);
847 /* Connect interrupt handler. */
848 static void cycx_x25_irq_connect(struct cycx_device *card,
849 struct cycx_x25_cmd *cmd)
851 struct wan_device *wandev = &card->wandev;
852 struct net_device *dev = NULL;
853 struct cycx_x25_channel *chan;
857 u8 lcn, sizeloc, sizerem;
859 cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
860 cycx_peek(&card->hw, cmd->buf + 5, &sizeloc, sizeof(sizeloc));
861 cycx_peek(&card->hw, cmd->buf + 6, d, cmd->len - 6);
863 sizerem = sizeloc >> 4;
866 loc[0] = rem[0] = '\0';
869 nibble_to_byte(d, loc, sizeloc, 0);
872 nibble_to_byte(d + (sizeloc >> 1), rem, sizerem, sizeloc & 1);
874 dprintk(1, KERN_INFO "%s:lcn=%d, local=%s, remote=%s\n",
875 __func__, lcn, loc, rem);
877 dev = cycx_x25_get_dev_by_dte_addr(wandev, rem);
879 /* Invalid channel, discard packet */
880 printk(KERN_INFO "%s: connect not expected: remote %s!\n",
885 chan = netdev_priv(dev);
887 cycx_x25_connect_response(card, chan);
888 cycx_x25_set_chan_state(dev, WAN_CONNECTED);
891 /* Connect confirm interrupt handler. */
892 static void cycx_x25_irq_connect_confirm(struct cycx_device *card,
893 struct cycx_x25_cmd *cmd)
895 struct wan_device *wandev = &card->wandev;
896 struct net_device *dev;
897 struct cycx_x25_channel *chan;
900 cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
901 cycx_peek(&card->hw, cmd->buf + 1, &key, sizeof(key));
902 dprintk(1, KERN_INFO "%s: %s:lcn=%d, key=%d\n",
903 card->devname, __func__, lcn, key);
905 dev = cycx_x25_get_dev_by_lcn(wandev, -key);
907 /* Invalid channel, discard packet */
908 clear_bit(--key, (void*)&card->u.x.connection_keys);
909 printk(KERN_INFO "%s: connect confirm not expected: lcn %d, "
910 "key=%d!\n", card->devname, lcn, key);
914 clear_bit(--key, (void*)&card->u.x.connection_keys);
915 chan = netdev_priv(dev);
917 cycx_x25_set_chan_state(dev, WAN_CONNECTED);
920 /* Disconnect confirm interrupt handler. */
921 static void cycx_x25_irq_disconnect_confirm(struct cycx_device *card,
922 struct cycx_x25_cmd *cmd)
924 struct wan_device *wandev = &card->wandev;
925 struct net_device *dev;
928 cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
929 dprintk(1, KERN_INFO "%s: %s:lcn=%d\n",
930 card->devname, __func__, lcn);
931 dev = cycx_x25_get_dev_by_lcn(wandev, lcn);
933 /* Invalid channel, discard packet */
934 printk(KERN_INFO "%s:disconnect confirm not expected!:lcn %d\n",
939 cycx_x25_set_chan_state(dev, WAN_DISCONNECTED);
942 /* disconnect interrupt handler. */
943 static void cycx_x25_irq_disconnect(struct cycx_device *card,
944 struct cycx_x25_cmd *cmd)
946 struct wan_device *wandev = &card->wandev;
947 struct net_device *dev;
950 cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
951 dprintk(1, KERN_INFO "%s:lcn=%d\n", __func__, lcn);
953 dev = cycx_x25_get_dev_by_lcn(wandev, lcn);
955 struct cycx_x25_channel *chan = netdev_priv(dev);
957 cycx_x25_disconnect_response(card, chan->link, lcn);
958 cycx_x25_set_chan_state(dev, WAN_DISCONNECTED);
960 cycx_x25_disconnect_response(card, 0, lcn);
963 /* LOG interrupt handler. */
964 static void cycx_x25_irq_log(struct cycx_device *card, struct cycx_x25_cmd *cmd)
966 #if CYCLOMX_X25_DEBUG
968 u16 size, toread, link, msg_code;
971 cycx_peek(&card->hw, cmd->buf, &msg_code, sizeof(msg_code));
972 cycx_peek(&card->hw, cmd->buf + 2, &link, sizeof(link));
973 cycx_peek(&card->hw, cmd->buf + 4, &size, sizeof(size));
974 /* at most 20 bytes are available... thanks to Daniela :) */
975 toread = size < 20 ? size : 20;
976 cycx_peek(&card->hw, cmd->buf + 10, &bf, toread);
977 cycx_peek(&card->hw, cmd->buf + 10 + toread, &code, 1);
978 cycx_peek(&card->hw, cmd->buf + 10 + toread + 1, &routine, 1);
980 printk(KERN_INFO "cycx_x25_irq_handler: X25_LOG (0x4500) indic.:\n");
981 printk(KERN_INFO "cmd->buf=0x%X\n", cmd->buf);
982 printk(KERN_INFO "Log message code=0x%X\n", msg_code);
983 printk(KERN_INFO "Link=%d\n", link);
984 printk(KERN_INFO "log code=0x%X\n", code);
985 printk(KERN_INFO "log routine=0x%X\n", routine);
986 printk(KERN_INFO "Message size=%d\n", size);
987 hex_dump("Message", bf, toread);
991 /* STATISTIC interrupt handler. */
992 static void cycx_x25_irq_stat(struct cycx_device *card,
993 struct cycx_x25_cmd *cmd)
995 cycx_peek(&card->hw, cmd->buf, &card->u.x.stats,
996 sizeof(card->u.x.stats));
997 hex_dump("cycx_x25_irq_stat", (unsigned char*)&card->u.x.stats,
998 sizeof(card->u.x.stats));
999 cycx_x25_dump_stats(&card->u.x.stats);
1000 wake_up_interruptible(&card->wait_stats);
1003 /* Spurious interrupt handler.
1005 * If number of spurious interrupts exceeded some limit, then ??? */
1006 static void cycx_x25_irq_spurious(struct cycx_device *card,
1007 struct cycx_x25_cmd *cmd)
1009 printk(KERN_INFO "%s: spurious interrupt (0x%X)!\n",
1010 card->devname, cmd->command);
1012 #ifdef CYCLOMX_X25_DEBUG
1013 static void hex_dump(char *msg, unsigned char *p, int len)
1015 unsigned char hex[1024],
1018 if (len >= (sizeof(hex) / 2))
1019 len = (sizeof(hex) / 2) - 1;
1022 sprintf(phex, "%02x", *p++);
1026 printk(KERN_INFO "%s: %s\n", msg, hex);
1030 /* Cyclom 2X Firmware-Specific Functions */
1031 /* Exec X.25 command. */
1032 static int x25_exec(struct cycx_device *card, int command, int link,
1033 void *d1, int len1, void *d2, int len2)
1035 struct cycx_x25_cmd c;
1036 unsigned long flags;
1037 u32 addr = 0x1200 + 0x2E0 * link + 0x1E2;
1038 u8 retry = CYCX_X25_MAX_CMD_RETRY;
1041 c.command = command;
1043 c.len = len1 + len2;
1045 spin_lock_irqsave(&card->u.x.lock, flags);
1048 cycx_poke(&card->hw, X25_MBOX_OFFS, &c, sizeof(c) - sizeof(c.buf));
1050 /* write X.25 data */
1052 cycx_poke(&card->hw, addr, d1, len1);
1056 u32 addr1 = 0xA00 + 0x400 * link;
1058 cycx_poke(&card->hw, addr + len1, d2, 249);
1059 cycx_poke(&card->hw, addr1, ((u8*)d2) + 249,
1062 cycx_poke(&card->hw, addr + len1, d2, len2);
1066 /* generate interruption, executing command */
1067 cycx_intr(&card->hw);
1069 /* wait till card->mbox == 0 */
1071 err = cycx_exec(card->mbox);
1072 } while (retry-- && err);
1074 spin_unlock_irqrestore(&card->u.x.lock, flags);
1079 /* Configure adapter. */
1080 static int cycx_x25_configure(struct cycx_device *card,
1081 struct cycx_x25_config *conf)
1085 struct cycx_x25_config conf[2];
1088 memset(&x25_cmd_conf, 0, sizeof(x25_cmd_conf));
1089 x25_cmd_conf.nlinks = 2;
1090 x25_cmd_conf.conf[0] = *conf;
1091 /* FIXME: we need to find a way in the wanrouter framework
1092 to configure the second link, for now lets use it
1093 with the same config from the first link, fixing
1094 the interface type to RS232, the speed in 38400 and
1095 the clock to external */
1096 x25_cmd_conf.conf[1] = *conf;
1097 x25_cmd_conf.conf[1].link = 1;
1098 x25_cmd_conf.conf[1].speed = 5; /* 38400 */
1099 x25_cmd_conf.conf[1].clock = 8;
1100 x25_cmd_conf.conf[1].flags = 0; /* default = RS232 */
1102 cycx_x25_dump_config(&x25_cmd_conf.conf[0]);
1103 cycx_x25_dump_config(&x25_cmd_conf.conf[1]);
1105 return x25_exec(card, X25_CONFIG, 0,
1106 &x25_cmd_conf, sizeof(x25_cmd_conf), NULL, 0);
1109 /* Get protocol statistics. */
1110 static int cycx_x25_get_stats(struct cycx_device *card)
1112 /* the firmware expects 20 in the size field!!!
1113 thanks to Daniela */
1114 int err = x25_exec(card, X25_STATISTIC, 0, NULL, 20, NULL, 0);
1119 interruptible_sleep_on(&card->wait_stats);
1121 if (signal_pending(current))
1124 card->wandev.stats.rx_packets = card->u.x.stats.n2_rx_frames;
1125 card->wandev.stats.rx_over_errors = card->u.x.stats.rx_over_errors;
1126 card->wandev.stats.rx_crc_errors = card->u.x.stats.rx_crc_errors;
1127 card->wandev.stats.rx_length_errors = 0; /* not available from fw */
1128 card->wandev.stats.rx_frame_errors = 0; /* not available from fw */
1129 card->wandev.stats.rx_missed_errors = card->u.x.stats.rx_aborts;
1130 card->wandev.stats.rx_dropped = 0; /* not available from fw */
1131 card->wandev.stats.rx_errors = 0; /* not available from fw */
1132 card->wandev.stats.tx_packets = card->u.x.stats.n2_tx_frames;
1133 card->wandev.stats.tx_aborted_errors = card->u.x.stats.tx_aborts;
1134 card->wandev.stats.tx_dropped = 0; /* not available from fw */
1135 card->wandev.stats.collisions = 0; /* not available from fw */
1136 card->wandev.stats.tx_errors = 0; /* not available from fw */
1138 cycx_x25_dump_devs(&card->wandev);
1143 /* return the number of nibbles */
1144 static int byte_to_nibble(u8 *s, u8 *d, char *nibble)
1148 if (*nibble && *s) {
1155 d[i] = (*s - '0') << 4;
1157 d[i] |= *(s + 1) - '0';
1169 static void nibble_to_byte(u8 *s, u8 *d, u8 len, u8 nibble)
1172 *d++ = '0' + (*s++ & 0x0F);
1177 *d++ = '0' + (*s >> 4);
1180 *d++ = '0' + (*s & 0x0F);
1190 /* Place X.25 call. */
1191 static int x25_place_call(struct cycx_device *card,
1192 struct cycx_x25_channel *chan)
1198 mylen = chan->local_addr ? strlen(chan->local_addr) : 0,
1199 remotelen = strlen(chan->addr);
1202 if (card->u.x.connection_keys == ~0U) {
1203 printk(KERN_INFO "%s: too many simultaneous connection "
1204 "requests!\n", card->devname);
1208 key = ffz(card->u.x.connection_keys);
1209 set_bit(key, (void*)&card->u.x.connection_keys);
1211 dprintk(1, KERN_INFO "%s:x25_place_call:key=%d\n", card->devname, key);
1212 memset(d, 0, sizeof(d));
1213 d[1] = key; /* user key */
1217 len = byte_to_nibble(chan->addr, d + 6, &nibble);
1219 if (chan->local_addr)
1220 len += byte_to_nibble(chan->local_addr, d + 6 + len, &nibble);
1225 d[5] = mylen << 4 | remotelen;
1226 d[6 + len + 1] = 0xCC; /* TCP/IP over X.25, thanks to Daniela :) */
1228 if ((err = x25_exec(card, X25_CONNECT_REQUEST, chan->link,
1229 &d, 7 + len + 1, NULL, 0)) != 0)
1230 clear_bit(--key, (void*)&card->u.x.connection_keys);
1237 /* Place X.25 CONNECT RESPONSE. */
1238 static int cycx_x25_connect_response(struct cycx_device *card,
1239 struct cycx_x25_channel *chan)
1243 memset(d, 0, sizeof(d));
1244 d[0] = d[3] = chan->lcn;
1247 d[7] = 0xCC; /* TCP/IP over X.25, thanks Daniela */
1249 return x25_exec(card, X25_CONNECT_RESPONSE, chan->link, &d, 8, NULL, 0);
1252 /* Place X.25 DISCONNECT RESPONSE. */
1253 static int cycx_x25_disconnect_response(struct cycx_device *card, u8 link,
1258 memset(d, 0, sizeof(d));
1263 return x25_exec(card, X25_DISCONNECT_RESPONSE, link, &d, 5, NULL, 0);
1266 /* Clear X.25 call. */
1267 static int x25_clear_call(struct cycx_device *card, u8 link, u8 lcn, u8 cause,
1272 memset(d, 0, sizeof(d));
1279 return x25_exec(card, X25_DISCONNECT_REQUEST, link, d, 7, NULL, 0);
1282 /* Send X.25 data packet. */
1283 static int cycx_x25_send(struct cycx_device *card, u8 link, u8 lcn, u8 bitm,
1286 u8 d[] = "?\xFF\x10??";
1291 return x25_exec(card, X25_DATA_REQUEST, link, &d, 5, buf, len);
1295 /* Find network device by its channel number. */
1296 static struct net_device *cycx_x25_get_dev_by_lcn(struct wan_device *wandev,
1299 struct net_device *dev = wandev->dev;
1300 struct cycx_x25_channel *chan;
1303 chan = netdev_priv(dev);
1305 if (chan->lcn == lcn)
1312 /* Find network device by its remote dte address. */
1313 static struct net_device *
1314 cycx_x25_get_dev_by_dte_addr(struct wan_device *wandev, char *dte)
1316 struct net_device *dev = wandev->dev;
1317 struct cycx_x25_channel *chan;
1320 chan = netdev_priv(dev);
1322 if (!strcmp(chan->addr, dte))
1329 /* Initiate connection on the logical channel.
1330 * o for PVC we just get channel configuration
1331 * o for SVCs place an X.25 call
1333 * Return: 0 connected
1334 * >0 connection in progress
1336 static int cycx_x25_chan_connect(struct net_device *dev)
1338 struct cycx_x25_channel *chan = netdev_priv(dev);
1339 struct cycx_device *card = chan->card;
1343 return -EINVAL; /* no destination address */
1345 dprintk(1, KERN_INFO "%s: placing X.25 call to %s...\n",
1346 card->devname, chan->addr);
1348 if (x25_place_call(card, chan))
1351 cycx_x25_set_chan_state(dev, WAN_CONNECTING);
1354 cycx_x25_set_chan_state(dev, WAN_CONNECTED);
1359 /* Disconnect logical channel.
1360 * o if SVC then clear X.25 call */
1361 static void cycx_x25_chan_disconnect(struct net_device *dev)
1363 struct cycx_x25_channel *chan = netdev_priv(dev);
1366 x25_clear_call(chan->card, chan->link, chan->lcn, 0, 0);
1367 cycx_x25_set_chan_state(dev, WAN_DISCONNECTING);
1369 cycx_x25_set_chan_state(dev, WAN_DISCONNECTED);
1372 /* Called by kernel timer */
1373 static void cycx_x25_chan_timer(unsigned long d)
1375 struct net_device *dev = (struct net_device *)d;
1376 struct cycx_x25_channel *chan = netdev_priv(dev);
1378 if (chan->state == WAN_CONNECTED)
1379 cycx_x25_chan_disconnect(dev);
1381 printk(KERN_ERR "%s: %s for svc (%s) not connected!\n",
1382 chan->card->devname, __func__, dev->name);
1385 /* Set logical channel state. */
1386 static void cycx_x25_set_chan_state(struct net_device *dev, u8 state)
1388 struct cycx_x25_channel *chan = netdev_priv(dev);
1389 struct cycx_device *card = chan->card;
1390 unsigned long flags;
1391 char *string_state = NULL;
1393 spin_lock_irqsave(&card->lock, flags);
1395 if (chan->state != state) {
1396 if (chan->svc && chan->state == WAN_CONNECTED)
1397 del_timer(&chan->timer);
1401 string_state = "connected!";
1402 *(__be16*)dev->dev_addr = htons(chan->lcn);
1403 netif_wake_queue(dev);
1406 if (chan->protocol == ETH_P_X25)
1407 cycx_x25_chan_send_event(dev, 1);
1410 case WAN_CONNECTING:
1411 string_state = "connecting...";
1413 case WAN_DISCONNECTING:
1414 string_state = "disconnecting...";
1416 case WAN_DISCONNECTED:
1417 string_state = "disconnected!";
1420 *(unsigned short*)dev->dev_addr = 0;
1424 if (chan->protocol == ETH_P_X25)
1425 cycx_x25_chan_send_event(dev, 2);
1427 netif_wake_queue(dev);
1431 printk(KERN_INFO "%s: interface %s %s\n", card->devname,
1432 dev->name, string_state);
1433 chan->state = state;
1436 spin_unlock_irqrestore(&card->lock, flags);
1439 /* Send packet on a logical channel.
1440 * When this function is called, tx_skb field of the channel data space
1441 * points to the transmit socket buffer. When transmission is complete,
1442 * release socket buffer and reset 'tbusy' flag.
1444 * Return: 0 - transmission complete
1448 * 1. If packet length is greater than MTU for this channel, we'll fragment
1449 * the packet into 'complete sequence' using M-bit.
1450 * 2. When transmission is complete, an event notification should be issued
1452 static int cycx_x25_chan_send(struct net_device *dev, struct sk_buff *skb)
1454 struct cycx_x25_channel *chan = netdev_priv(dev);
1455 struct cycx_device *card = chan->card;
1456 int bitm = 0; /* final packet */
1457 unsigned len = skb->len;
1459 if (skb->len > card->wandev.mtu) {
1460 len = card->wandev.mtu;
1461 bitm = 0x10; /* set M-bit (more data) */
1464 if (cycx_x25_send(card, chan->link, chan->lcn, bitm, len, skb->data))
1472 ++chan->ifstats.tx_packets;
1473 chan->ifstats.tx_bytes += len;
1478 /* Send event (connection, disconnection, etc) to X.25 socket layer */
1480 static void cycx_x25_chan_send_event(struct net_device *dev, u8 event)
1482 struct sk_buff *skb;
1485 if ((skb = dev_alloc_skb(1)) == NULL) {
1486 printk(KERN_ERR "%s: out of memory\n", __func__);
1490 ptr = skb_put(skb, 1);
1493 skb->protocol = x25_type_trans(skb, dev);
1497 /* Convert line speed in bps to a number used by cyclom 2x code. */
1498 static u8 bps_to_speed_code(u32 bps)
1500 u8 number = 0; /* defaults to the lowest (1200) speed ;> */
1502 if (bps >= 512000) number = 8;
1503 else if (bps >= 256000) number = 7;
1504 else if (bps >= 64000) number = 6;
1505 else if (bps >= 38400) number = 5;
1506 else if (bps >= 19200) number = 4;
1507 else if (bps >= 9600) number = 3;
1508 else if (bps >= 4800) number = 2;
1509 else if (bps >= 2400) number = 1;
1515 static u8 cycx_log2(u32 n)
1530 /* Convert decimal string to unsigned integer.
1531 * If len != 0 then only 'len' characters of the string are converted. */
1532 static unsigned dec_to_uint(u8 *str, int len)
1539 for (; len && isdigit(*str); ++str, --len)
1540 val = (val * 10) + (*str - (unsigned) '0');
1545 static void reset_timer(struct net_device *dev)
1547 struct cycx_x25_channel *chan = netdev_priv(dev);
1550 mod_timer(&chan->timer, jiffies+chan->idle_tmout*HZ);
1552 #ifdef CYCLOMX_X25_DEBUG
1553 static void cycx_x25_dump_config(struct cycx_x25_config *conf)
1555 printk(KERN_INFO "X.25 configuration\n");
1556 printk(KERN_INFO "-----------------\n");
1557 printk(KERN_INFO "link number=%d\n", conf->link);
1558 printk(KERN_INFO "line speed=%d\n", conf->speed);
1559 printk(KERN_INFO "clock=%sternal\n", conf->clock == 8 ? "Ex" : "In");
1560 printk(KERN_INFO "# level 2 retransm.=%d\n", conf->n2);
1561 printk(KERN_INFO "level 2 window=%d\n", conf->n2win);
1562 printk(KERN_INFO "level 3 window=%d\n", conf->n3win);
1563 printk(KERN_INFO "# logical channels=%d\n", conf->nvc);
1564 printk(KERN_INFO "level 3 pkt len=%d\n", conf->pktlen);
1565 printk(KERN_INFO "my address=%d\n", conf->locaddr);
1566 printk(KERN_INFO "remote address=%d\n", conf->remaddr);
1567 printk(KERN_INFO "t1=%d seconds\n", conf->t1);
1568 printk(KERN_INFO "t2=%d seconds\n", conf->t2);
1569 printk(KERN_INFO "t21=%d seconds\n", conf->t21);
1570 printk(KERN_INFO "# PVCs=%d\n", conf->npvc);
1571 printk(KERN_INFO "t23=%d seconds\n", conf->t23);
1572 printk(KERN_INFO "flags=0x%x\n", conf->flags);
1575 static void cycx_x25_dump_stats(struct cycx_x25_stats *stats)
1577 printk(KERN_INFO "X.25 statistics\n");
1578 printk(KERN_INFO "--------------\n");
1579 printk(KERN_INFO "rx_crc_errors=%d\n", stats->rx_crc_errors);
1580 printk(KERN_INFO "rx_over_errors=%d\n", stats->rx_over_errors);
1581 printk(KERN_INFO "n2_tx_frames=%d\n", stats->n2_tx_frames);
1582 printk(KERN_INFO "n2_rx_frames=%d\n", stats->n2_rx_frames);
1583 printk(KERN_INFO "tx_timeouts=%d\n", stats->tx_timeouts);
1584 printk(KERN_INFO "rx_timeouts=%d\n", stats->rx_timeouts);
1585 printk(KERN_INFO "n3_tx_packets=%d\n", stats->n3_tx_packets);
1586 printk(KERN_INFO "n3_rx_packets=%d\n", stats->n3_rx_packets);
1587 printk(KERN_INFO "tx_aborts=%d\n", stats->tx_aborts);
1588 printk(KERN_INFO "rx_aborts=%d\n", stats->rx_aborts);
1591 static void cycx_x25_dump_devs(struct wan_device *wandev)
1593 struct net_device *dev = wandev->dev;
1595 printk(KERN_INFO "X.25 dev states\n");
1596 printk(KERN_INFO "name: addr: txoff: protocol:\n");
1597 printk(KERN_INFO "---------------------------------------\n");
1600 struct cycx_x25_channel *chan = netdev_priv(dev);
1602 printk(KERN_INFO "%-5.5s %-15.15s %d ETH_P_%s\n",
1603 chan->name, chan->addr, netif_queue_stopped(dev),
1604 chan->protocol == ETH_P_IP ? "IP" : "X25");
1609 #endif /* CYCLOMX_X25_DEBUG */