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-2000 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 * 2000/01/08 acme cleanup
16 * 1999/10/27 acme use ARPHRD_HWX25 so that the X.25 stack know
17 * that we have a X.25 stack implemented in
19 * 1999/10/18 acme support for X.25 sockets in if_send,
20 * beware: socket(AF_X25...) IS WORK IN PROGRESS,
21 * TCP/IP over X.25 via wanrouter not affected,
23 * 1999/10/09 acme chan_disc renamed to chan_disconnect,
24 * began adding support for X.25 sockets:
25 * conf->protocol in new_if
26 * 1999/10/05 acme fixed return E... to return -E...
27 * 1999/08/10 acme serialized access to the card thru a spinlock
29 * 1999/08/09 acme removed per channel spinlocks
30 * removed references to enable_tx_int
31 * 1999/05/28 acme fixed nibble_to_byte, ackvc now properly treated
33 * 1999/05/25 acme fixed t1, t2, t21 & t23 configuration
34 * use spinlocks instead of cli/sti in some points
35 * 1999/05/24 acme finished the x25_get_stat function
36 * 1999/05/23 acme dev->type = ARPHRD_X25 (tcpdump only works,
37 * AFAIT, with ARPHRD_ETHER). This seems to be
38 * needed to use socket(AF_X25)...
39 * Now the config file must specify a peer media
40 * address for svc channels over a crossover cable.
41 * Removed hold_timeout from x25_channel_t,
43 * A little enhancement in the DEBUG processing
44 * 1999/05/22 acme go to DISCONNECTED in disconnect_confirm_intr,
45 * instead of chan_disc.
46 * 1999/05/16 marcelo fixed timer initialization in SVCs
47 * 1999/01/05 acme x25_configure now get (most of) all
49 * 1999/01/05 acme pktlen now (correctly) uses log2 (value
51 * 1999/01/03 acme judicious use of data types (u8, u16, u32, etc)
52 * 1999/01/03 acme cyx_isr: reset dpmbase to acknowledge
53 * indication (interrupt from cyclom 2x)
54 * 1999/01/02 acme cyx_isr: first hackings...
55 * 1999/01/0203 acme when initializing an array don't give less
56 * elements than declared...
57 * example: char send_cmd[6] = "?\xFF\x10";
58 * you'll gonna lose a couple hours, 'cause your
59 * brain won't admit that there's an error in the
60 * above declaration... the side effect is that
61 * memset is put into the unresolved symbols
62 * instead of using the inline memset functions...
63 * 1999/01/02 acme began chan_connect, chan_send, x25_send
64 * 1998/12/31 acme x25_configure
65 * this code can be compiled as non module
66 * 1998/12/27 acme code cleanup
67 * IPX code wiped out! let's decrease code
68 * complexity for now, remember: I'm learning! :)
69 * bps_to_speed_code OK
70 * 1998/12/26 acme Minimal debug code cleanup
71 * 1998/08/08 acme Initial version.
74 #define CYCLOMX_X25_DEBUG 1
76 #include <linux/version.h>
77 #include <linux/kernel.h> /* printk(), and other useful stuff */
78 #include <linux/stddef.h> /* offsetof(), etc. */
79 #include <linux/errno.h> /* return codes */
80 #include <linux/string.h> /* inline memset(), etc. */
81 #include <linux/malloc.h> /* kmalloc(), kfree() */
82 #include <linux/wanrouter.h> /* WAN router definitions */
83 #include <asm/byteorder.h> /* htons(), etc. */
84 #include <linux/if_arp.h> /* ARPHRD_HWX25 */
85 #include <linux/cyclomx.h> /* Cyclom 2X common user API definitions */
86 #include <linux/cycx_x25.h> /* X.25 firmware API definitions */
88 /* Defines & Macros */
89 #define MAX_CMD_RETRY 5
90 #define X25_CHAN_MTU 2048 /* unfragmented logical channel MTU */
93 /* This is an extension of the 'struct net_device' we create for each network
94 interface to keep the rest of X.25 channel-specific data. */
95 typedef struct x25_channel
{
96 /* This member must be first. */
97 struct net_device
*slave
; /* WAN slave */
99 char name
[WAN_IFNAME_SZ
+1]; /* interface name, ASCIIZ */
100 char addr
[WAN_ADDRESS_SZ
+1]; /* media address, ASCIIZ */
101 char *local_addr
; /* local media address, ASCIIZ -
102 svc thru crossover cable */
103 s16 lcn
; /* logical channel number/conn.req.key*/
105 struct timer_list timer
; /* timer used for svc channel disc. */
106 u16 protocol
; /* ethertype, 0 - multiplexed */
107 u8 svc
; /* 0 - permanent, 1 - switched */
108 u8 state
; /* channel state */
109 u8 drop_sequence
; /* mark sequence for dropping */
110 u32 idle_tmout
; /* sec, before disconnecting */
111 struct sk_buff
*rx_skb
; /* receive socket buffer */
112 cycx_t
*card
; /* -> owner */
113 struct enet_statistics ifstats
; /* interface statistics */
116 /* Function Prototypes */
117 /* WAN link driver entry points. These are called by the WAN router module. */
118 static int update (wan_device_t
*wandev
),
119 new_if (wan_device_t
*wandev
, struct net_device
*dev
,
121 del_if (wan_device_t
*wandev
, struct net_device
*dev
);
123 /* Network device interface */
124 static int if_init (struct net_device
*dev
),
125 if_open (struct net_device
*dev
),
126 if_close (struct net_device
*dev
),
127 if_header (struct sk_buff
*skb
, struct net_device
*dev
,
128 u16 type
, void *daddr
, void *saddr
, unsigned len
),
129 if_rebuild_hdr (struct sk_buff
*skb
),
130 if_send (struct sk_buff
*skb
, struct net_device
*dev
);
132 static struct net_device_stats
* if_stats (struct net_device
*dev
);
134 /* Interrupt handlers */
135 static void cyx_isr (cycx_t
*card
),
136 tx_intr (cycx_t
*card
, TX25Cmd
*cmd
),
137 rx_intr (cycx_t
*card
, TX25Cmd
*cmd
),
138 log_intr (cycx_t
*card
, TX25Cmd
*cmd
),
139 stat_intr (cycx_t
*card
, TX25Cmd
*cmd
),
140 connect_confirm_intr (cycx_t
*card
, TX25Cmd
*cmd
),
141 disconnect_confirm_intr (cycx_t
*card
, TX25Cmd
*cmd
),
142 connect_intr (cycx_t
*card
, TX25Cmd
*cmd
),
143 disconnect_intr (cycx_t
*card
, TX25Cmd
*cmd
),
144 spur_intr (cycx_t
*card
, TX25Cmd
*cmd
);
146 /* X.25 firmware interface functions */
147 static int x25_configure (cycx_t
*card
, TX25Config
*conf
),
148 x25_get_stats (cycx_t
*card
),
149 x25_send (cycx_t
*card
, u8 link
, u8 lcn
, u8 bitm
, int len
,
151 x25_connect_response (cycx_t
*card
, x25_channel_t
*chan
),
152 x25_disconnect_response (cycx_t
*card
, u8 link
, u8 lcn
);
154 /* channel functions */
155 static int chan_connect (struct net_device
*dev
),
156 chan_send (struct net_device
*dev
, struct sk_buff
*skb
);
158 static void chan_disconnect (struct net_device
*dev
),
159 chan_x25_send_event(struct net_device
*dev
, u8 event
);
161 /* Miscellaneous functions */
162 static void set_chan_state (struct net_device
*dev
, u8 state
),
163 chan_timer (unsigned long d
);
165 static void nibble_to_byte (u8
*s
, u8
*d
, u8 len
, u8 nibble
),
166 reset_timer (struct net_device
*dev
);
168 static u8
bps_to_speed_code (u32 bps
);
169 static u8
log2 (u32 n
);
171 static unsigned dec_to_uint (u8
*str
, int len
);
173 static struct net_device
*get_dev_by_lcn (wan_device_t
*wandev
, s16 lcn
);
174 static struct net_device
*get_dev_by_dte_addr (wan_device_t
*wandev
, char *dte
);
176 #ifdef CYCLOMX_X25_DEBUG
177 static void hex_dump(char *msg
, unsigned char *p
, int len
);
178 static void x25_dump_config(TX25Config
*conf
);
179 static void x25_dump_stats(TX25Stats
*stats
);
180 static void x25_dump_devs(wan_device_t
*wandev
);
181 #define dprintk(format, a...) printk(format, ##a)
183 #define hex_dump(msg, p, len)
184 #define x25_dump_config(conf)
185 #define x25_dump_stats(stats)
186 #define x25_dump_devs(wandev)
187 #define dprintk(format, a...)
189 /* Public Functions */
191 /* X.25 Protocol Initialization routine.
193 * This routine is called by the main Cyclom 2X module during setup. At this
194 * point adapter is completely initialized and X.25 firmware is running.
195 * o configure adapter
196 * o initialize protocol-specific fields of the adapter data space.
200 int cyx_init (cycx_t
*card
, wandev_conf_t
*conf
)
204 /* Verify configuration ID */
205 if (conf
->config_id
!= WANCONFIG_X25
) {
206 printk(KERN_INFO
"%s: invalid configuration ID %u!\n",
207 card
->devname
, conf
->config_id
);
211 /* Initialize protocol-specific fields */
212 card
->mbox
= card
->hw
.dpmbase
+ X25_MBOX_OFFS
;
213 card
->u
.x
.connection_keys
= 0;
214 card
->u
.x
.lock
= SPIN_LOCK_UNLOCKED
;
216 /* Configure adapter. Here we set reasonable defaults, then parse
217 * device configuration structure and set configuration options.
218 * Most configuration options are verified and corrected (if
219 * necessary) since we can't rely on the adapter to do so and don't
220 * want it to fail either. */
221 memset(&cfg
, 0, sizeof(cfg
));
223 cfg
.clock
= conf
->clocking
== WANOPT_EXTERNAL
? 8 : 55;
224 cfg
.speed
= bps_to_speed_code(conf
->bps
);
230 cfg
.flags
= 0x02; /* default = V35 */
231 cfg
.t1
= 10; /* line carrier timeout */
232 cfg
.t2
= 29; /* tx timeout */
233 cfg
.t21
= 180; /* CALL timeout */
234 cfg
.t23
= 180; /* CLEAR timeout */
237 if (!conf
->mtu
|| conf
->mtu
>= 512)
238 card
->wandev
.mtu
= 512;
239 else if (conf
->mtu
>= 256)
240 card
->wandev
.mtu
= 256;
241 else if (conf
->mtu
>= 128)
242 card
->wandev
.mtu
= 128;
244 card
->wandev
.mtu
= 64;
246 cfg
.pktlen
= log2(card
->wandev
.mtu
);
248 if (conf
->station
== WANOPT_DTE
) {
249 cfg
.locaddr
= 3; /* DTE */
250 cfg
.remaddr
= 1; /* DCE */
252 cfg
.locaddr
= 1; /* DCE */
253 cfg
.remaddr
= 3; /* DTE */
256 if (conf
->interface
== WANOPT_RS232
)
257 cfg
.flags
= 0; /* FIXME just reset the 2nd bit */
259 if (conf
->u
.x25
.hi_pvc
) {
260 card
->u
.x
.hi_pvc
= min(conf
->u
.x25
.hi_pvc
, 4095);
261 card
->u
.x
.lo_pvc
= min(conf
->u
.x25
.lo_pvc
, card
->u
.x
.hi_pvc
);
264 if (conf
->u
.x25
.hi_svc
) {
265 card
->u
.x
.hi_svc
= min(conf
->u
.x25
.hi_svc
, 4095);
266 card
->u
.x
.lo_svc
= min(conf
->u
.x25
.lo_svc
, card
->u
.x
.hi_svc
);
269 if (card
->u
.x
.lo_pvc
== 255)
272 cfg
.npvc
= card
->u
.x
.hi_pvc
- card
->u
.x
.lo_pvc
+ 1;
274 cfg
.nvc
= card
->u
.x
.hi_svc
- card
->u
.x
.lo_svc
+ 1 + cfg
.npvc
;
276 if (conf
->u
.x25
.hdlc_window
)
277 cfg
.n2win
= min(conf
->u
.x25
.hdlc_window
, 7);
279 if (conf
->u
.x25
.pkt_window
)
280 cfg
.n3win
= min(conf
->u
.x25
.pkt_window
, 7);
283 cfg
.t1
= min(conf
->u
.x25
.t1
, 30);
286 cfg
.t2
= min(conf
->u
.x25
.t2
, 30);
288 if (conf
->u
.x25
.t11_t21
)
289 cfg
.t21
= min(conf
->u
.x25
.t11_t21
, 30);
291 if (conf
->u
.x25
.t13_t23
)
292 cfg
.t23
= min(conf
->u
.x25
.t13_t23
, 30);
295 cfg
.n2
= min(conf
->u
.x25
.n2
, 30);
297 /* initialize adapter */
298 if (x25_configure(card
, &cfg
))
301 /* Initialize protocol-specific fields of adapter data space */
302 card
->wandev
.bps
= conf
->bps
;
303 card
->wandev
.interface
= conf
->interface
;
304 card
->wandev
.clocking
= conf
->clocking
;
305 card
->wandev
.station
= conf
->station
;
308 card
->wandev
.update
= update
;
309 card
->wandev
.new_if
= new_if
;
310 card
->wandev
.del_if
= del_if
;
311 card
->wandev
.state
= WAN_DISCONNECTED
;
316 /* WAN Device Driver Entry Points */
317 /* Update device status & statistics. */
318 static int update (wan_device_t
*wandev
)
321 if (!wandev
|| !wandev
->private)
324 if (wandev
->state
== WAN_UNCONFIGURED
)
327 x25_get_stats(wandev
->private);
332 /* Create new logical channel.
333 * This routine is called by the router when ROUTER_IFNEW IOCTL is being
335 * o parse media- and hardware-specific configuration
336 * o make sure that a new channel can be created
337 * o allocate resources, if necessary
338 * o prepare network device structure for registration.
341 * < 0 failure (channel will not be created) */
342 static int new_if (wan_device_t
*wandev
, struct net_device
*dev
,
345 cycx_t
*card
= wandev
->private;
349 if (!conf
->name
[0] || strlen(conf
->name
) > WAN_IFNAME_SZ
) {
350 printk(KERN_INFO
"%s: invalid interface name!\n",card
->devname
);
354 /* allocate and initialize private data */
355 if ((chan
= kmalloc(sizeof(x25_channel_t
), GFP_KERNEL
)) == NULL
)
358 memset(chan
, 0, sizeof(x25_channel_t
));
359 strcpy(chan
->name
, conf
->name
);
361 chan
->link
= conf
->port
;
362 chan
->protocol
= conf
->protocol
? ETH_P_X25
: ETH_P_IP
;
364 /* only used in svc connected thru crossover cable */
365 chan
->local_addr
= NULL
;
367 if (conf
->addr
[0] == '@') { /* SVC */
368 int len
= strlen(conf
->local_addr
);
371 if (len
> WAN_ADDRESS_SZ
) {
372 printk(KERN_ERR
"%s: %s local addr too long!\n",
373 wandev
->name
, chan
->name
);
377 chan
->local_addr
= kmalloc(len
+ 1, GFP_KERNEL
);
379 if (!chan
->local_addr
) {
385 strncpy(chan
->local_addr
, conf
->local_addr
,
390 strncpy(chan
->addr
, &conf
->addr
[1], WAN_ADDRESS_SZ
);
391 init_timer(&chan
->timer
);
392 chan
->timer
.function
= chan_timer
;
393 chan
->timer
.data
= (unsigned long)dev
;
395 /* Set channel timeouts (default if not specified) */
396 chan
->idle_tmout
= conf
->idle_timeout
? conf
->idle_timeout
: 90;
397 } else if (is_digit(conf
->addr
[0])) { /* PVC */
398 s16 lcn
= dec_to_uint(conf
->addr
, 0);
400 if (lcn
>= card
->u
.x
.lo_pvc
&& lcn
<= card
->u
.x
.hi_pvc
)
404 "%s: PVC %u is out of range on interface %s!\n",
405 wandev
->name
, lcn
, chan
->name
);
409 printk(KERN_ERR
"%s: invalid media address on interface %s!\n",
410 wandev
->name
, chan
->name
);
415 if (chan
->local_addr
)
416 kfree(chan
->local_addr
);
422 /* prepare network device data space for registration */
423 dev
->name
= chan
->name
;
430 /* Delete logical channel. */
431 static int del_if (wan_device_t
*wandev
, struct net_device
*dev
)
434 x25_channel_t
*chan
= dev
->priv
;
437 if (chan
->local_addr
)
438 kfree(chan
->local_addr
);
440 if (chan
->state
== WAN_CONNECTED
)
441 del_timer(&chan
->timer
);
451 /* Network Device Interface */
452 /* Initialize Linux network interface.
454 * This routine is called only once for each interface, during Linux network
455 * interface registration. Returning anything but zero will fail interface
457 static int if_init (struct net_device
*dev
)
459 x25_channel_t
*chan
= dev
->priv
;
460 cycx_t
*card
= chan
->card
;
461 wan_device_t
*wandev
= &card
->wandev
;
463 /* Initialize device driver entry points */
465 dev
->stop
= if_close
;
466 dev
->hard_header
= if_header
;
467 dev
->rebuild_header
= if_rebuild_hdr
;
468 dev
->hard_start_xmit
= if_send
;
469 dev
->get_stats
= if_stats
;
471 /* Initialize media-specific parameters */
472 dev
->mtu
= X25_CHAN_MTU
;
473 dev
->type
= ARPHRD_HWX25
; /* ARP h/w type */
474 dev
->hard_header_len
= 0; /* media header length */
475 dev
->addr_len
= 0; /* hardware address length */
478 *(u16
*)dev
->dev_addr
= htons(chan
->lcn
);
480 /* Initialize hardware parameters (just for reference) */
481 dev
->irq
= wandev
->irq
;
482 dev
->dma
= wandev
->dma
;
483 dev
->base_addr
= wandev
->ioport
;
484 dev
->mem_start
= (unsigned long)wandev
->maddr
;
485 dev
->mem_end
= (unsigned long)(wandev
->maddr
+ wandev
->msize
- 1);
486 dev
->flags
|= IFF_NOARP
;
488 /* Set transmit buffer queue length */
489 dev
->tx_queue_len
= 10;
491 /* Initialize socket buffers */
492 dev_init_buffers(dev
);
493 set_chan_state(dev
, WAN_DISCONNECTED
);
498 /* Open network interface.
499 * o prevent module from unloading by incrementing use count
500 * o if link is disconnected then initiate connection
502 * Return 0 if O.k. or errno. */
503 static int if_open (struct net_device
*dev
)
505 x25_channel_t
*chan
= dev
->priv
;
506 cycx_t
*card
= chan
->card
;
508 if (netif_running(dev
))
509 return -EBUSY
; /* only one open is allowed */
511 netif_start_queue(dev
);
512 cyclomx_mod_inc_use_count(card
);
517 /* Close network interface.
519 * o if there's no more open channels then disconnect physical link. */
520 static int if_close (struct net_device
*dev
)
522 x25_channel_t
*chan
= dev
->priv
;
523 cycx_t
*card
= chan
->card
;
525 netif_stop_queue(dev
);
527 if (chan
->state
== WAN_CONNECTED
|| chan
->state
== WAN_CONNECTING
)
528 chan_disconnect(dev
);
530 cyclomx_mod_dec_use_count(card
);
535 /* Build media header.
536 * o encapsulate packet according to encapsulation type.
538 * The trick here is to put packet type (Ethertype) into 'protocol' field of
539 * the socket buffer, so that we don't forget it. If encapsulation fails,
540 * set skb->protocol to 0 and discard packet later.
542 * Return: media header length. */
543 static int if_header (struct sk_buff
*skb
, struct net_device
*dev
,
544 u16 type
, void *daddr
, void *saddr
, unsigned len
)
546 skb
->protocol
= type
;
548 return dev
->hard_header_len
;
551 /* * Re-build media header.
552 * Return: 1 physical address resolved.
553 * 0 physical address not resolved */
554 static int if_rebuild_hdr (struct sk_buff
*skb
)
559 /* Send a packet on a network interface.
560 * o set busy flag (marks start of the transmission).
561 * o check link state. If link is not up, then drop the packet.
562 * o check channel status. If it's down then initiate a call.
563 * o pass a packet to corresponding WAN device.
564 * o free socket buffer
566 * Return: 0 complete (socket buffer must be freed)
567 * non-0 packet may be re-transmitted (tbusy must be set)
570 * 1. This routine is called either by the protocol stack or by the "net
571 * bottom half" (with interrupts enabled).
572 * 2. Setting tbusy flag will inhibit further transmit requests from the
573 * protocol stack and can be used for flow control with protocol layer. */
574 static int if_send (struct sk_buff
*skb
, struct net_device
*dev
)
576 x25_channel_t
*chan
= dev
->priv
;
577 cycx_t
*card
= chan
->card
;
580 chan
->protocol
= skb
->protocol
;
582 if (card
->wandev
.state
!= WAN_CONNECTED
)
583 ++chan
->ifstats
.tx_dropped
;
584 else if (chan
->svc
&& chan
->protocol
&&
585 chan
->protocol
!= skb
->protocol
) {
587 "%s: unsupported Ethertype 0x%04X on interface %s!\n",
588 card
->devname
, skb
->protocol
, dev
->name
);
589 ++chan
->ifstats
.tx_errors
;
590 } else if (chan
->protocol
== ETH_P_IP
) {
591 switch (chan
->state
) {
592 case WAN_DISCONNECTED
:
593 if (chan_connect(dev
)) {
594 netif_stop_queue(dev
);
600 dev
->trans_start
= jiffies
;
601 netif_stop_queue(dev
);
603 if (chan_send(dev
, skb
))
608 ++chan
->ifstats
.tx_dropped
;
609 ++card
->wandev
.stats
.tx_dropped
;
611 } else { /* chan->protocol == ETH_P_X25 */
612 switch (skb
->data
[0]) {
614 case 1: /* Connect request */
617 case 2: /* Disconnect request */
618 chan_disconnect(dev
);
622 "%s: unknown %d x25-iface request on %s!\n",
623 card
->devname
, skb
->data
[0], dev
->name
);
624 ++chan
->ifstats
.tx_errors
;
628 skb_pull(skb
, 1); /* Remove control byte */
630 dev
->trans_start
= jiffies
;
631 netif_stop_queue(dev
);
633 if (chan_send(dev
, skb
)) {
634 /* prepare for future retransmissions */
646 /* Get Ethernet-style interface statistics.
647 * Return a pointer to struct net_device_stats */
648 static struct net_device_stats
*if_stats (struct net_device
*dev
)
650 x25_channel_t
*chan
= dev
->priv
;
652 return chan
? &chan
->ifstats
: NULL
;
655 /* Interrupt Handlers */
656 /* X.25 Interrupt Service Routine. */
657 static void cyx_isr (cycx_t
*card
)
663 card
->buff_int_mode_unbusy
= 0;
664 cycx_peek(&card
->hw
, X25_RXMBOX_OFFS
, &cmd
, sizeof(cmd
));
666 switch (cmd
.command
) {
667 case X25_DATA_INDICATION
:
670 case X25_ACK_FROM_VC
:
674 log_intr(card
, &cmd
);
677 stat_intr(card
, &cmd
);
679 case X25_CONNECT_CONFIRM
:
680 connect_confirm_intr(card
, &cmd
);
682 case X25_CONNECT_INDICATION
:
683 connect_intr(card
, &cmd
);
685 case X25_DISCONNECT_INDICATION
:
686 disconnect_intr(card
, &cmd
);
688 case X25_DISCONNECT_CONFIRM
:
689 disconnect_confirm_intr(card
, &cmd
);
692 cyclomx_set_state(card
, WAN_CONNECTED
);
695 cyclomx_set_state(card
, WAN_DISCONNECTED
);
698 spur_intr(card
, &cmd
); /* unwanted interrupt */
701 cycx_poke(&card
->hw
, 0, &z
, sizeof(z
));
702 cycx_poke(&card
->hw
, X25_RXMBOX_OFFS
, &z
, sizeof(z
));
706 /* Transmit interrupt handler.
707 * o Release socket buffer
708 * o Clear 'tbusy' flag */
709 static void tx_intr (cycx_t
*card
, TX25Cmd
*cmd
)
711 struct net_device
*dev
;
712 wan_device_t
*wandev
= &card
->wandev
;
715 cycx_peek(&card
->hw
, cmd
->buf
, &lcn
, sizeof(lcn
));
717 /* unbusy device and then dev_tint(); */
718 if ((dev
= get_dev_by_lcn(wandev
, lcn
)) != NULL
) {
719 card
->buff_int_mode_unbusy
= 1;
720 netif_wake_queue(dev
);
722 printk(KERN_ERR
"%s:ackvc for inexistent lcn %d\n",
726 /* Receive interrupt handler.
727 * This routine handles fragmented IP packets using M-bit according to the
729 * o map logical channel number to network interface.
730 * o allocate socket buffer or append received packet to the existing one.
731 * o if M-bit is reset (i.e. it's the last packet in a sequence) then
732 * decapsulate packet and pass socket buffer to the protocol stack.
735 * 1. When allocating a socket buffer, if M-bit is set then more data is
736 * coming and we have to allocate buffer for the maximum IP packet size
737 * expected on this channel.
738 * 2. If something goes wrong and X.25 packet has to be dropped (e.g. no
739 * socket buffers available) the whole packet sequence must be discarded. */
740 static void rx_intr (cycx_t
*card
, TX25Cmd
*cmd
)
742 wan_device_t
*wandev
= &card
->wandev
;
743 struct net_device
*dev
;
747 int pktlen
= cmd
->len
- 5;
749 cycx_peek(&card
->hw
, cmd
->buf
, &lcn
, sizeof(lcn
));
750 cycx_peek(&card
->hw
, cmd
->buf
+ 4, &bitm
, sizeof(bitm
));
753 if ((dev
= get_dev_by_lcn(wandev
, lcn
)) == NULL
) {
754 /* Invalid channel, discard packet */
755 printk(KERN_INFO
"%s: receiving on orphaned LCN %d!\n",
763 if (chan
->drop_sequence
) {
765 chan
->drop_sequence
= 0;
770 if ((skb
= chan
->rx_skb
) == NULL
) {
771 /* Allocate new socket buffer */
772 int bufsize
= bitm
? dev
->mtu
: pktlen
;
774 if ((skb
= dev_alloc_skb((chan
->protocol
== ETH_P_X25
? 1 : 0) +
776 dev
->hard_header_len
)) == NULL
) {
777 printk(KERN_INFO
"%s: no socket buffers available!\n",
779 chan
->drop_sequence
= 1;
780 ++chan
->ifstats
.rx_dropped
;
784 if (chan
->protocol
== ETH_P_X25
) /* X.25 socket layer control */
785 /* 0 = data packet (dev_alloc_skb zeroed skb->data) */
789 skb
->protocol
= htons(chan
->protocol
);
793 if (skb_tailroom(skb
) < pktlen
) {
794 /* No room for the packet. Call off the whole thing! */
799 chan
->drop_sequence
= 1;
801 printk(KERN_INFO
"%s: unexpectedly long packet sequence "
802 "on interface %s!\n", card
->devname
, dev
->name
);
803 ++chan
->ifstats
.rx_length_errors
;
807 /* Append packet to the socket buffer */
808 cycx_peek(&card
->hw
, cmd
->buf
+ 5, skb_put(skb
, pktlen
), pktlen
);
811 return; /* more data is coming */
813 dev
->last_rx
= jiffies
; /* timestamp */
814 chan
->rx_skb
= NULL
; /* dequeue packet */
816 ++chan
->ifstats
.rx_packets
;
817 chan
->ifstats
.rx_bytes
+= skb
->len
;
819 skb
->mac
.raw
= skb
->data
;
823 /* Connect interrupt handler. */
824 static void connect_intr (cycx_t
*card
, TX25Cmd
*cmd
)
826 wan_device_t
*wandev
= &card
->wandev
;
827 struct net_device
*dev
= NULL
;
832 u8 lcn
, sizeloc
, sizerem
;
834 cycx_peek(&card
->hw
, cmd
->buf
, &lcn
, sizeof(lcn
));
835 cycx_peek(&card
->hw
, cmd
->buf
+ 5, &sizeloc
, sizeof(sizeloc
));
836 cycx_peek(&card
->hw
, cmd
->buf
+ 6, d
, cmd
->len
- 6);
838 sizerem
= sizeloc
>> 4;
841 loc
[0] = rem
[0] = '\0';
844 nibble_to_byte(d
, loc
, sizeloc
, 0);
847 nibble_to_byte(d
+ (sizeloc
>> 1), rem
, sizerem
, sizeloc
& 1);
849 dprintk(KERN_INFO
"connect_intr:lcn=%d, local=%s, remote=%s\n",
852 if ((dev
= get_dev_by_dte_addr(wandev
, rem
)) == NULL
) {
853 /* Invalid channel, discard packet */
854 printk(KERN_INFO
"%s: connect not expected: remote %s!\n",
861 x25_connect_response(card
, chan
);
862 set_chan_state(dev
, WAN_CONNECTED
);
865 /* Connect confirm interrupt handler. */
866 static void connect_confirm_intr (cycx_t
*card
, TX25Cmd
*cmd
)
868 wan_device_t
*wandev
= &card
->wandev
;
869 struct net_device
*dev
;
873 cycx_peek(&card
->hw
, cmd
->buf
, &lcn
, sizeof(lcn
));
874 cycx_peek(&card
->hw
, cmd
->buf
+ 1, &key
, sizeof(key
));
875 dprintk(KERN_INFO
"%s: connect_confirm_intr:lcn=%d, key=%d\n",
876 card
->devname
, lcn
, key
);
878 if ((dev
= get_dev_by_lcn(wandev
, -key
)) == NULL
) {
879 /* Invalid channel, discard packet */
880 clear_bit(--key
, (void*)&card
->u
.x
.connection_keys
);
881 printk(KERN_INFO
"%s: connect confirm not expected: lcn %d, "
882 "key=%d!\n", card
->devname
, lcn
, key
);
886 clear_bit(--key
, (void*)&card
->u
.x
.connection_keys
);
889 set_chan_state(dev
, WAN_CONNECTED
);
892 /* Disconnect confirm interrupt handler. */
893 static void disconnect_confirm_intr (cycx_t
*card
, TX25Cmd
*cmd
)
895 wan_device_t
*wandev
= &card
->wandev
;
896 struct net_device
*dev
;
899 cycx_peek(&card
->hw
, cmd
->buf
, &lcn
, sizeof(lcn
));
900 dprintk(KERN_INFO
"%s: disconnect_confirm_intr:lcn=%d\n",
902 if ((dev
= get_dev_by_lcn(wandev
, lcn
)) == NULL
) {
903 /* Invalid channel, discard packet */
904 printk(KERN_INFO
"%s:disconnect confirm not expected!:lcn %d\n",
909 set_chan_state(dev
, WAN_DISCONNECTED
);
912 /* disconnect interrupt handler. */
913 static void disconnect_intr (cycx_t
*card
, TX25Cmd
*cmd
)
915 wan_device_t
*wandev
= &card
->wandev
;
916 struct net_device
*dev
;
919 cycx_peek(&card
->hw
, cmd
->buf
, &lcn
, sizeof(lcn
));
920 dprintk(KERN_INFO
"disconnect_intr:lcn=%d\n", lcn
);
922 if ((dev
= get_dev_by_lcn(wandev
, lcn
)) != NULL
) {
923 x25_channel_t
*chan
= dev
->priv
;
925 x25_disconnect_response(card
, chan
->link
, lcn
);
926 set_chan_state(dev
, WAN_DISCONNECTED
);
928 x25_disconnect_response(card
, 0, lcn
);
931 /* LOG interrupt handler. */
932 static void log_intr (cycx_t
*card
, TX25Cmd
*cmd
)
934 #if CYCLOMX_X25_DEBUG
936 u16 size
, toread
, link
, msg_code
;
939 cycx_peek(&card
->hw
, cmd
->buf
, &msg_code
, sizeof(msg_code
));
940 cycx_peek(&card
->hw
, cmd
->buf
+ 2, &link
, sizeof(link
));
941 cycx_peek(&card
->hw
, cmd
->buf
+ 4, &size
, sizeof(size
));
942 /* at most 20 bytes are available... thanks to Daniela :) */
943 toread
= size
< 20 ? size
: 20;
944 cycx_peek(&card
->hw
, cmd
->buf
+ 10, &bf
, toread
);
945 cycx_peek(&card
->hw
, cmd
->buf
+ 10 + toread
, &code
, 1);
946 cycx_peek(&card
->hw
, cmd
->buf
+ 10 + toread
+ 1, &routine
, 1);
948 printk(KERN_INFO
"cyx_isr: X25_LOG (0x4500) indic.:\n");
949 printk(KERN_INFO
"cmd->buf=0x%X\n", cmd
->buf
);
950 printk(KERN_INFO
"Log message code=0x%X\n", msg_code
);
951 printk(KERN_INFO
"Link=%d\n", link
);
952 printk(KERN_INFO
"log code=0x%X\n", code
);
953 printk(KERN_INFO
"log routine=0x%X\n", routine
);
954 printk(KERN_INFO
"Message size=%d\n", size
);
955 hex_dump("Message", bf
, toread
);
959 /* STATISTIC interrupt handler. */
960 static void stat_intr (cycx_t
*card
, TX25Cmd
*cmd
)
962 cycx_peek(&card
->hw
, cmd
->buf
, &card
->u
.x
.stats
,
963 sizeof(card
->u
.x
.stats
));
964 hex_dump("stat_intr", (unsigned char*)&card
->u
.x
.stats
,
965 sizeof(card
->u
.x
.stats
));
966 x25_dump_stats(&card
->u
.x
.stats
);
967 wake_up_interruptible(&card
->wait_stats
);
970 /* Spurious interrupt handler.
972 * If number of spurious interrupts exceeded some limit, then ??? */
973 static void spur_intr (cycx_t
*card
, TX25Cmd
*cmd
)
975 printk(KERN_INFO
"%s: spurious interrupt (0x%X)!\n",
976 card
->devname
, cmd
->command
);
978 #ifdef CYCLOMX_X25_DEBUG
979 static void hex_dump(char *msg
, unsigned char *p
, int len
)
981 unsigned char hex
[1024],
984 if (len
>= (sizeof(hex
) / 2))
985 len
= (sizeof(hex
) / 2) - 1;
988 sprintf(phex
, "%02x", *p
++);
992 printk(KERN_INFO
"%s: %s\n", msg
, hex
);
996 /* Cyclom 2X Firmware-Specific Functions */
997 /* Exec X.25 command. */
998 static int x25_exec (cycx_t
*card
, int command
, int link
,
999 void *d1
, int len1
, void *d2
, int len2
)
1002 unsigned long flags
;
1003 u32 addr
= 0x1200 + 0x2E0 * link
+ 0x1E2;
1004 u8 retry
= MAX_CMD_RETRY
;
1007 c
.command
= command
;
1009 c
.len
= len1
+ len2
;
1011 spin_lock_irqsave(&card
->u
.x
.lock
, flags
);
1014 cycx_poke(&card
->hw
, X25_MBOX_OFFS
, &c
, sizeof(c
) - sizeof(c
.buf
));
1016 /* write X.25 data */
1018 cycx_poke(&card
->hw
, addr
, d1
, len1
);
1022 u32 addr1
= 0xA00 + 0x400 * link
;
1024 cycx_poke(&card
->hw
, addr
+ len1
, d2
, 249);
1025 cycx_poke(&card
->hw
, addr1
, ((u8
*)d2
) + 249,
1028 cycx_poke(&card
->hw
, addr
+ len1
, d2
, len2
);
1032 /* generate interruption, executing command */
1033 cycx_intr(&card
->hw
);
1035 /* wait till card->mbox == 0 */
1037 err
= cycx_exec(card
->mbox
);
1038 } while (retry
-- && err
);
1040 spin_unlock_irqrestore(&card
->u
.x
.lock
, flags
);
1045 /* Configure adapter. */
1046 static int x25_configure (cycx_t
*card
, TX25Config
*conf
)
1053 memset (&x25_cmd_conf
, 0, sizeof(x25_cmd_conf
));
1054 x25_cmd_conf
.nlinks
= 2;
1055 x25_cmd_conf
.conf
[0] = *conf
;
1056 /* FIXME: we need to find a way in the wanrouter framework
1057 to configure the second link, for now lets use it
1058 with the same config from the first link, fixing
1059 the interface type to RS232, the speed in 38400 and
1060 the clock to external */
1061 x25_cmd_conf
.conf
[1] = *conf
;
1062 x25_cmd_conf
.conf
[1].link
= 1;
1063 x25_cmd_conf
.conf
[1].speed
= 5; /* 38400 */
1064 x25_cmd_conf
.conf
[1].clock
= 8;
1065 x25_cmd_conf
.conf
[1].flags
= 0; /* default = RS232 */
1067 x25_dump_config(&x25_cmd_conf
.conf
[0]);
1068 x25_dump_config(&x25_cmd_conf
.conf
[1]);
1070 return x25_exec(card
, X25_CONFIG
, 0,
1071 &x25_cmd_conf
, sizeof(x25_cmd_conf
), NULL
, 0);
1074 /* Get protocol statistics. */
1075 static int x25_get_stats (cycx_t
*card
)
1077 /* the firmware expects 20 in the size field!!!
1078 thanks to Daniela */
1079 int err
= x25_exec(card
, X25_STATISTIC
, 0, NULL
, 20, NULL
, 0);
1084 interruptible_sleep_on(&card
->wait_stats
);
1086 if (signal_pending(current
))
1089 card
->wandev
.stats
.rx_packets
= card
->u
.x
.stats
.n2_rx_frames
;
1090 card
->wandev
.stats
.rx_over_errors
= card
->u
.x
.stats
.rx_over_errors
;
1091 card
->wandev
.stats
.rx_crc_errors
= card
->u
.x
.stats
.rx_crc_errors
;
1092 card
->wandev
.stats
.rx_length_errors
= 0; /* not available from fw */
1093 card
->wandev
.stats
.rx_frame_errors
= 0; /* not available from fw */
1094 card
->wandev
.stats
.rx_missed_errors
= card
->u
.x
.stats
.rx_aborts
;
1095 card
->wandev
.stats
.rx_dropped
= 0; /* not available from fw */
1096 card
->wandev
.stats
.rx_errors
= 0; /* not available from fw */
1097 card
->wandev
.stats
.tx_packets
= card
->u
.x
.stats
.n2_tx_frames
;
1098 card
->wandev
.stats
.tx_aborted_errors
= card
->u
.x
.stats
.tx_aborts
;
1099 card
->wandev
.stats
.tx_dropped
= 0; /* not available from fw */
1100 card
->wandev
.stats
.collisions
= 0; /* not available from fw */
1101 card
->wandev
.stats
.tx_errors
= 0; /* not available from fw */
1103 x25_dump_devs(&card
->wandev
);
1108 /* return the number of nibbles */
1109 static int byte_to_nibble(u8
*s
, u8
*d
, char *nibble
)
1113 if (*nibble
&& *s
) {
1120 d
[i
] = (*s
- '0') << 4;
1122 d
[i
] |= *(s
+ 1) - '0';
1134 static void nibble_to_byte(u8
*s
, u8
*d
, u8 len
, u8 nibble
)
1137 *d
++ = '0' + (*s
++ & 0x0F);
1142 *d
++ = '0' + (*s
>> 4);
1145 *d
++ = '0' + (*s
& 0x0F);
1155 /* Place X.25 call. */
1156 static int x25_place_call (cycx_t
*card
, x25_channel_t
*chan
)
1162 mylen
= chan
->local_addr
? strlen(chan
->local_addr
) : 0,
1163 remotelen
= strlen(chan
->addr
);
1166 if (card
->u
.x
.connection_keys
== ~0UL) {
1167 printk(KERN_INFO
"%s: too many simultaneous connection "
1168 "requests!\n", card
->devname
);
1172 key
= ffz(card
->u
.x
.connection_keys
);
1173 set_bit(key
, (void*)&card
->u
.x
.connection_keys
);
1175 dprintk(KERN_INFO
"%s:x25_place_call:key=%d\n", card
->devname
, key
);
1176 memset(d
, 0, sizeof(d
));
1177 d
[1] = key
; /* user key */
1181 len
= byte_to_nibble(chan
->addr
, d
+ 6, &nibble
);
1183 if (chan
->local_addr
)
1184 len
+= byte_to_nibble(chan
->local_addr
, d
+ 6 + len
, &nibble
);
1189 d
[5] = mylen
<< 4 | remotelen
;
1190 d
[6 + len
+ 1] = 0xCC; /* TCP/IP over X.25, thanks to Daniela :) */
1192 if ((err
= x25_exec(card
, X25_CONNECT_REQUEST
, chan
->link
,
1193 &d
, 7 + len
+ 1, NULL
, 0)) != 0)
1194 clear_bit(--key
, (void*)&card
->u
.x
.connection_keys
);
1201 /* Place X.25 CONNECT RESPONSE. */
1202 static int x25_connect_response (cycx_t
*card
, x25_channel_t
*chan
)
1206 memset(d
, 0, sizeof(d
));
1207 d
[0] = d
[3] = chan
->lcn
;
1210 d
[7] = 0xCC; /* TCP/IP over X.25, thanks Daniela */
1212 return x25_exec(card
, X25_CONNECT_RESPONSE
, chan
->link
, &d
, 8, NULL
, 0);
1215 /* Place X.25 DISCONNECT RESPONSE. */
1216 static int x25_disconnect_response (cycx_t
*card
, u8 link
, u8 lcn
)
1220 memset(d
, 0, sizeof(d
));
1225 return x25_exec(card
, X25_DISCONNECT_RESPONSE
, link
, &d
, 5, NULL
, 0);
1228 /* Clear X.25 call. */
1229 static int x25_clear_call (cycx_t
*card
, u8 link
, u8 lcn
, u8 cause
, u8 diagn
)
1233 memset(d
, 0, sizeof(d
));
1240 return x25_exec(card
, X25_DISCONNECT_REQUEST
, link
, d
, 7, NULL
, 0);
1243 /* Send X.25 data packet. */
1244 static int x25_send (cycx_t
*card
, u8 link
, u8 lcn
, u8 bitm
, int len
, void *buf
)
1246 u8 d
[] = "?\xFF\x10??";
1251 return x25_exec(card
, X25_DATA_REQUEST
, link
, &d
, 5, buf
, len
);
1255 /* Find network device by its channel number. */
1256 static struct net_device
*get_dev_by_lcn (wan_device_t
*wandev
, s16 lcn
)
1258 struct net_device
*dev
= wandev
->dev
;
1259 x25_channel_t
*chan
;
1262 if (chan
->lcn
== lcn
)
1269 /* Find network device by its remote dte address. */
1270 static struct net_device
*get_dev_by_dte_addr (wan_device_t
*wandev
, char *dte
)
1272 struct net_device
*dev
= wandev
->dev
;
1273 x25_channel_t
*chan
;
1276 if (!strcmp(chan
->addr
, dte
))
1283 /* Initiate connection on the logical channel.
1284 * o for PVC we just get channel configuration
1285 * o for SVCs place an X.25 call
1287 * Return: 0 connected
1288 * >0 connection in progress
1290 static int chan_connect (struct net_device
*dev
)
1292 x25_channel_t
*chan
= dev
->priv
;
1293 cycx_t
*card
= chan
->card
;
1297 return -EINVAL
; /* no destination address */
1299 dprintk(KERN_INFO
"%s: placing X.25 call to %s...\n",
1300 card
->devname
, chan
->addr
);
1302 if (x25_place_call(card
, chan
))
1305 set_chan_state(dev
, WAN_CONNECTING
);
1308 set_chan_state(dev
, WAN_CONNECTED
);
1313 /* Disconnect logical channel.
1314 * o if SVC then clear X.25 call */
1315 static void chan_disconnect (struct net_device
*dev
)
1317 x25_channel_t
*chan
= dev
->priv
;
1320 x25_clear_call(chan
->card
, chan
->link
, chan
->lcn
, 0, 0);
1321 set_chan_state(dev
, WAN_DISCONNECTING
);
1323 set_chan_state(dev
, WAN_DISCONNECTED
);
1326 /* Called by kernel timer */
1327 static void chan_timer (unsigned long d
)
1329 struct net_device
*dev
= (struct net_device
*)d
;
1330 x25_channel_t
*chan
= dev
->priv
;
1332 if (chan
->state
== WAN_CONNECTED
)
1333 chan_disconnect(dev
);
1335 printk(KERN_ERR
"%s: chan_timer for svc (%s) not connected!\n",
1336 chan
->card
->devname
, dev
->name
);
1339 /* Set logical channel state. */
1340 static void set_chan_state (struct net_device
*dev
, u8 state
)
1342 x25_channel_t
*chan
= dev
->priv
;
1343 cycx_t
*card
= chan
->card
;
1345 char *string_state
= NULL
;
1347 spin_lock_irqsave(&card
->lock
, flags
);
1349 if (chan
->state
!= state
) {
1350 if (chan
->svc
&& chan
->state
== WAN_CONNECTED
)
1351 del_timer(&chan
->timer
);
1355 string_state
= "connected!";
1356 *(u16
*)dev
->dev_addr
= htons(chan
->lcn
);
1357 netif_wake_queue(dev
);
1360 if (chan
->protocol
== ETH_P_X25
)
1361 chan_x25_send_event(dev
, 1);
1365 case WAN_CONNECTING
:
1366 string_state
= "connecting...";
1369 case WAN_DISCONNECTING
:
1370 string_state
= "disconnecting...";
1373 case WAN_DISCONNECTED
:
1374 string_state
= "disconnected!";
1377 *(unsigned short*)dev
->dev_addr
= 0;
1381 if (chan
->protocol
== ETH_P_X25
)
1382 chan_x25_send_event(dev
, 2);
1384 netif_wake_queue(dev
);
1388 printk (KERN_INFO
"%s: interface %s %s\n", card
->devname
,
1389 dev
->name
, string_state
);
1390 chan
->state
= state
;
1393 spin_unlock_irqrestore(&card
->lock
, flags
);
1396 /* Send packet on a logical channel.
1397 * When this function is called, tx_skb field of the channel data space
1398 * points to the transmit socket buffer. When transmission is complete,
1399 * release socket buffer and reset 'tbusy' flag.
1401 * Return: 0 - transmission complete
1405 * 1. If packet length is greater than MTU for this channel, we'll fragment
1406 * the packet into 'complete sequence' using M-bit.
1407 * 2. When transmission is complete, an event notification should be issued
1409 static int chan_send (struct net_device
*dev
, struct sk_buff
*skb
)
1411 x25_channel_t
*chan
= dev
->priv
;
1412 cycx_t
*card
= chan
->card
;
1413 int bitm
= 0; /* final packet */
1414 unsigned len
= skb
->len
;
1416 if (skb
->len
> card
->wandev
.mtu
) {
1417 len
= card
->wandev
.mtu
;
1418 bitm
= 0x10; /* set M-bit (more data) */
1421 if (x25_send(card
, chan
->link
, chan
->lcn
, bitm
, len
, skb
->data
))
1429 ++chan
->ifstats
.tx_packets
;
1430 chan
->ifstats
.tx_bytes
+= len
;
1435 /* Send event (connection, disconnection, etc) to X.25 socket layer */
1437 static void chan_x25_send_event(struct net_device
*dev
, u8 event
)
1439 struct sk_buff
*skb
;
1442 if ((skb
= dev_alloc_skb(1)) == NULL
) {
1443 printk(KERN_ERR __FUNCTION__
": out of memory\n");
1447 ptr
= skb_put(skb
, 1);
1451 skb
->protocol
= htons(ETH_P_X25
);
1452 skb
->mac
.raw
= skb
->data
;
1453 skb
->pkt_type
= PACKET_HOST
;
1458 /* Convert line speed in bps to a number used by cyclom 2x code. */
1459 static u8
bps_to_speed_code (u32 bps
)
1461 u8 number
= 0; /* defaults to the lowest (1200) speed ;> */
1463 if (bps
>= 512000) number
= 8;
1464 else if (bps
>= 256000) number
= 7;
1465 else if (bps
>= 64000) number
= 6;
1466 else if (bps
>= 38400) number
= 5;
1467 else if (bps
>= 19200) number
= 4;
1468 else if (bps
>= 9600) number
= 3;
1469 else if (bps
>= 4800) number
= 2;
1470 else if (bps
>= 2400) number
= 1;
1476 static u8
log2 (u32 n
)
1491 /* Convert decimal string to unsigned integer.
1492 * If len != 0 then only 'len' characters of the string are converted. */
1493 static unsigned dec_to_uint (u8
*str
, int len
)
1500 for (; len
&& is_digit(*str
); ++str
, --len
)
1501 val
= (val
* 10) + (*str
- (unsigned) '0');
1506 static void reset_timer(struct net_device
*dev
)
1508 x25_channel_t
*chan
= dev
->priv
;
1511 del_timer(&chan
->timer
);
1512 chan
->timer
.expires
= jiffies
+ chan
->idle_tmout
* HZ
;
1513 add_timer(&chan
->timer
);
1516 #ifdef CYCLOMX_X25_DEBUG
1517 static void x25_dump_config(TX25Config
*conf
)
1519 printk(KERN_INFO
"X.25 configuration\n");
1520 printk(KERN_INFO
"-----------------\n");
1521 printk(KERN_INFO
"link number=%d\n", conf
->link
);
1522 printk(KERN_INFO
"line speed=%d\n", conf
->speed
);
1523 printk(KERN_INFO
"clock=%sternal\n", conf
->clock
== 8 ? "Ex" : "In");
1524 printk(KERN_INFO
"# level 2 retransm.=%d\n", conf
->n2
);
1525 printk(KERN_INFO
"level 2 window=%d\n", conf
->n2win
);
1526 printk(KERN_INFO
"level 3 window=%d\n", conf
->n3win
);
1527 printk(KERN_INFO
"# logical channels=%d\n", conf
->nvc
);
1528 printk(KERN_INFO
"level 3 pkt len=%d\n", conf
->pktlen
);
1529 printk(KERN_INFO
"my address=%d\n", conf
->locaddr
);
1530 printk(KERN_INFO
"remote address=%d\n", conf
->remaddr
);
1531 printk(KERN_INFO
"t1=%d seconds\n", conf
->t1
);
1532 printk(KERN_INFO
"t2=%d seconds\n", conf
->t2
);
1533 printk(KERN_INFO
"t21=%d seconds\n", conf
->t21
);
1534 printk(KERN_INFO
"# PVCs=%d\n", conf
->npvc
);
1535 printk(KERN_INFO
"t23=%d seconds\n", conf
->t23
);
1536 printk(KERN_INFO
"flags=0x%x\n", conf
->flags
);
1539 static void x25_dump_stats(TX25Stats
*stats
)
1541 printk(KERN_INFO
"X.25 statistics\n");
1542 printk(KERN_INFO
"--------------\n");
1543 printk(KERN_INFO
"rx_crc_errors=%d\n", stats
->rx_crc_errors
);
1544 printk(KERN_INFO
"rx_over_errors=%d\n", stats
->rx_over_errors
);
1545 printk(KERN_INFO
"n2_tx_frames=%d\n", stats
->n2_tx_frames
);
1546 printk(KERN_INFO
"n2_rx_frames=%d\n", stats
->n2_rx_frames
);
1547 printk(KERN_INFO
"tx_timeouts=%d\n", stats
->tx_timeouts
);
1548 printk(KERN_INFO
"rx_timeouts=%d\n", stats
->rx_timeouts
);
1549 printk(KERN_INFO
"n3_tx_packets=%d\n", stats
->n3_tx_packets
);
1550 printk(KERN_INFO
"n3_rx_packets=%d\n", stats
->n3_rx_packets
);
1551 printk(KERN_INFO
"tx_aborts=%d\n", stats
->tx_aborts
);
1552 printk(KERN_INFO
"rx_aborts=%d\n", stats
->rx_aborts
);
1555 static void x25_dump_devs(wan_device_t
*wandev
)
1557 struct net_device
*dev
= wandev
->dev
;
1559 printk(KERN_INFO
"X.25 dev states\n");
1560 printk(KERN_INFO
"name: addr: txoff: protocol:\n");
1561 printk(KERN_INFO
"---------------------------------------\n");
1564 x25_channel_t
*chan
= dev
->priv
;
1566 printk(KERN_INFO
"%-5.5s %-15.15s %d ETH_P_%s\n",
1567 chan
->name
, chan
->addr
, netif_queue_stopped(dev
),
1568 chan
->protocol
== ETH_P_IP
? "IP" : "X25");
1573 #endif /* CYCLOMX_X25_DEBUG */