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 cycx_netdevice_open(struct net_device *dev),
136 cycx_netdevice_stop(struct net_device *dev),
137 cycx_netdevice_hard_header(struct sk_buff *skb,
138 struct net_device *dev, u16 type,
139 void *daddr, void *saddr, unsigned len),
140 cycx_netdevice_rebuild_header(struct sk_buff *skb),
141 cycx_netdevice_hard_start_xmit(struct sk_buff *skb,
142 struct net_device *dev);
144 static struct net_device_stats *
145 cycx_netdevice_get_stats(struct net_device *dev);
147 /* Interrupt handlers */
148 static void cycx_x25_irq_handler(struct cycx_device *card),
149 cycx_x25_irq_tx(struct cycx_device *card, struct cycx_x25_cmd *cmd),
150 cycx_x25_irq_rx(struct cycx_device *card, struct cycx_x25_cmd *cmd),
151 cycx_x25_irq_log(struct cycx_device *card,
152 struct cycx_x25_cmd *cmd),
153 cycx_x25_irq_stat(struct cycx_device *card,
154 struct cycx_x25_cmd *cmd),
155 cycx_x25_irq_connect_confirm(struct cycx_device *card,
156 struct cycx_x25_cmd *cmd),
157 cycx_x25_irq_disconnect_confirm(struct cycx_device *card,
158 struct cycx_x25_cmd *cmd),
159 cycx_x25_irq_connect(struct cycx_device *card,
160 struct cycx_x25_cmd *cmd),
161 cycx_x25_irq_disconnect(struct cycx_device *card,
162 struct cycx_x25_cmd *cmd),
163 cycx_x25_irq_spurious(struct cycx_device *card,
164 struct cycx_x25_cmd *cmd);
166 /* X.25 firmware interface functions */
167 static int cycx_x25_configure(struct cycx_device *card,
168 struct cycx_x25_config *conf),
169 cycx_x25_get_stats(struct cycx_device *card),
170 cycx_x25_send(struct cycx_device *card, u8 link, u8 lcn, u8 bitm,
172 cycx_x25_connect_response(struct cycx_device *card,
173 struct cycx_x25_channel *chan),
174 cycx_x25_disconnect_response(struct cycx_device *card, u8 link,
177 /* channel functions */
178 static int cycx_x25_chan_connect(struct net_device *dev),
179 cycx_x25_chan_send(struct net_device *dev, struct sk_buff *skb);
181 static void cycx_x25_chan_disconnect(struct net_device *dev),
182 cycx_x25_chan_send_event(struct net_device *dev, u8 event);
184 /* Miscellaneous functions */
185 static void cycx_x25_set_chan_state(struct net_device *dev, u8 state),
186 cycx_x25_chan_timer(unsigned long d);
188 static void nibble_to_byte(u8 *s, u8 *d, u8 len, u8 nibble),
189 reset_timer(struct net_device *dev);
191 static u8 bps_to_speed_code(u32 bps);
192 static u8 cycx_log2(u32 n);
194 static unsigned dec_to_uint(u8 *str, int len);
196 static struct net_device *cycx_x25_get_dev_by_lcn(struct wan_device *wandev,
198 static struct net_device *
199 cycx_x25_get_dev_by_dte_addr(struct wan_device *wandev, char *dte);
201 #ifdef CYCLOMX_X25_DEBUG
202 static void hex_dump(char *msg, unsigned char *p, int len);
203 static void cycx_x25_dump_config(struct cycx_x25_config *conf);
204 static void cycx_x25_dump_stats(struct cycx_x25_stats *stats);
205 static void cycx_x25_dump_devs(struct wan_device *wandev);
207 #define hex_dump(msg, p, len)
208 #define cycx_x25_dump_config(conf)
209 #define cycx_x25_dump_stats(stats)
210 #define cycx_x25_dump_devs(wandev)
212 /* Public Functions */
214 /* X.25 Protocol Initialization routine.
216 * This routine is called by the main Cyclom 2X module during setup. At this
217 * point adapter is completely initialized and X.25 firmware is running.
218 * o configure adapter
219 * o initialize protocol-specific fields of the adapter data space.
223 int cycx_x25_wan_init(struct cycx_device *card, wandev_conf_t *conf)
225 struct cycx_x25_config cfg;
227 /* Verify configuration ID */
228 if (conf->config_id != WANCONFIG_X25) {
229 printk(KERN_INFO "%s: invalid configuration ID %u!\n",
230 card->devname, conf->config_id);
234 /* Initialize protocol-specific fields */
235 card->mbox = card->hw.dpmbase + X25_MBOX_OFFS;
236 card->u.x.connection_keys = 0;
237 spin_lock_init(&card->u.x.lock);
239 /* Configure adapter. Here we set reasonable defaults, then parse
240 * device configuration structure and set configuration options.
241 * Most configuration options are verified and corrected (if
242 * necessary) since we can't rely on the adapter to do so and don't
243 * want it to fail either. */
244 memset(&cfg, 0, sizeof(cfg));
246 cfg.clock = conf->clocking == WANOPT_EXTERNAL ? 8 : 55;
247 cfg.speed = bps_to_speed_code(conf->bps);
253 cfg.flags = 0x02; /* default = V35 */
254 cfg.t1 = 10; /* line carrier timeout */
255 cfg.t2 = 29; /* tx timeout */
256 cfg.t21 = 180; /* CALL timeout */
257 cfg.t23 = 180; /* CLEAR timeout */
260 if (!conf->mtu || conf->mtu >= 512)
261 card->wandev.mtu = 512;
262 else if (conf->mtu >= 256)
263 card->wandev.mtu = 256;
264 else if (conf->mtu >= 128)
265 card->wandev.mtu = 128;
267 card->wandev.mtu = 64;
269 cfg.pktlen = cycx_log2(card->wandev.mtu);
271 if (conf->station == WANOPT_DTE) {
272 cfg.locaddr = 3; /* DTE */
273 cfg.remaddr = 1; /* DCE */
275 cfg.locaddr = 1; /* DCE */
276 cfg.remaddr = 3; /* DTE */
279 if (conf->interface == WANOPT_RS232)
280 cfg.flags = 0; /* FIXME just reset the 2nd bit */
282 if (conf->u.x25.hi_pvc) {
283 card->u.x.hi_pvc = min_t(unsigned int, conf->u.x25.hi_pvc, 4095);
284 card->u.x.lo_pvc = min_t(unsigned int, conf->u.x25.lo_pvc, card->u.x.hi_pvc);
287 if (conf->u.x25.hi_svc) {
288 card->u.x.hi_svc = min_t(unsigned int, conf->u.x25.hi_svc, 4095);
289 card->u.x.lo_svc = min_t(unsigned int, conf->u.x25.lo_svc, card->u.x.hi_svc);
292 if (card->u.x.lo_pvc == 255)
295 cfg.npvc = card->u.x.hi_pvc - card->u.x.lo_pvc + 1;
297 cfg.nvc = card->u.x.hi_svc - card->u.x.lo_svc + 1 + cfg.npvc;
299 if (conf->u.x25.hdlc_window)
300 cfg.n2win = min_t(unsigned int, conf->u.x25.hdlc_window, 7);
302 if (conf->u.x25.pkt_window)
303 cfg.n3win = min_t(unsigned int, conf->u.x25.pkt_window, 7);
306 cfg.t1 = min_t(unsigned int, conf->u.x25.t1, 30);
309 cfg.t2 = min_t(unsigned int, conf->u.x25.t2, 30);
311 if (conf->u.x25.t11_t21)
312 cfg.t21 = min_t(unsigned int, conf->u.x25.t11_t21, 30);
314 if (conf->u.x25.t13_t23)
315 cfg.t23 = min_t(unsigned int, conf->u.x25.t13_t23, 30);
318 cfg.n2 = min_t(unsigned int, conf->u.x25.n2, 30);
320 /* initialize adapter */
321 if (cycx_x25_configure(card, &cfg))
324 /* Initialize protocol-specific fields of adapter data space */
325 card->wandev.bps = conf->bps;
326 card->wandev.interface = conf->interface;
327 card->wandev.clocking = conf->clocking;
328 card->wandev.station = conf->station;
329 card->isr = cycx_x25_irq_handler;
331 card->wandev.update = cycx_wan_update;
332 card->wandev.new_if = cycx_wan_new_if;
333 card->wandev.del_if = cycx_wan_del_if;
334 card->wandev.state = WAN_DISCONNECTED;
339 /* WAN Device Driver Entry Points */
340 /* Update device status & statistics. */
341 static int cycx_wan_update(struct wan_device *wandev)
344 if (!wandev || !wandev->private)
347 if (wandev->state == WAN_UNCONFIGURED)
350 cycx_x25_get_stats(wandev->private);
355 /* Create new logical channel.
356 * This routine is called by the router when ROUTER_IFNEW IOCTL is being
358 * o parse media- and hardware-specific configuration
359 * o make sure that a new channel can be created
360 * o allocate resources, if necessary
361 * o prepare network device structure for registration.
364 * < 0 failure (channel will not be created) */
365 static int cycx_wan_new_if(struct wan_device *wandev, struct net_device *dev,
368 struct cycx_device *card = wandev->private;
369 struct cycx_x25_channel *chan;
372 if (!conf->name[0] || strlen(conf->name) > WAN_IFNAME_SZ) {
373 printk(KERN_INFO "%s: invalid interface name!\n",
378 /* allocate and initialize private data */
379 chan = kzalloc(sizeof(struct cycx_x25_channel), GFP_KERNEL);
383 strcpy(chan->name, conf->name);
385 chan->link = conf->port;
386 chan->protocol = conf->protocol ? ETH_P_X25 : ETH_P_IP;
388 /* only used in svc connected thru crossover cable */
389 chan->local_addr = NULL;
391 if (conf->addr[0] == '@') { /* SVC */
392 int len = strlen(conf->local_addr);
395 if (len > WAN_ADDRESS_SZ) {
396 printk(KERN_ERR "%s: %s local addr too long!\n",
397 wandev->name, chan->name);
401 chan->local_addr = kmalloc(len + 1, GFP_KERNEL);
403 if (!chan->local_addr) {
409 strncpy(chan->local_addr, conf->local_addr,
414 strncpy(chan->addr, &conf->addr[1], WAN_ADDRESS_SZ);
415 init_timer(&chan->timer);
416 chan->timer.function = cycx_x25_chan_timer;
417 chan->timer.data = (unsigned long)dev;
419 /* Set channel timeouts (default if not specified) */
420 chan->idle_tmout = conf->idle_timeout ? conf->idle_timeout : 90;
421 } else if (isdigit(conf->addr[0])) { /* PVC */
422 s16 lcn = dec_to_uint(conf->addr, 0);
424 if (lcn >= card->u.x.lo_pvc && lcn <= card->u.x.hi_pvc)
428 "%s: PVC %u is out of range on interface %s!\n",
429 wandev->name, lcn, chan->name);
433 printk(KERN_ERR "%s: invalid media address on interface %s!\n",
434 wandev->name, chan->name);
439 kfree(chan->local_addr);
444 /* prepare network device data space for registration */
445 strcpy(dev->name, chan->name);
446 dev->init = cycx_netdevice_init;
452 /* Delete logical channel. */
453 static int cycx_wan_del_if(struct wan_device *wandev, struct net_device *dev)
456 struct cycx_x25_channel *chan = dev->priv;
459 kfree(chan->local_addr);
460 if (chan->state == WAN_CONNECTED)
461 del_timer(&chan->timer);
471 /* Network Device Interface */
472 /* Initialize Linux network interface.
474 * This routine is called only once for each interface, during Linux network
475 * interface registration. Returning anything but zero will fail interface
477 static int cycx_netdevice_init(struct net_device *dev)
479 struct cycx_x25_channel *chan = dev->priv;
480 struct cycx_device *card = chan->card;
481 struct wan_device *wandev = &card->wandev;
483 /* Initialize device driver entry points */
484 dev->open = cycx_netdevice_open;
485 dev->stop = cycx_netdevice_stop;
486 dev->hard_header = cycx_netdevice_hard_header;
487 dev->rebuild_header = cycx_netdevice_rebuild_header;
488 dev->hard_start_xmit = cycx_netdevice_hard_start_xmit;
489 dev->get_stats = cycx_netdevice_get_stats;
491 /* Initialize media-specific parameters */
492 dev->mtu = CYCX_X25_CHAN_MTU;
493 dev->type = ARPHRD_HWX25; /* ARP h/w type */
494 dev->hard_header_len = 0; /* media header length */
495 dev->addr_len = 0; /* hardware address length */
498 *(u16*)dev->dev_addr = htons(chan->lcn);
500 /* Initialize hardware parameters (just for reference) */
501 dev->irq = wandev->irq;
502 dev->dma = wandev->dma;
503 dev->base_addr = wandev->ioport;
504 dev->mem_start = (unsigned long)wandev->maddr;
505 dev->mem_end = (unsigned long)(wandev->maddr +
507 dev->flags |= IFF_NOARP;
509 /* Set transmit buffer queue length */
510 dev->tx_queue_len = 10;
512 /* Initialize socket buffers */
513 cycx_x25_set_chan_state(dev, WAN_DISCONNECTED);
518 /* Open network interface.
519 * o prevent module from unloading by incrementing use count
520 * o if link is disconnected then initiate connection
522 * Return 0 if O.k. or errno. */
523 static int cycx_netdevice_open(struct net_device *dev)
525 if (netif_running(dev))
526 return -EBUSY; /* only one open is allowed */
528 netif_start_queue(dev);
532 /* Close network interface.
534 * o if there's no more open channels then disconnect physical link. */
535 static int cycx_netdevice_stop(struct net_device *dev)
537 struct cycx_x25_channel *chan = dev->priv;
539 netif_stop_queue(dev);
541 if (chan->state == WAN_CONNECTED || chan->state == WAN_CONNECTING)
542 cycx_x25_chan_disconnect(dev);
547 /* Build media header.
548 * o encapsulate packet according to encapsulation type.
550 * The trick here is to put packet type (Ethertype) into 'protocol' field of
551 * the socket buffer, so that we don't forget it. If encapsulation fails,
552 * set skb->protocol to 0 and discard packet later.
554 * Return: media header length. */
555 static int cycx_netdevice_hard_header(struct sk_buff *skb,
556 struct net_device *dev, u16 type,
557 void *daddr, void *saddr, unsigned len)
559 skb->protocol = type;
561 return dev->hard_header_len;
564 /* * Re-build media header.
565 * Return: 1 physical address resolved.
566 * 0 physical address not resolved */
567 static int cycx_netdevice_rebuild_header(struct sk_buff *skb)
572 /* Send a packet on a network interface.
573 * o set busy flag (marks start of the transmission).
574 * o check link state. If link is not up, then drop the packet.
575 * o check channel status. If it's down then initiate a call.
576 * o pass a packet to corresponding WAN device.
577 * o free socket buffer
579 * Return: 0 complete (socket buffer must be freed)
580 * non-0 packet may be re-transmitted (tbusy must be set)
583 * 1. This routine is called either by the protocol stack or by the "net
584 * bottom half" (with interrupts enabled).
585 * 2. Setting tbusy flag will inhibit further transmit requests from the
586 * protocol stack and can be used for flow control with protocol layer. */
587 static int cycx_netdevice_hard_start_xmit(struct sk_buff *skb,
588 struct net_device *dev)
590 struct cycx_x25_channel *chan = dev->priv;
591 struct cycx_device *card = chan->card;
594 chan->protocol = skb->protocol;
596 if (card->wandev.state != WAN_CONNECTED)
597 ++chan->ifstats.tx_dropped;
598 else if (chan->svc && chan->protocol &&
599 chan->protocol != skb->protocol) {
601 "%s: unsupported Ethertype 0x%04X on interface %s!\n",
602 card->devname, skb->protocol, dev->name);
603 ++chan->ifstats.tx_errors;
604 } else if (chan->protocol == ETH_P_IP) {
605 switch (chan->state) {
606 case WAN_DISCONNECTED:
607 if (cycx_x25_chan_connect(dev)) {
608 netif_stop_queue(dev);
614 dev->trans_start = jiffies;
615 netif_stop_queue(dev);
617 if (cycx_x25_chan_send(dev, skb))
622 ++chan->ifstats.tx_dropped;
623 ++card->wandev.stats.tx_dropped;
625 } else { /* chan->protocol == ETH_P_X25 */
626 switch (skb->data[0]) {
628 case 1: /* Connect request */
629 cycx_x25_chan_connect(dev);
631 case 2: /* Disconnect request */
632 cycx_x25_chan_disconnect(dev);
636 "%s: unknown %d x25-iface request on %s!\n",
637 card->devname, skb->data[0], dev->name);
638 ++chan->ifstats.tx_errors;
642 skb_pull(skb, 1); /* Remove control byte */
644 dev->trans_start = jiffies;
645 netif_stop_queue(dev);
647 if (cycx_x25_chan_send(dev, skb)) {
648 /* prepare for future retransmissions */
660 /* Get Ethernet-style interface statistics.
661 * Return a pointer to struct net_device_stats */
662 static struct net_device_stats *cycx_netdevice_get_stats(struct net_device *dev)
664 struct cycx_x25_channel *chan = dev->priv;
666 return chan ? &chan->ifstats : NULL;
669 /* Interrupt Handlers */
670 /* X.25 Interrupt Service Routine. */
671 static void cycx_x25_irq_handler(struct cycx_device *card)
673 struct cycx_x25_cmd cmd;
677 card->buff_int_mode_unbusy = 0;
678 cycx_peek(&card->hw, X25_RXMBOX_OFFS, &cmd, sizeof(cmd));
680 switch (cmd.command) {
681 case X25_DATA_INDICATION:
682 cycx_x25_irq_rx(card, &cmd);
684 case X25_ACK_FROM_VC:
685 cycx_x25_irq_tx(card, &cmd);
688 cycx_x25_irq_log(card, &cmd);
691 cycx_x25_irq_stat(card, &cmd);
693 case X25_CONNECT_CONFIRM:
694 cycx_x25_irq_connect_confirm(card, &cmd);
696 case X25_CONNECT_INDICATION:
697 cycx_x25_irq_connect(card, &cmd);
699 case X25_DISCONNECT_INDICATION:
700 cycx_x25_irq_disconnect(card, &cmd);
702 case X25_DISCONNECT_CONFIRM:
703 cycx_x25_irq_disconnect_confirm(card, &cmd);
706 cycx_set_state(card, WAN_CONNECTED);
709 cycx_set_state(card, WAN_DISCONNECTED);
712 cycx_x25_irq_spurious(card, &cmd);
716 cycx_poke(&card->hw, 0, &z, sizeof(z));
717 cycx_poke(&card->hw, X25_RXMBOX_OFFS, &z, sizeof(z));
721 /* Transmit interrupt handler.
722 * o Release socket buffer
723 * o Clear 'tbusy' flag */
724 static void cycx_x25_irq_tx(struct cycx_device *card, struct cycx_x25_cmd *cmd)
726 struct net_device *dev;
727 struct wan_device *wandev = &card->wandev;
730 cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
732 /* unbusy device and then dev_tint(); */
733 dev = cycx_x25_get_dev_by_lcn(wandev, lcn);
735 card->buff_int_mode_unbusy = 1;
736 netif_wake_queue(dev);
738 printk(KERN_ERR "%s:ackvc for inexistent lcn %d\n",
742 /* Receive interrupt handler.
743 * This routine handles fragmented IP packets using M-bit according to the
745 * o map logical channel number to network interface.
746 * o allocate socket buffer or append received packet to the existing one.
747 * o if M-bit is reset (i.e. it's the last packet in a sequence) then
748 * decapsulate packet and pass socket buffer to the protocol stack.
751 * 1. When allocating a socket buffer, if M-bit is set then more data is
752 * coming and we have to allocate buffer for the maximum IP packet size
753 * expected on this channel.
754 * 2. If something goes wrong and X.25 packet has to be dropped (e.g. no
755 * socket buffers available) the whole packet sequence must be discarded. */
756 static void cycx_x25_irq_rx(struct cycx_device *card, struct cycx_x25_cmd *cmd)
758 struct wan_device *wandev = &card->wandev;
759 struct net_device *dev;
760 struct cycx_x25_channel *chan;
763 int pktlen = cmd->len - 5;
765 cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
766 cycx_peek(&card->hw, cmd->buf + 4, &bitm, sizeof(bitm));
769 dev = cycx_x25_get_dev_by_lcn(wandev, lcn);
771 /* Invalid channel, discard packet */
772 printk(KERN_INFO "%s: receiving on orphaned LCN %d!\n",
780 if (chan->drop_sequence) {
782 chan->drop_sequence = 0;
787 if ((skb = chan->rx_skb) == NULL) {
788 /* Allocate new socket buffer */
789 int bufsize = bitm ? dev->mtu : pktlen;
791 if ((skb = dev_alloc_skb((chan->protocol == ETH_P_X25 ? 1 : 0) +
793 dev->hard_header_len)) == NULL) {
794 printk(KERN_INFO "%s: no socket buffers available!\n",
796 chan->drop_sequence = 1;
797 ++chan->ifstats.rx_dropped;
801 if (chan->protocol == ETH_P_X25) /* X.25 socket layer control */
802 /* 0 = data packet (dev_alloc_skb zeroed skb->data) */
806 skb->protocol = htons(chan->protocol);
810 if (skb_tailroom(skb) < pktlen) {
811 /* No room for the packet. Call off the whole thing! */
812 dev_kfree_skb_irq(skb);
816 chan->drop_sequence = 1;
818 printk(KERN_INFO "%s: unexpectedly long packet sequence "
819 "on interface %s!\n", card->devname, dev->name);
820 ++chan->ifstats.rx_length_errors;
824 /* Append packet to the socket buffer */
825 cycx_peek(&card->hw, cmd->buf + 5, skb_put(skb, pktlen), pktlen);
828 return; /* more data is coming */
830 chan->rx_skb = NULL; /* dequeue packet */
832 ++chan->ifstats.rx_packets;
833 chan->ifstats.rx_bytes += pktlen;
835 skb_reset_mac_header(skb);
837 dev->last_rx = jiffies; /* timestamp */
840 /* Connect interrupt handler. */
841 static void cycx_x25_irq_connect(struct cycx_device *card,
842 struct cycx_x25_cmd *cmd)
844 struct wan_device *wandev = &card->wandev;
845 struct net_device *dev = NULL;
846 struct cycx_x25_channel *chan;
850 u8 lcn, sizeloc, sizerem;
852 cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
853 cycx_peek(&card->hw, cmd->buf + 5, &sizeloc, sizeof(sizeloc));
854 cycx_peek(&card->hw, cmd->buf + 6, d, cmd->len - 6);
856 sizerem = sizeloc >> 4;
859 loc[0] = rem[0] = '\0';
862 nibble_to_byte(d, loc, sizeloc, 0);
865 nibble_to_byte(d + (sizeloc >> 1), rem, sizerem, sizeloc & 1);
867 dprintk(1, KERN_INFO "%s:lcn=%d, local=%s, remote=%s\n",
868 __FUNCTION__, lcn, loc, rem);
870 dev = cycx_x25_get_dev_by_dte_addr(wandev, rem);
872 /* Invalid channel, discard packet */
873 printk(KERN_INFO "%s: connect not expected: remote %s!\n",
880 cycx_x25_connect_response(card, chan);
881 cycx_x25_set_chan_state(dev, WAN_CONNECTED);
884 /* Connect confirm interrupt handler. */
885 static void cycx_x25_irq_connect_confirm(struct cycx_device *card,
886 struct cycx_x25_cmd *cmd)
888 struct wan_device *wandev = &card->wandev;
889 struct net_device *dev;
890 struct cycx_x25_channel *chan;
893 cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
894 cycx_peek(&card->hw, cmd->buf + 1, &key, sizeof(key));
895 dprintk(1, KERN_INFO "%s: %s:lcn=%d, key=%d\n",
896 card->devname, __FUNCTION__, lcn, key);
898 dev = cycx_x25_get_dev_by_lcn(wandev, -key);
900 /* Invalid channel, discard packet */
901 clear_bit(--key, (void*)&card->u.x.connection_keys);
902 printk(KERN_INFO "%s: connect confirm not expected: lcn %d, "
903 "key=%d!\n", card->devname, lcn, key);
907 clear_bit(--key, (void*)&card->u.x.connection_keys);
910 cycx_x25_set_chan_state(dev, WAN_CONNECTED);
913 /* Disconnect confirm interrupt handler. */
914 static void cycx_x25_irq_disconnect_confirm(struct cycx_device *card,
915 struct cycx_x25_cmd *cmd)
917 struct wan_device *wandev = &card->wandev;
918 struct net_device *dev;
921 cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
922 dprintk(1, KERN_INFO "%s: %s:lcn=%d\n",
923 card->devname, __FUNCTION__, lcn);
924 dev = cycx_x25_get_dev_by_lcn(wandev, lcn);
926 /* Invalid channel, discard packet */
927 printk(KERN_INFO "%s:disconnect confirm not expected!:lcn %d\n",
932 cycx_x25_set_chan_state(dev, WAN_DISCONNECTED);
935 /* disconnect interrupt handler. */
936 static void cycx_x25_irq_disconnect(struct cycx_device *card,
937 struct cycx_x25_cmd *cmd)
939 struct wan_device *wandev = &card->wandev;
940 struct net_device *dev;
943 cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
944 dprintk(1, KERN_INFO "%s:lcn=%d\n", __FUNCTION__, lcn);
946 dev = cycx_x25_get_dev_by_lcn(wandev, lcn);
948 struct cycx_x25_channel *chan = dev->priv;
950 cycx_x25_disconnect_response(card, chan->link, lcn);
951 cycx_x25_set_chan_state(dev, WAN_DISCONNECTED);
953 cycx_x25_disconnect_response(card, 0, lcn);
956 /* LOG interrupt handler. */
957 static void cycx_x25_irq_log(struct cycx_device *card, struct cycx_x25_cmd *cmd)
959 #if CYCLOMX_X25_DEBUG
961 u16 size, toread, link, msg_code;
964 cycx_peek(&card->hw, cmd->buf, &msg_code, sizeof(msg_code));
965 cycx_peek(&card->hw, cmd->buf + 2, &link, sizeof(link));
966 cycx_peek(&card->hw, cmd->buf + 4, &size, sizeof(size));
967 /* at most 20 bytes are available... thanks to Daniela :) */
968 toread = size < 20 ? size : 20;
969 cycx_peek(&card->hw, cmd->buf + 10, &bf, toread);
970 cycx_peek(&card->hw, cmd->buf + 10 + toread, &code, 1);
971 cycx_peek(&card->hw, cmd->buf + 10 + toread + 1, &routine, 1);
973 printk(KERN_INFO "cycx_x25_irq_handler: X25_LOG (0x4500) indic.:\n");
974 printk(KERN_INFO "cmd->buf=0x%X\n", cmd->buf);
975 printk(KERN_INFO "Log message code=0x%X\n", msg_code);
976 printk(KERN_INFO "Link=%d\n", link);
977 printk(KERN_INFO "log code=0x%X\n", code);
978 printk(KERN_INFO "log routine=0x%X\n", routine);
979 printk(KERN_INFO "Message size=%d\n", size);
980 hex_dump("Message", bf, toread);
984 /* STATISTIC interrupt handler. */
985 static void cycx_x25_irq_stat(struct cycx_device *card,
986 struct cycx_x25_cmd *cmd)
988 cycx_peek(&card->hw, cmd->buf, &card->u.x.stats,
989 sizeof(card->u.x.stats));
990 hex_dump("cycx_x25_irq_stat", (unsigned char*)&card->u.x.stats,
991 sizeof(card->u.x.stats));
992 cycx_x25_dump_stats(&card->u.x.stats);
993 wake_up_interruptible(&card->wait_stats);
996 /* Spurious interrupt handler.
998 * If number of spurious interrupts exceeded some limit, then ??? */
999 static void cycx_x25_irq_spurious(struct cycx_device *card,
1000 struct cycx_x25_cmd *cmd)
1002 printk(KERN_INFO "%s: spurious interrupt (0x%X)!\n",
1003 card->devname, cmd->command);
1005 #ifdef CYCLOMX_X25_DEBUG
1006 static void hex_dump(char *msg, unsigned char *p, int len)
1008 unsigned char hex[1024],
1011 if (len >= (sizeof(hex) / 2))
1012 len = (sizeof(hex) / 2) - 1;
1015 sprintf(phex, "%02x", *p++);
1019 printk(KERN_INFO "%s: %s\n", msg, hex);
1023 /* Cyclom 2X Firmware-Specific Functions */
1024 /* Exec X.25 command. */
1025 static int x25_exec(struct cycx_device *card, int command, int link,
1026 void *d1, int len1, void *d2, int len2)
1028 struct cycx_x25_cmd c;
1029 unsigned long flags;
1030 u32 addr = 0x1200 + 0x2E0 * link + 0x1E2;
1031 u8 retry = CYCX_X25_MAX_CMD_RETRY;
1034 c.command = command;
1036 c.len = len1 + len2;
1038 spin_lock_irqsave(&card->u.x.lock, flags);
1041 cycx_poke(&card->hw, X25_MBOX_OFFS, &c, sizeof(c) - sizeof(c.buf));
1043 /* write X.25 data */
1045 cycx_poke(&card->hw, addr, d1, len1);
1049 u32 addr1 = 0xA00 + 0x400 * link;
1051 cycx_poke(&card->hw, addr + len1, d2, 249);
1052 cycx_poke(&card->hw, addr1, ((u8*)d2) + 249,
1055 cycx_poke(&card->hw, addr + len1, d2, len2);
1059 /* generate interruption, executing command */
1060 cycx_intr(&card->hw);
1062 /* wait till card->mbox == 0 */
1064 err = cycx_exec(card->mbox);
1065 } while (retry-- && err);
1067 spin_unlock_irqrestore(&card->u.x.lock, flags);
1072 /* Configure adapter. */
1073 static int cycx_x25_configure(struct cycx_device *card,
1074 struct cycx_x25_config *conf)
1078 struct cycx_x25_config conf[2];
1081 memset(&x25_cmd_conf, 0, sizeof(x25_cmd_conf));
1082 x25_cmd_conf.nlinks = 2;
1083 x25_cmd_conf.conf[0] = *conf;
1084 /* FIXME: we need to find a way in the wanrouter framework
1085 to configure the second link, for now lets use it
1086 with the same config from the first link, fixing
1087 the interface type to RS232, the speed in 38400 and
1088 the clock to external */
1089 x25_cmd_conf.conf[1] = *conf;
1090 x25_cmd_conf.conf[1].link = 1;
1091 x25_cmd_conf.conf[1].speed = 5; /* 38400 */
1092 x25_cmd_conf.conf[1].clock = 8;
1093 x25_cmd_conf.conf[1].flags = 0; /* default = RS232 */
1095 cycx_x25_dump_config(&x25_cmd_conf.conf[0]);
1096 cycx_x25_dump_config(&x25_cmd_conf.conf[1]);
1098 return x25_exec(card, X25_CONFIG, 0,
1099 &x25_cmd_conf, sizeof(x25_cmd_conf), NULL, 0);
1102 /* Get protocol statistics. */
1103 static int cycx_x25_get_stats(struct cycx_device *card)
1105 /* the firmware expects 20 in the size field!!!
1106 thanks to Daniela */
1107 int err = x25_exec(card, X25_STATISTIC, 0, NULL, 20, NULL, 0);
1112 interruptible_sleep_on(&card->wait_stats);
1114 if (signal_pending(current))
1117 card->wandev.stats.rx_packets = card->u.x.stats.n2_rx_frames;
1118 card->wandev.stats.rx_over_errors = card->u.x.stats.rx_over_errors;
1119 card->wandev.stats.rx_crc_errors = card->u.x.stats.rx_crc_errors;
1120 card->wandev.stats.rx_length_errors = 0; /* not available from fw */
1121 card->wandev.stats.rx_frame_errors = 0; /* not available from fw */
1122 card->wandev.stats.rx_missed_errors = card->u.x.stats.rx_aborts;
1123 card->wandev.stats.rx_dropped = 0; /* not available from fw */
1124 card->wandev.stats.rx_errors = 0; /* not available from fw */
1125 card->wandev.stats.tx_packets = card->u.x.stats.n2_tx_frames;
1126 card->wandev.stats.tx_aborted_errors = card->u.x.stats.tx_aborts;
1127 card->wandev.stats.tx_dropped = 0; /* not available from fw */
1128 card->wandev.stats.collisions = 0; /* not available from fw */
1129 card->wandev.stats.tx_errors = 0; /* not available from fw */
1131 cycx_x25_dump_devs(&card->wandev);
1136 /* return the number of nibbles */
1137 static int byte_to_nibble(u8 *s, u8 *d, char *nibble)
1141 if (*nibble && *s) {
1148 d[i] = (*s - '0') << 4;
1150 d[i] |= *(s + 1) - '0';
1162 static void nibble_to_byte(u8 *s, u8 *d, u8 len, u8 nibble)
1165 *d++ = '0' + (*s++ & 0x0F);
1170 *d++ = '0' + (*s >> 4);
1173 *d++ = '0' + (*s & 0x0F);
1183 /* Place X.25 call. */
1184 static int x25_place_call(struct cycx_device *card,
1185 struct cycx_x25_channel *chan)
1191 mylen = chan->local_addr ? strlen(chan->local_addr) : 0,
1192 remotelen = strlen(chan->addr);
1195 if (card->u.x.connection_keys == ~0U) {
1196 printk(KERN_INFO "%s: too many simultaneous connection "
1197 "requests!\n", card->devname);
1201 key = ffz(card->u.x.connection_keys);
1202 set_bit(key, (void*)&card->u.x.connection_keys);
1204 dprintk(1, KERN_INFO "%s:x25_place_call:key=%d\n", card->devname, key);
1205 memset(d, 0, sizeof(d));
1206 d[1] = key; /* user key */
1210 len = byte_to_nibble(chan->addr, d + 6, &nibble);
1212 if (chan->local_addr)
1213 len += byte_to_nibble(chan->local_addr, d + 6 + len, &nibble);
1218 d[5] = mylen << 4 | remotelen;
1219 d[6 + len + 1] = 0xCC; /* TCP/IP over X.25, thanks to Daniela :) */
1221 if ((err = x25_exec(card, X25_CONNECT_REQUEST, chan->link,
1222 &d, 7 + len + 1, NULL, 0)) != 0)
1223 clear_bit(--key, (void*)&card->u.x.connection_keys);
1230 /* Place X.25 CONNECT RESPONSE. */
1231 static int cycx_x25_connect_response(struct cycx_device *card,
1232 struct cycx_x25_channel *chan)
1236 memset(d, 0, sizeof(d));
1237 d[0] = d[3] = chan->lcn;
1240 d[7] = 0xCC; /* TCP/IP over X.25, thanks Daniela */
1242 return x25_exec(card, X25_CONNECT_RESPONSE, chan->link, &d, 8, NULL, 0);
1245 /* Place X.25 DISCONNECT RESPONSE. */
1246 static int cycx_x25_disconnect_response(struct cycx_device *card, u8 link,
1251 memset(d, 0, sizeof(d));
1256 return x25_exec(card, X25_DISCONNECT_RESPONSE, link, &d, 5, NULL, 0);
1259 /* Clear X.25 call. */
1260 static int x25_clear_call(struct cycx_device *card, u8 link, u8 lcn, u8 cause,
1265 memset(d, 0, sizeof(d));
1272 return x25_exec(card, X25_DISCONNECT_REQUEST, link, d, 7, NULL, 0);
1275 /* Send X.25 data packet. */
1276 static int cycx_x25_send(struct cycx_device *card, u8 link, u8 lcn, u8 bitm,
1279 u8 d[] = "?\xFF\x10??";
1284 return x25_exec(card, X25_DATA_REQUEST, link, &d, 5, buf, len);
1288 /* Find network device by its channel number. */
1289 static struct net_device *cycx_x25_get_dev_by_lcn(struct wan_device *wandev,
1292 struct net_device *dev = wandev->dev;
1293 struct cycx_x25_channel *chan;
1296 chan = (struct cycx_x25_channel*)dev->priv;
1298 if (chan->lcn == lcn)
1305 /* Find network device by its remote dte address. */
1306 static struct net_device *
1307 cycx_x25_get_dev_by_dte_addr(struct wan_device *wandev, char *dte)
1309 struct net_device *dev = wandev->dev;
1310 struct cycx_x25_channel *chan;
1313 chan = (struct cycx_x25_channel*)dev->priv;
1315 if (!strcmp(chan->addr, dte))
1322 /* Initiate connection on the logical channel.
1323 * o for PVC we just get channel configuration
1324 * o for SVCs place an X.25 call
1326 * Return: 0 connected
1327 * >0 connection in progress
1329 static int cycx_x25_chan_connect(struct net_device *dev)
1331 struct cycx_x25_channel *chan = dev->priv;
1332 struct cycx_device *card = chan->card;
1336 return -EINVAL; /* no destination address */
1338 dprintk(1, KERN_INFO "%s: placing X.25 call to %s...\n",
1339 card->devname, chan->addr);
1341 if (x25_place_call(card, chan))
1344 cycx_x25_set_chan_state(dev, WAN_CONNECTING);
1347 cycx_x25_set_chan_state(dev, WAN_CONNECTED);
1352 /* Disconnect logical channel.
1353 * o if SVC then clear X.25 call */
1354 static void cycx_x25_chan_disconnect(struct net_device *dev)
1356 struct cycx_x25_channel *chan = dev->priv;
1359 x25_clear_call(chan->card, chan->link, chan->lcn, 0, 0);
1360 cycx_x25_set_chan_state(dev, WAN_DISCONNECTING);
1362 cycx_x25_set_chan_state(dev, WAN_DISCONNECTED);
1365 /* Called by kernel timer */
1366 static void cycx_x25_chan_timer(unsigned long d)
1368 struct net_device *dev = (struct net_device *)d;
1369 struct cycx_x25_channel *chan = dev->priv;
1371 if (chan->state == WAN_CONNECTED)
1372 cycx_x25_chan_disconnect(dev);
1374 printk(KERN_ERR "%s: %s for svc (%s) not connected!\n",
1375 chan->card->devname, __FUNCTION__, dev->name);
1378 /* Set logical channel state. */
1379 static void cycx_x25_set_chan_state(struct net_device *dev, u8 state)
1381 struct cycx_x25_channel *chan = dev->priv;
1382 struct cycx_device *card = chan->card;
1383 unsigned long flags;
1384 char *string_state = NULL;
1386 spin_lock_irqsave(&card->lock, flags);
1388 if (chan->state != state) {
1389 if (chan->svc && chan->state == WAN_CONNECTED)
1390 del_timer(&chan->timer);
1394 string_state = "connected!";
1395 *(u16*)dev->dev_addr = htons(chan->lcn);
1396 netif_wake_queue(dev);
1399 if (chan->protocol == ETH_P_X25)
1400 cycx_x25_chan_send_event(dev, 1);
1403 case WAN_CONNECTING:
1404 string_state = "connecting...";
1406 case WAN_DISCONNECTING:
1407 string_state = "disconnecting...";
1409 case WAN_DISCONNECTED:
1410 string_state = "disconnected!";
1413 *(unsigned short*)dev->dev_addr = 0;
1417 if (chan->protocol == ETH_P_X25)
1418 cycx_x25_chan_send_event(dev, 2);
1420 netif_wake_queue(dev);
1424 printk(KERN_INFO "%s: interface %s %s\n", card->devname,
1425 dev->name, string_state);
1426 chan->state = state;
1429 spin_unlock_irqrestore(&card->lock, flags);
1432 /* Send packet on a logical channel.
1433 * When this function is called, tx_skb field of the channel data space
1434 * points to the transmit socket buffer. When transmission is complete,
1435 * release socket buffer and reset 'tbusy' flag.
1437 * Return: 0 - transmission complete
1441 * 1. If packet length is greater than MTU for this channel, we'll fragment
1442 * the packet into 'complete sequence' using M-bit.
1443 * 2. When transmission is complete, an event notification should be issued
1445 static int cycx_x25_chan_send(struct net_device *dev, struct sk_buff *skb)
1447 struct cycx_x25_channel *chan = dev->priv;
1448 struct cycx_device *card = chan->card;
1449 int bitm = 0; /* final packet */
1450 unsigned len = skb->len;
1452 if (skb->len > card->wandev.mtu) {
1453 len = card->wandev.mtu;
1454 bitm = 0x10; /* set M-bit (more data) */
1457 if (cycx_x25_send(card, chan->link, chan->lcn, bitm, len, skb->data))
1465 ++chan->ifstats.tx_packets;
1466 chan->ifstats.tx_bytes += len;
1471 /* Send event (connection, disconnection, etc) to X.25 socket layer */
1473 static void cycx_x25_chan_send_event(struct net_device *dev, u8 event)
1475 struct sk_buff *skb;
1478 if ((skb = dev_alloc_skb(1)) == NULL) {
1479 printk(KERN_ERR "%s: out of memory\n", __FUNCTION__);
1483 ptr = skb_put(skb, 1);
1486 skb->protocol = x25_type_trans(skb, dev);
1488 dev->last_rx = jiffies; /* timestamp */
1491 /* Convert line speed in bps to a number used by cyclom 2x code. */
1492 static u8 bps_to_speed_code(u32 bps)
1494 u8 number = 0; /* defaults to the lowest (1200) speed ;> */
1496 if (bps >= 512000) number = 8;
1497 else if (bps >= 256000) number = 7;
1498 else if (bps >= 64000) number = 6;
1499 else if (bps >= 38400) number = 5;
1500 else if (bps >= 19200) number = 4;
1501 else if (bps >= 9600) number = 3;
1502 else if (bps >= 4800) number = 2;
1503 else if (bps >= 2400) number = 1;
1509 static u8 cycx_log2(u32 n)
1524 /* Convert decimal string to unsigned integer.
1525 * If len != 0 then only 'len' characters of the string are converted. */
1526 static unsigned dec_to_uint(u8 *str, int len)
1533 for (; len && isdigit(*str); ++str, --len)
1534 val = (val * 10) + (*str - (unsigned) '0');
1539 static void reset_timer(struct net_device *dev)
1541 struct cycx_x25_channel *chan = dev->priv;
1544 mod_timer(&chan->timer, jiffies+chan->idle_tmout*HZ);
1546 #ifdef CYCLOMX_X25_DEBUG
1547 static void cycx_x25_dump_config(struct cycx_x25_config *conf)
1549 printk(KERN_INFO "X.25 configuration\n");
1550 printk(KERN_INFO "-----------------\n");
1551 printk(KERN_INFO "link number=%d\n", conf->link);
1552 printk(KERN_INFO "line speed=%d\n", conf->speed);
1553 printk(KERN_INFO "clock=%sternal\n", conf->clock == 8 ? "Ex" : "In");
1554 printk(KERN_INFO "# level 2 retransm.=%d\n", conf->n2);
1555 printk(KERN_INFO "level 2 window=%d\n", conf->n2win);
1556 printk(KERN_INFO "level 3 window=%d\n", conf->n3win);
1557 printk(KERN_INFO "# logical channels=%d\n", conf->nvc);
1558 printk(KERN_INFO "level 3 pkt len=%d\n", conf->pktlen);
1559 printk(KERN_INFO "my address=%d\n", conf->locaddr);
1560 printk(KERN_INFO "remote address=%d\n", conf->remaddr);
1561 printk(KERN_INFO "t1=%d seconds\n", conf->t1);
1562 printk(KERN_INFO "t2=%d seconds\n", conf->t2);
1563 printk(KERN_INFO "t21=%d seconds\n", conf->t21);
1564 printk(KERN_INFO "# PVCs=%d\n", conf->npvc);
1565 printk(KERN_INFO "t23=%d seconds\n", conf->t23);
1566 printk(KERN_INFO "flags=0x%x\n", conf->flags);
1569 static void cycx_x25_dump_stats(struct cycx_x25_stats *stats)
1571 printk(KERN_INFO "X.25 statistics\n");
1572 printk(KERN_INFO "--------------\n");
1573 printk(KERN_INFO "rx_crc_errors=%d\n", stats->rx_crc_errors);
1574 printk(KERN_INFO "rx_over_errors=%d\n", stats->rx_over_errors);
1575 printk(KERN_INFO "n2_tx_frames=%d\n", stats->n2_tx_frames);
1576 printk(KERN_INFO "n2_rx_frames=%d\n", stats->n2_rx_frames);
1577 printk(KERN_INFO "tx_timeouts=%d\n", stats->tx_timeouts);
1578 printk(KERN_INFO "rx_timeouts=%d\n", stats->rx_timeouts);
1579 printk(KERN_INFO "n3_tx_packets=%d\n", stats->n3_tx_packets);
1580 printk(KERN_INFO "n3_rx_packets=%d\n", stats->n3_rx_packets);
1581 printk(KERN_INFO "tx_aborts=%d\n", stats->tx_aborts);
1582 printk(KERN_INFO "rx_aborts=%d\n", stats->rx_aborts);
1585 static void cycx_x25_dump_devs(struct wan_device *wandev)
1587 struct net_device *dev = wandev->dev;
1589 printk(KERN_INFO "X.25 dev states\n");
1590 printk(KERN_INFO "name: addr: txoff: protocol:\n");
1591 printk(KERN_INFO "---------------------------------------\n");
1594 struct cycx_x25_channel *chan = dev->priv;
1596 printk(KERN_INFO "%-5.5s %-15.15s %d ETH_P_%s\n",
1597 chan->name, chan->addr, netif_queue_stopped(dev),
1598 chan->protocol == ETH_P_IP ? "IP" : "X25");
1603 #endif /* CYCLOMX_X25_DEBUG */