1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79#define CYCLOMX_X25_DEBUG 1
80
81#include <linux/ctype.h>
82#include <linux/errno.h>
83#include <linux/if_arp.h>
84#include <linux/kernel.h>
85#include <linux/module.h>
86#include <linux/string.h>
87#include <linux/slab.h>
88#include <linux/stddef.h>
89#include <linux/wanrouter.h>
90
91#include <asm/byteorder.h>
92
93#include <linux/cyclomx.h>
94#include <linux/cycx_x25.h>
95
96#include <net/x25device.h>
97
98
99#define CYCX_X25_MAX_CMD_RETRY 5
100#define CYCX_X25_CHAN_MTU 2048
101
102
103
104
105struct cycx_x25_channel {
106
107 struct net_device *slave;
108
109 char name[WAN_IFNAME_SZ+1];
110 char addr[WAN_ADDRESS_SZ+1];
111 char *local_addr;
112
113 s16 lcn;
114 u8 link;
115 struct timer_list timer;
116 u16 protocol;
117 u8 svc;
118 u8 state;
119 u8 drop_sequence;
120 u32 idle_tmout;
121 struct sk_buff *rx_skb;
122 struct cycx_device *card;
123 struct net_device_stats ifstats;
124};
125
126
127
128static int cycx_wan_update(struct wan_device *wandev),
129 cycx_wan_new_if(struct wan_device *wandev, struct net_device *dev,
130 wanif_conf_t *conf),
131 cycx_wan_del_if(struct wan_device *wandev, struct net_device *dev);
132
133
134static int cycx_netdevice_init(struct net_device *dev);
135static int cycx_netdevice_open(struct net_device *dev);
136static int cycx_netdevice_stop(struct net_device *dev);
137static int cycx_netdevice_hard_header(struct sk_buff *skb,
138 struct net_device *dev, u16 type,
139 const void *daddr, const void *saddr,
140 unsigned len);
141static int cycx_netdevice_rebuild_header(struct sk_buff *skb);
142static int cycx_netdevice_hard_start_xmit(struct sk_buff *skb,
143 struct net_device *dev);
144
145static struct net_device_stats *
146 cycx_netdevice_get_stats(struct net_device *dev);
147
148
149static 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);
166
167
168static 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,
172 int len, void *buf),
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,
176 u8 lcn);
177
178
179static int cycx_x25_chan_connect(struct net_device *dev),
180 cycx_x25_chan_send(struct net_device *dev, struct sk_buff *skb);
181
182static void cycx_x25_chan_disconnect(struct net_device *dev),
183 cycx_x25_chan_send_event(struct net_device *dev, u8 event);
184
185
186static void cycx_x25_set_chan_state(struct net_device *dev, u8 state),
187 cycx_x25_chan_timer(unsigned long d);
188
189static void nibble_to_byte(u8 *s, u8 *d, u8 len, u8 nibble),
190 reset_timer(struct net_device *dev);
191
192static u8 bps_to_speed_code(u32 bps);
193static u8 cycx_log2(u32 n);
194
195static unsigned dec_to_uint(u8 *str, int len);
196
197static struct net_device *cycx_x25_get_dev_by_lcn(struct wan_device *wandev,
198 s16 lcn);
199static struct net_device *
200 cycx_x25_get_dev_by_dte_addr(struct wan_device *wandev, char *dte);
201
202#ifdef CYCLOMX_X25_DEBUG
203static void hex_dump(char *msg, unsigned char *p, int len);
204static void cycx_x25_dump_config(struct cycx_x25_config *conf);
205static void cycx_x25_dump_stats(struct cycx_x25_stats *stats);
206static void cycx_x25_dump_devs(struct wan_device *wandev);
207#else
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)
212#endif
213
214
215
216
217
218
219
220
221
222
223
224int cycx_x25_wan_init(struct cycx_device *card, wandev_conf_t *conf)
225{
226 struct cycx_x25_config cfg;
227
228
229 if (conf->config_id != WANCONFIG_X25) {
230 printk(KERN_INFO "%s: invalid configuration ID %u!\n",
231 card->devname, conf->config_id);
232 return -EINVAL;
233 }
234
235
236 card->mbox = card->hw.dpmbase + X25_MBOX_OFFS;
237 card->u.x.connection_keys = 0;
238 spin_lock_init(&card->u.x.lock);
239
240
241
242
243
244
245 memset(&cfg, 0, sizeof(cfg));
246 cfg.link = 0;
247 cfg.clock = conf->clocking == WANOPT_EXTERNAL ? 8 : 55;
248 cfg.speed = bps_to_speed_code(conf->bps);
249 cfg.n3win = 7;
250 cfg.n2win = 2;
251 cfg.n2 = 5;
252 cfg.nvc = 1;
253 cfg.npvc = 1;
254 cfg.flags = 0x02;
255 cfg.t1 = 10;
256 cfg.t2 = 29;
257 cfg.t21 = 180;
258 cfg.t23 = 180;
259
260
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;
267 else
268 card->wandev.mtu = 64;
269
270 cfg.pktlen = cycx_log2(card->wandev.mtu);
271
272 if (conf->station == WANOPT_DTE) {
273 cfg.locaddr = 3;
274 cfg.remaddr = 1;
275 } else {
276 cfg.locaddr = 1;
277 cfg.remaddr = 3;
278 }
279
280 if (conf->interface == WANOPT_RS232)
281 cfg.flags = 0;
282
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);
286 }
287
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);
291 }
292
293 if (card->u.x.lo_pvc == 255)
294 cfg.npvc = 0;
295 else
296 cfg.npvc = card->u.x.hi_pvc - card->u.x.lo_pvc + 1;
297
298 cfg.nvc = card->u.x.hi_svc - card->u.x.lo_svc + 1 + cfg.npvc;
299
300 if (conf->u.x25.hdlc_window)
301 cfg.n2win = min_t(unsigned int, conf->u.x25.hdlc_window, 7);
302
303 if (conf->u.x25.pkt_window)
304 cfg.n3win = min_t(unsigned int, conf->u.x25.pkt_window, 7);
305
306 if (conf->u.x25.t1)
307 cfg.t1 = min_t(unsigned int, conf->u.x25.t1, 30);
308
309 if (conf->u.x25.t2)
310 cfg.t2 = min_t(unsigned int, conf->u.x25.t2, 30);
311
312 if (conf->u.x25.t11_t21)
313 cfg.t21 = min_t(unsigned int, conf->u.x25.t11_t21, 30);
314
315 if (conf->u.x25.t13_t23)
316 cfg.t23 = min_t(unsigned int, conf->u.x25.t13_t23, 30);
317
318 if (conf->u.x25.n2)
319 cfg.n2 = min_t(unsigned int, conf->u.x25.n2, 30);
320
321
322 if (cycx_x25_configure(card, &cfg))
323 return -EIO;
324
325
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;
331 card->exec = NULL;
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;
336
337 return 0;
338}
339
340
341
342static int cycx_wan_update(struct wan_device *wandev)
343{
344
345 if (!wandev || !wandev->private)
346 return -EFAULT;
347
348 if (wandev->state == WAN_UNCONFIGURED)
349 return -ENODEV;
350
351 cycx_x25_get_stats(wandev->private);
352
353 return 0;
354}
355
356
357
358
359
360
361
362
363
364
365
366static int cycx_wan_new_if(struct wan_device *wandev, struct net_device *dev,
367 wanif_conf_t *conf)
368{
369 struct cycx_device *card = wandev->private;
370 struct cycx_x25_channel *chan;
371 int err = 0;
372
373 if (!conf->name[0] || strlen(conf->name) > WAN_IFNAME_SZ) {
374 printk(KERN_INFO "%s: invalid interface name!\n",
375 card->devname);
376 return -EINVAL;
377 }
378
379
380 chan = kzalloc(sizeof(struct cycx_x25_channel), GFP_KERNEL);
381 if (!chan)
382 return -ENOMEM;
383
384 strcpy(chan->name, conf->name);
385 chan->card = card;
386 chan->link = conf->port;
387 chan->protocol = conf->protocol ? ETH_P_X25 : ETH_P_IP;
388 chan->rx_skb = NULL;
389
390 chan->local_addr = NULL;
391
392 if (conf->addr[0] == '@') {
393 int len = strlen(conf->local_addr);
394
395 if (len) {
396 if (len > WAN_ADDRESS_SZ) {
397 printk(KERN_ERR "%s: %s local addr too long!\n",
398 wandev->name, chan->name);
399 kfree(chan);
400 return -EINVAL;
401 } else {
402 chan->local_addr = kmalloc(len + 1, GFP_KERNEL);
403
404 if (!chan->local_addr) {
405 kfree(chan);
406 return -ENOMEM;
407 }
408 }
409
410 strncpy(chan->local_addr, conf->local_addr,
411 WAN_ADDRESS_SZ);
412 }
413
414 chan->svc = 1;
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;
419
420
421 chan->idle_tmout = conf->idle_timeout ? conf->idle_timeout : 90;
422 } else if (isdigit(conf->addr[0])) {
423 s16 lcn = dec_to_uint(conf->addr, 0);
424
425 if (lcn >= card->u.x.lo_pvc && lcn <= card->u.x.hi_pvc)
426 chan->lcn = lcn;
427 else {
428 printk(KERN_ERR
429 "%s: PVC %u is out of range on interface %s!\n",
430 wandev->name, lcn, chan->name);
431 err = -EINVAL;
432 }
433 } else {
434 printk(KERN_ERR "%s: invalid media address on interface %s!\n",
435 wandev->name, chan->name);
436 err = -EINVAL;
437 }
438
439 if (err) {
440 kfree(chan->local_addr);
441 kfree(chan);
442 return err;
443 }
444
445
446 strcpy(dev->name, chan->name);
447 dev->init = cycx_netdevice_init;
448 dev->priv = chan;
449
450 return 0;
451}
452
453
454static int cycx_wan_del_if(struct wan_device *wandev, struct net_device *dev)
455{
456 if (dev->priv) {
457 struct cycx_x25_channel *chan = dev->priv;
458
459 if (chan->svc) {
460 kfree(chan->local_addr);
461 if (chan->state == WAN_CONNECTED)
462 del_timer(&chan->timer);
463 }
464
465 kfree(chan);
466 dev->priv = NULL;
467 }
468
469 return 0;
470}
471
472
473
474
475static const struct header_ops cycx_header_ops = {
476 .create = cycx_netdevice_hard_header,
477 .rebuild = cycx_netdevice_rebuild_header,
478};
479
480
481
482
483
484
485static int cycx_netdevice_init(struct net_device *dev)
486{
487 struct cycx_x25_channel *chan = dev->priv;
488 struct cycx_device *card = chan->card;
489 struct wan_device *wandev = &card->wandev;
490
491
492 dev->open = cycx_netdevice_open;
493 dev->stop = cycx_netdevice_stop;
494 dev->header_ops = &cycx_header_ops;
495
496 dev->hard_start_xmit = cycx_netdevice_hard_start_xmit;
497 dev->get_stats = cycx_netdevice_get_stats;
498
499
500 dev->mtu = CYCX_X25_CHAN_MTU;
501 dev->type = ARPHRD_HWX25;
502 dev->hard_header_len = 0;
503 dev->addr_len = 0;
504
505 if (!chan->svc)
506 *(__be16*)dev->dev_addr = htons(chan->lcn);
507
508
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 +
514 wandev->msize - 1);
515 dev->flags |= IFF_NOARP;
516
517
518 dev->tx_queue_len = 10;
519
520
521 cycx_x25_set_chan_state(dev, WAN_DISCONNECTED);
522
523 return 0;
524}
525
526
527
528
529
530
531static int cycx_netdevice_open(struct net_device *dev)
532{
533 if (netif_running(dev))
534 return -EBUSY;
535
536 netif_start_queue(dev);
537 return 0;
538}
539
540
541
542
543static int cycx_netdevice_stop(struct net_device *dev)
544{
545 struct cycx_x25_channel *chan = dev->priv;
546
547 netif_stop_queue(dev);
548
549 if (chan->state == WAN_CONNECTED || chan->state == WAN_CONNECTING)
550 cycx_x25_chan_disconnect(dev);
551
552 return 0;
553}
554
555
556
557
558
559
560
561
562
563static int cycx_netdevice_hard_header(struct sk_buff *skb,
564 struct net_device *dev, u16 type,
565 const void *daddr, const void *saddr,
566 unsigned len)
567{
568 skb->protocol = htons(type);
569
570 return dev->hard_header_len;
571}
572
573
574
575
576static int cycx_netdevice_rebuild_header(struct sk_buff *skb)
577{
578 return 1;
579}
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596static int cycx_netdevice_hard_start_xmit(struct sk_buff *skb,
597 struct net_device *dev)
598{
599 struct cycx_x25_channel *chan = dev->priv;
600 struct cycx_device *card = chan->card;
601
602 if (!chan->svc)
603 chan->protocol = ntohs(skb->protocol);
604
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)) {
609 printk(KERN_INFO
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);
618 return -EBUSY;
619 }
620
621 case WAN_CONNECTED:
622 reset_timer(dev);
623 dev->trans_start = jiffies;
624 netif_stop_queue(dev);
625
626 if (cycx_x25_chan_send(dev, skb))
627 return -EBUSY;
628
629 break;
630 default:
631 ++chan->ifstats.tx_dropped;
632 ++card->wandev.stats.tx_dropped;
633 }
634 } else {
635 switch (skb->data[0]) {
636 case 0: break;
637 case 1:
638 cycx_x25_chan_connect(dev);
639 goto free_packet;
640 case 2:
641 cycx_x25_chan_disconnect(dev);
642 goto free_packet;
643 default:
644 printk(KERN_INFO
645 "%s: unknown %d x25-iface request on %s!\n",
646 card->devname, skb->data[0], dev->name);
647 ++chan->ifstats.tx_errors;
648 goto free_packet;
649 }
650
651 skb_pull(skb, 1);
652 reset_timer(dev);
653 dev->trans_start = jiffies;
654 netif_stop_queue(dev);
655
656 if (cycx_x25_chan_send(dev, skb)) {
657
658 skb_push(skb, 1);
659 return -EBUSY;
660 }
661 }
662
663free_packet:
664 dev_kfree_skb(skb);
665
666 return 0;
667}
668
669
670
671static struct net_device_stats *cycx_netdevice_get_stats(struct net_device *dev)
672{
673 struct cycx_x25_channel *chan = dev->priv;
674
675 return chan ? &chan->ifstats : NULL;
676}
677
678
679
680static void cycx_x25_irq_handler(struct cycx_device *card)
681{
682 struct cycx_x25_cmd cmd;
683 u16 z = 0;
684
685 card->in_isr = 1;
686 card->buff_int_mode_unbusy = 0;
687 cycx_peek(&card->hw, X25_RXMBOX_OFFS, &cmd, sizeof(cmd));
688
689 switch (cmd.command) {
690 case X25_DATA_INDICATION:
691 cycx_x25_irq_rx(card, &cmd);
692 break;
693 case X25_ACK_FROM_VC:
694 cycx_x25_irq_tx(card, &cmd);
695 break;
696 case X25_LOG:
697 cycx_x25_irq_log(card, &cmd);
698 break;
699 case X25_STATISTIC:
700 cycx_x25_irq_stat(card, &cmd);
701 break;
702 case X25_CONNECT_CONFIRM:
703 cycx_x25_irq_connect_confirm(card, &cmd);
704 break;
705 case X25_CONNECT_INDICATION:
706 cycx_x25_irq_connect(card, &cmd);
707 break;
708 case X25_DISCONNECT_INDICATION:
709 cycx_x25_irq_disconnect(card, &cmd);
710 break;
711 case X25_DISCONNECT_CONFIRM:
712 cycx_x25_irq_disconnect_confirm(card, &cmd);
713 break;
714 case X25_LINE_ON:
715 cycx_set_state(card, WAN_CONNECTED);
716 break;
717 case X25_LINE_OFF:
718 cycx_set_state(card, WAN_DISCONNECTED);
719 break;
720 default:
721 cycx_x25_irq_spurious(card, &cmd);
722 break;
723 }
724
725 cycx_poke(&card->hw, 0, &z, sizeof(z));
726 cycx_poke(&card->hw, X25_RXMBOX_OFFS, &z, sizeof(z));
727 card->in_isr = 0;
728}
729
730
731
732
733static void cycx_x25_irq_tx(struct cycx_device *card, struct cycx_x25_cmd *cmd)
734{
735 struct net_device *dev;
736 struct wan_device *wandev = &card->wandev;
737 u8 lcn;
738
739 cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
740
741
742 dev = cycx_x25_get_dev_by_lcn(wandev, lcn);
743 if (dev) {
744 card->buff_int_mode_unbusy = 1;
745 netif_wake_queue(dev);
746 } else
747 printk(KERN_ERR "%s:ackvc for inexistent lcn %d\n",
748 card->devname, lcn);
749}
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765static void cycx_x25_irq_rx(struct cycx_device *card, struct cycx_x25_cmd *cmd)
766{
767 struct wan_device *wandev = &card->wandev;
768 struct net_device *dev;
769 struct cycx_x25_channel *chan;
770 struct sk_buff *skb;
771 u8 bitm, lcn;
772 int pktlen = cmd->len - 5;
773
774 cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
775 cycx_peek(&card->hw, cmd->buf + 4, &bitm, sizeof(bitm));
776 bitm &= 0x10;
777
778 dev = cycx_x25_get_dev_by_lcn(wandev, lcn);
779 if (!dev) {
780
781 printk(KERN_INFO "%s: receiving on orphaned LCN %d!\n",
782 card->devname, lcn);
783 return;
784 }
785
786 chan = dev->priv;
787 reset_timer(dev);
788
789 if (chan->drop_sequence) {
790 if (!bitm)
791 chan->drop_sequence = 0;
792 else
793 return;
794 }
795
796 if ((skb = chan->rx_skb) == NULL) {
797
798 int bufsize = bitm ? dev->mtu : pktlen;
799
800 if ((skb = dev_alloc_skb((chan->protocol == ETH_P_X25 ? 1 : 0) +
801 bufsize +
802 dev->hard_header_len)) == NULL) {
803 printk(KERN_INFO "%s: no socket buffers available!\n",
804 card->devname);
805 chan->drop_sequence = 1;
806 ++chan->ifstats.rx_dropped;
807 return;
808 }
809
810 if (chan->protocol == ETH_P_X25)
811
812 skb_put(skb, 1);
813
814 skb->dev = dev;
815 skb->protocol = htons(chan->protocol);
816 chan->rx_skb = skb;
817 }
818
819 if (skb_tailroom(skb) < pktlen) {
820
821 dev_kfree_skb_irq(skb);
822 chan->rx_skb = NULL;
823
824 if (bitm)
825 chan->drop_sequence = 1;
826
827 printk(KERN_INFO "%s: unexpectedly long packet sequence "
828 "on interface %s!\n", card->devname, dev->name);
829 ++chan->ifstats.rx_length_errors;
830 return;
831 }
832
833
834 cycx_peek(&card->hw, cmd->buf + 5, skb_put(skb, pktlen), pktlen);
835
836 if (bitm)
837 return;
838
839 chan->rx_skb = NULL;
840
841 ++chan->ifstats.rx_packets;
842 chan->ifstats.rx_bytes += pktlen;
843
844 skb_reset_mac_header(skb);
845 netif_rx(skb);
846 dev->last_rx = jiffies;
847}
848
849
850static void cycx_x25_irq_connect(struct cycx_device *card,
851 struct cycx_x25_cmd *cmd)
852{
853 struct wan_device *wandev = &card->wandev;
854 struct net_device *dev = NULL;
855 struct cycx_x25_channel *chan;
856 u8 d[32],
857 loc[24],
858 rem[24];
859 u8 lcn, sizeloc, sizerem;
860
861 cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
862 cycx_peek(&card->hw, cmd->buf + 5, &sizeloc, sizeof(sizeloc));
863 cycx_peek(&card->hw, cmd->buf + 6, d, cmd->len - 6);
864
865 sizerem = sizeloc >> 4;
866 sizeloc &= 0x0F;
867
868 loc[0] = rem[0] = '\0';
869
870 if (sizeloc)
871 nibble_to_byte(d, loc, sizeloc, 0);
872
873 if (sizerem)
874 nibble_to_byte(d + (sizeloc >> 1), rem, sizerem, sizeloc & 1);
875
876 dprintk(1, KERN_INFO "%s:lcn=%d, local=%s, remote=%s\n",
877 __FUNCTION__, lcn, loc, rem);
878
879 dev = cycx_x25_get_dev_by_dte_addr(wandev, rem);
880 if (!dev) {
881
882 printk(KERN_INFO "%s: connect not expected: remote %s!\n",
883 card->devname, rem);
884 return;
885 }
886
887 chan = dev->priv;
888 chan->lcn = lcn;
889 cycx_x25_connect_response(card, chan);
890 cycx_x25_set_chan_state(dev, WAN_CONNECTED);
891}
892
893
894static void cycx_x25_irq_connect_confirm(struct cycx_device *card,
895 struct cycx_x25_cmd *cmd)
896{
897 struct wan_device *wandev = &card->wandev;
898 struct net_device *dev;
899 struct cycx_x25_channel *chan;
900 u8 lcn, key;
901
902 cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
903 cycx_peek(&card->hw, cmd->buf + 1, &key, sizeof(key));
904 dprintk(1, KERN_INFO "%s: %s:lcn=%d, key=%d\n",
905 card->devname, __FUNCTION__, lcn, key);
906
907 dev = cycx_x25_get_dev_by_lcn(wandev, -key);
908 if (!dev) {
909
910 clear_bit(--key, (void*)&card->u.x.connection_keys);
911 printk(KERN_INFO "%s: connect confirm not expected: lcn %d, "
912 "key=%d!\n", card->devname, lcn, key);
913 return;
914 }
915
916 clear_bit(--key, (void*)&card->u.x.connection_keys);
917 chan = dev->priv;
918 chan->lcn = lcn;
919 cycx_x25_set_chan_state(dev, WAN_CONNECTED);
920}
921
922
923static void cycx_x25_irq_disconnect_confirm(struct cycx_device *card,
924 struct cycx_x25_cmd *cmd)
925{
926 struct wan_device *wandev = &card->wandev;
927 struct net_device *dev;
928 u8 lcn;
929
930 cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
931 dprintk(1, KERN_INFO "%s: %s:lcn=%d\n",
932 card->devname, __FUNCTION__, lcn);
933 dev = cycx_x25_get_dev_by_lcn(wandev, lcn);
934 if (!dev) {
935
936 printk(KERN_INFO "%s:disconnect confirm not expected!:lcn %d\n",
937 card->devname, lcn);
938 return;
939 }
940
941 cycx_x25_set_chan_state(dev, WAN_DISCONNECTED);
942}
943
944
945static void cycx_x25_irq_disconnect(struct cycx_device *card,
946 struct cycx_x25_cmd *cmd)
947{
948 struct wan_device *wandev = &card->wandev;
949 struct net_device *dev;
950 u8 lcn;
951
952 cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
953 dprintk(1, KERN_INFO "%s:lcn=%d\n", __FUNCTION__, lcn);
954
955 dev = cycx_x25_get_dev_by_lcn(wandev, lcn);
956 if (dev) {
957 struct cycx_x25_channel *chan = dev->priv;
958
959 cycx_x25_disconnect_response(card, chan->link, lcn);
960 cycx_x25_set_chan_state(dev, WAN_DISCONNECTED);
961 } else
962 cycx_x25_disconnect_response(card, 0, lcn);
963}
964
965
966static void cycx_x25_irq_log(struct cycx_device *card, struct cycx_x25_cmd *cmd)
967{
968#if CYCLOMX_X25_DEBUG
969 char bf[20];
970 u16 size, toread, link, msg_code;
971 u8 code, routine;
972
973 cycx_peek(&card->hw, cmd->buf, &msg_code, sizeof(msg_code));
974 cycx_peek(&card->hw, cmd->buf + 2, &link, sizeof(link));
975 cycx_peek(&card->hw, cmd->buf + 4, &size, sizeof(size));
976
977 toread = size < 20 ? size : 20;
978 cycx_peek(&card->hw, cmd->buf + 10, &bf, toread);
979 cycx_peek(&card->hw, cmd->buf + 10 + toread, &code, 1);
980 cycx_peek(&card->hw, cmd->buf + 10 + toread + 1, &routine, 1);
981
982 printk(KERN_INFO "cycx_x25_irq_handler: X25_LOG (0x4500) indic.:\n");
983 printk(KERN_INFO "cmd->buf=0x%X\n", cmd->buf);
984 printk(KERN_INFO "Log message code=0x%X\n", msg_code);
985 printk(KERN_INFO "Link=%d\n", link);
986 printk(KERN_INFO "log code=0x%X\n", code);
987 printk(KERN_INFO "log routine=0x%X\n", routine);
988 printk(KERN_INFO "Message size=%d\n", size);
989 hex_dump("Message", bf, toread);
990#endif
991}
992
993
994static void cycx_x25_irq_stat(struct cycx_device *card,
995 struct cycx_x25_cmd *cmd)
996{
997 cycx_peek(&card->hw, cmd->buf, &card->u.x.stats,
998 sizeof(card->u.x.stats));
999 hex_dump("cycx_x25_irq_stat", (unsigned char*)&card->u.x.stats,
1000 sizeof(card->u.x.stats));
1001 cycx_x25_dump_stats(&card->u.x.stats);
1002 wake_up_interruptible(&card->wait_stats);
1003}
1004
1005
1006
1007
1008static void cycx_x25_irq_spurious(struct cycx_device *card,
1009 struct cycx_x25_cmd *cmd)
1010{
1011 printk(KERN_INFO "%s: spurious interrupt (0x%X)!\n",
1012 card->devname, cmd->command);
1013}
1014#ifdef CYCLOMX_X25_DEBUG
1015static void hex_dump(char *msg, unsigned char *p, int len)
1016{
1017 unsigned char hex[1024],
1018 * phex = hex;
1019
1020 if (len >= (sizeof(hex) / 2))
1021 len = (sizeof(hex) / 2) - 1;
1022
1023 while (len--) {
1024 sprintf(phex, "%02x", *p++);
1025 phex += 2;
1026 }
1027
1028 printk(KERN_INFO "%s: %s\n", msg, hex);
1029}
1030#endif
1031
1032
1033
1034static int x25_exec(struct cycx_device *card, int command, int link,
1035 void *d1, int len1, void *d2, int len2)
1036{
1037 struct cycx_x25_cmd c;
1038 unsigned long flags;
1039 u32 addr = 0x1200 + 0x2E0 * link + 0x1E2;
1040 u8 retry = CYCX_X25_MAX_CMD_RETRY;
1041 int err = 0;
1042
1043 c.command = command;
1044 c.link = link;
1045 c.len = len1 + len2;
1046
1047 spin_lock_irqsave(&card->u.x.lock, flags);
1048
1049
1050 cycx_poke(&card->hw, X25_MBOX_OFFS, &c, sizeof(c) - sizeof(c.buf));
1051
1052
1053 if (d1) {
1054 cycx_poke(&card->hw, addr, d1, len1);
1055
1056 if (d2) {
1057 if (len2 > 254) {
1058 u32 addr1 = 0xA00 + 0x400 * link;
1059
1060 cycx_poke(&card->hw, addr + len1, d2, 249);
1061 cycx_poke(&card->hw, addr1, ((u8*)d2) + 249,
1062 len2 - 249);
1063 } else
1064 cycx_poke(&card->hw, addr + len1, d2, len2);
1065 }
1066 }
1067
1068
1069 cycx_intr(&card->hw);
1070
1071
1072 do {
1073 err = cycx_exec(card->mbox);
1074 } while (retry-- && err);
1075
1076 spin_unlock_irqrestore(&card->u.x.lock, flags);
1077
1078 return err;
1079}
1080
1081
1082static int cycx_x25_configure(struct cycx_device *card,
1083 struct cycx_x25_config *conf)
1084{
1085 struct {
1086 u16 nlinks;
1087 struct cycx_x25_config conf[2];
1088 } x25_cmd_conf;
1089
1090 memset(&x25_cmd_conf, 0, sizeof(x25_cmd_conf));
1091 x25_cmd_conf.nlinks = 2;
1092 x25_cmd_conf.conf[0] = *conf;
1093
1094
1095
1096
1097
1098 x25_cmd_conf.conf[1] = *conf;
1099 x25_cmd_conf.conf[1].link = 1;
1100 x25_cmd_conf.conf[1].speed = 5;
1101 x25_cmd_conf.conf[1].clock = 8;
1102 x25_cmd_conf.conf[1].flags = 0;
1103
1104 cycx_x25_dump_config(&x25_cmd_conf.conf[0]);
1105 cycx_x25_dump_config(&x25_cmd_conf.conf[1]);
1106
1107 return x25_exec(card, X25_CONFIG, 0,
1108 &x25_cmd_conf, sizeof(x25_cmd_conf), NULL, 0);
1109}
1110
1111
1112static int cycx_x25_get_stats(struct cycx_device *card)
1113{
1114
1115
1116 int err = x25_exec(card, X25_STATISTIC, 0, NULL, 20, NULL, 0);
1117
1118 if (err)
1119 return err;
1120
1121 interruptible_sleep_on(&card->wait_stats);
1122
1123 if (signal_pending(current))
1124 return -EINTR;
1125
1126 card->wandev.stats.rx_packets = card->u.x.stats.n2_rx_frames;
1127 card->wandev.stats.rx_over_errors = card->u.x.stats.rx_over_errors;
1128 card->wandev.stats.rx_crc_errors = card->u.x.stats.rx_crc_errors;
1129 card->wandev.stats.rx_length_errors = 0;
1130 card->wandev.stats.rx_frame_errors = 0;
1131 card->wandev.stats.rx_missed_errors = card->u.x.stats.rx_aborts;
1132 card->wandev.stats.rx_dropped = 0;
1133 card->wandev.stats.rx_errors = 0;
1134 card->wandev.stats.tx_packets = card->u.x.stats.n2_tx_frames;
1135 card->wandev.stats.tx_aborted_errors = card->u.x.stats.tx_aborts;
1136 card->wandev.stats.tx_dropped = 0;
1137 card->wandev.stats.collisions = 0;
1138 card->wandev.stats.tx_errors = 0;
1139
1140 cycx_x25_dump_devs(&card->wandev);
1141
1142 return 0;
1143}
1144
1145
1146static int byte_to_nibble(u8 *s, u8 *d, char *nibble)
1147{
1148 int i = 0;
1149
1150 if (*nibble && *s) {
1151 d[i] |= *s++ - '0';
1152 *nibble = 0;
1153 ++i;
1154 }
1155
1156 while (*s) {
1157 d[i] = (*s - '0') << 4;
1158 if (*(s + 1))
1159 d[i] |= *(s + 1) - '0';
1160 else {
1161 *nibble = 1;
1162 break;
1163 }
1164 ++i;
1165 s += 2;
1166 }
1167
1168 return i;
1169}
1170
1171static void nibble_to_byte(u8 *s, u8 *d, u8 len, u8 nibble)
1172{
1173 if (nibble) {
1174 *d++ = '0' + (*s++ & 0x0F);
1175 --len;
1176 }
1177
1178 while (len) {
1179 *d++ = '0' + (*s >> 4);
1180
1181 if (--len) {
1182 *d++ = '0' + (*s & 0x0F);
1183 --len;
1184 } else break;
1185
1186 ++s;
1187 }
1188
1189 *d = '\0';
1190}
1191
1192
1193static int x25_place_call(struct cycx_device *card,
1194 struct cycx_x25_channel *chan)
1195{
1196 int err = 0,
1197 len;
1198 char d[64],
1199 nibble = 0,
1200 mylen = chan->local_addr ? strlen(chan->local_addr) : 0,
1201 remotelen = strlen(chan->addr);
1202 u8 key;
1203
1204 if (card->u.x.connection_keys == ~0U) {
1205 printk(KERN_INFO "%s: too many simultaneous connection "
1206 "requests!\n", card->devname);
1207 return -EAGAIN;
1208 }
1209
1210 key = ffz(card->u.x.connection_keys);
1211 set_bit(key, (void*)&card->u.x.connection_keys);
1212 ++key;
1213 dprintk(1, KERN_INFO "%s:x25_place_call:key=%d\n", card->devname, key);
1214 memset(d, 0, sizeof(d));
1215 d[1] = key;
1216 d[2] = 0x10;
1217 d[4] = 0x0B;
1218
1219 len = byte_to_nibble(chan->addr, d + 6, &nibble);
1220
1221 if (chan->local_addr)
1222 len += byte_to_nibble(chan->local_addr, d + 6 + len, &nibble);
1223
1224 if (nibble)
1225 ++len;
1226
1227 d[5] = mylen << 4 | remotelen;
1228 d[6 + len + 1] = 0xCC;
1229
1230 if ((err = x25_exec(card, X25_CONNECT_REQUEST, chan->link,
1231 &d, 7 + len + 1, NULL, 0)) != 0)
1232 clear_bit(--key, (void*)&card->u.x.connection_keys);
1233 else
1234 chan->lcn = -key;
1235
1236 return err;
1237}
1238
1239
1240static int cycx_x25_connect_response(struct cycx_device *card,
1241 struct cycx_x25_channel *chan)
1242{
1243 u8 d[8];
1244
1245 memset(d, 0, sizeof(d));
1246 d[0] = d[3] = chan->lcn;
1247 d[2] = 0x10;
1248 d[4] = 0x0F;
1249 d[7] = 0xCC;
1250
1251 return x25_exec(card, X25_CONNECT_RESPONSE, chan->link, &d, 8, NULL, 0);
1252}
1253
1254
1255static int cycx_x25_disconnect_response(struct cycx_device *card, u8 link,
1256 u8 lcn)
1257{
1258 char d[5];
1259
1260 memset(d, 0, sizeof(d));
1261 d[0] = d[3] = lcn;
1262 d[2] = 0x10;
1263 d[4] = 0x17;
1264
1265 return x25_exec(card, X25_DISCONNECT_RESPONSE, link, &d, 5, NULL, 0);
1266}
1267
1268
1269static int x25_clear_call(struct cycx_device *card, u8 link, u8 lcn, u8 cause,
1270 u8 diagn)
1271{
1272 u8 d[7];
1273
1274 memset(d, 0, sizeof(d));
1275 d[0] = d[3] = lcn;
1276 d[2] = 0x10;
1277 d[4] = 0x13;
1278 d[5] = cause;
1279 d[6] = diagn;
1280
1281 return x25_exec(card, X25_DISCONNECT_REQUEST, link, d, 7, NULL, 0);
1282}
1283
1284
1285static int cycx_x25_send(struct cycx_device *card, u8 link, u8 lcn, u8 bitm,
1286 int len, void *buf)
1287{
1288 u8 d[] = "?\xFF\x10??";
1289
1290 d[0] = d[3] = lcn;
1291 d[4] = bitm;
1292
1293 return x25_exec(card, X25_DATA_REQUEST, link, &d, 5, buf, len);
1294}
1295
1296
1297
1298static struct net_device *cycx_x25_get_dev_by_lcn(struct wan_device *wandev,
1299 s16 lcn)
1300{
1301 struct net_device *dev = wandev->dev;
1302 struct cycx_x25_channel *chan;
1303
1304 while (dev) {
1305 chan = (struct cycx_x25_channel*)dev->priv;
1306
1307 if (chan->lcn == lcn)
1308 break;
1309 dev = chan->slave;
1310 }
1311 return dev;
1312}
1313
1314
1315static struct net_device *
1316 cycx_x25_get_dev_by_dte_addr(struct wan_device *wandev, char *dte)
1317{
1318 struct net_device *dev = wandev->dev;
1319 struct cycx_x25_channel *chan;
1320
1321 while (dev) {
1322 chan = (struct cycx_x25_channel*)dev->priv;
1323
1324 if (!strcmp(chan->addr, dte))
1325 break;
1326 dev = chan->slave;
1327 }
1328 return dev;
1329}
1330
1331
1332
1333
1334
1335
1336
1337
1338static int cycx_x25_chan_connect(struct net_device *dev)
1339{
1340 struct cycx_x25_channel *chan = dev->priv;
1341 struct cycx_device *card = chan->card;
1342
1343 if (chan->svc) {
1344 if (!chan->addr[0])
1345 return -EINVAL;
1346
1347 dprintk(1, KERN_INFO "%s: placing X.25 call to %s...\n",
1348 card->devname, chan->addr);
1349
1350 if (x25_place_call(card, chan))
1351 return -EIO;
1352
1353 cycx_x25_set_chan_state(dev, WAN_CONNECTING);
1354 return 1;
1355 } else
1356 cycx_x25_set_chan_state(dev, WAN_CONNECTED);
1357
1358 return 0;
1359}
1360
1361
1362
1363static void cycx_x25_chan_disconnect(struct net_device *dev)
1364{
1365 struct cycx_x25_channel *chan = dev->priv;
1366
1367 if (chan->svc) {
1368 x25_clear_call(chan->card, chan->link, chan->lcn, 0, 0);
1369 cycx_x25_set_chan_state(dev, WAN_DISCONNECTING);
1370 } else
1371 cycx_x25_set_chan_state(dev, WAN_DISCONNECTED);
1372}
1373
1374
1375static void cycx_x25_chan_timer(unsigned long d)
1376{
1377 struct net_device *dev = (struct net_device *)d;
1378 struct cycx_x25_channel *chan = dev->priv;
1379
1380 if (chan->state == WAN_CONNECTED)
1381 cycx_x25_chan_disconnect(dev);
1382 else
1383 printk(KERN_ERR "%s: %s for svc (%s) not connected!\n",
1384 chan->card->devname, __FUNCTION__, dev->name);
1385}
1386
1387
1388static void cycx_x25_set_chan_state(struct net_device *dev, u8 state)
1389{
1390 struct cycx_x25_channel *chan = dev->priv;
1391 struct cycx_device *card = chan->card;
1392 unsigned long flags;
1393 char *string_state = NULL;
1394
1395 spin_lock_irqsave(&card->lock, flags);
1396
1397 if (chan->state != state) {
1398 if (chan->svc && chan->state == WAN_CONNECTED)
1399 del_timer(&chan->timer);
1400
1401 switch (state) {
1402 case WAN_CONNECTED:
1403 string_state = "connected!";
1404 *(__be16*)dev->dev_addr = htons(chan->lcn);
1405 netif_wake_queue(dev);
1406 reset_timer(dev);
1407
1408 if (chan->protocol == ETH_P_X25)
1409 cycx_x25_chan_send_event(dev, 1);
1410
1411 break;
1412 case WAN_CONNECTING:
1413 string_state = "connecting...";
1414 break;
1415 case WAN_DISCONNECTING:
1416 string_state = "disconnecting...";
1417 break;
1418 case WAN_DISCONNECTED:
1419 string_state = "disconnected!";
1420
1421 if (chan->svc) {
1422 *(unsigned short*)dev->dev_addr = 0;
1423 chan->lcn = 0;
1424 }
1425
1426 if (chan->protocol == ETH_P_X25)
1427 cycx_x25_chan_send_event(dev, 2);
1428
1429 netif_wake_queue(dev);
1430 break;
1431 }
1432
1433 printk(KERN_INFO "%s: interface %s %s\n", card->devname,
1434 dev->name, string_state);
1435 chan->state = state;
1436 }
1437
1438 spin_unlock_irqrestore(&card->lock, flags);
1439}
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454static int cycx_x25_chan_send(struct net_device *dev, struct sk_buff *skb)
1455{
1456 struct cycx_x25_channel *chan = dev->priv;
1457 struct cycx_device *card = chan->card;
1458 int bitm = 0;
1459 unsigned len = skb->len;
1460
1461 if (skb->len > card->wandev.mtu) {
1462 len = card->wandev.mtu;
1463 bitm = 0x10;
1464 }
1465
1466 if (cycx_x25_send(card, chan->link, chan->lcn, bitm, len, skb->data))
1467 return 1;
1468
1469 if (bitm) {
1470 skb_pull(skb, len);
1471 return 1;
1472 }
1473
1474 ++chan->ifstats.tx_packets;
1475 chan->ifstats.tx_bytes += len;
1476
1477 return 0;
1478}
1479
1480
1481
1482static void cycx_x25_chan_send_event(struct net_device *dev, u8 event)
1483{
1484 struct sk_buff *skb;
1485 unsigned char *ptr;
1486
1487 if ((skb = dev_alloc_skb(1)) == NULL) {
1488 printk(KERN_ERR "%s: out of memory\n", __FUNCTION__);
1489 return;
1490 }
1491
1492 ptr = skb_put(skb, 1);
1493 *ptr = event;
1494
1495 skb->protocol = x25_type_trans(skb, dev);
1496 netif_rx(skb);
1497 dev->last_rx = jiffies;
1498}
1499
1500
1501static u8 bps_to_speed_code(u32 bps)
1502{
1503 u8 number = 0;
1504
1505 if (bps >= 512000) number = 8;
1506 else if (bps >= 256000) number = 7;
1507 else if (bps >= 64000) number = 6;
1508 else if (bps >= 38400) number = 5;
1509 else if (bps >= 19200) number = 4;
1510 else if (bps >= 9600) number = 3;
1511 else if (bps >= 4800) number = 2;
1512 else if (bps >= 2400) number = 1;
1513
1514 return number;
1515}
1516
1517
1518static u8 cycx_log2(u32 n)
1519{
1520 u8 log = 0;
1521
1522 if (!n)
1523 return 0;
1524
1525 while (n > 1) {
1526 n >>= 1;
1527 ++log;
1528 }
1529
1530 return log;
1531}
1532
1533
1534
1535static unsigned dec_to_uint(u8 *str, int len)
1536{
1537 unsigned val = 0;
1538
1539 if (!len)
1540 len = strlen(str);
1541
1542 for (; len && isdigit(*str); ++str, --len)
1543 val = (val * 10) + (*str - (unsigned) '0');
1544
1545 return val;
1546}
1547
1548static void reset_timer(struct net_device *dev)
1549{
1550 struct cycx_x25_channel *chan = dev->priv;
1551
1552 if (chan->svc)
1553 mod_timer(&chan->timer, jiffies+chan->idle_tmout*HZ);
1554}
1555#ifdef CYCLOMX_X25_DEBUG
1556static void cycx_x25_dump_config(struct cycx_x25_config *conf)
1557{
1558 printk(KERN_INFO "X.25 configuration\n");
1559 printk(KERN_INFO "-----------------\n");
1560 printk(KERN_INFO "link number=%d\n", conf->link);
1561 printk(KERN_INFO "line speed=%d\n", conf->speed);
1562 printk(KERN_INFO "clock=%sternal\n", conf->clock == 8 ? "Ex" : "In");
1563 printk(KERN_INFO "# level 2 retransm.=%d\n", conf->n2);
1564 printk(KERN_INFO "level 2 window=%d\n", conf->n2win);
1565 printk(KERN_INFO "level 3 window=%d\n", conf->n3win);
1566 printk(KERN_INFO "# logical channels=%d\n", conf->nvc);
1567 printk(KERN_INFO "level 3 pkt len=%d\n", conf->pktlen);
1568 printk(KERN_INFO "my address=%d\n", conf->locaddr);
1569 printk(KERN_INFO "remote address=%d\n", conf->remaddr);
1570 printk(KERN_INFO "t1=%d seconds\n", conf->t1);
1571 printk(KERN_INFO "t2=%d seconds\n", conf->t2);
1572 printk(KERN_INFO "t21=%d seconds\n", conf->t21);
1573 printk(KERN_INFO "# PVCs=%d\n", conf->npvc);
1574 printk(KERN_INFO "t23=%d seconds\n", conf->t23);
1575 printk(KERN_INFO "flags=0x%x\n", conf->flags);
1576}
1577
1578static void cycx_x25_dump_stats(struct cycx_x25_stats *stats)
1579{
1580 printk(KERN_INFO "X.25 statistics\n");
1581 printk(KERN_INFO "--------------\n");
1582 printk(KERN_INFO "rx_crc_errors=%d\n", stats->rx_crc_errors);
1583 printk(KERN_INFO "rx_over_errors=%d\n", stats->rx_over_errors);
1584 printk(KERN_INFO "n2_tx_frames=%d\n", stats->n2_tx_frames);
1585 printk(KERN_INFO "n2_rx_frames=%d\n", stats->n2_rx_frames);
1586 printk(KERN_INFO "tx_timeouts=%d\n", stats->tx_timeouts);
1587 printk(KERN_INFO "rx_timeouts=%d\n", stats->rx_timeouts);
1588 printk(KERN_INFO "n3_tx_packets=%d\n", stats->n3_tx_packets);
1589 printk(KERN_INFO "n3_rx_packets=%d\n", stats->n3_rx_packets);
1590 printk(KERN_INFO "tx_aborts=%d\n", stats->tx_aborts);
1591 printk(KERN_INFO "rx_aborts=%d\n", stats->rx_aborts);
1592}
1593
1594static void cycx_x25_dump_devs(struct wan_device *wandev)
1595{
1596 struct net_device *dev = wandev->dev;
1597
1598 printk(KERN_INFO "X.25 dev states\n");
1599 printk(KERN_INFO "name: addr: txoff: protocol:\n");
1600 printk(KERN_INFO "---------------------------------------\n");
1601
1602 while(dev) {
1603 struct cycx_x25_channel *chan = dev->priv;
1604
1605 printk(KERN_INFO "%-5.5s %-15.15s %d ETH_P_%s\n",
1606 chan->name, chan->addr, netif_queue_stopped(dev),
1607 chan->protocol == ETH_P_IP ? "IP" : "X25");
1608 dev = chan->slave;
1609 }
1610}
1611
1612#endif
1613
1614