Import 2.3.18pre1
[davej-history.git] / drivers / net / cycx_x25.c
blob7e79943c0c5ac30ac46786d759edd5623b4104e1
1 /*
2 * cycx_x25.c CYCLOM X Multiprotocol WAN Link Driver. X.25 module.
4 * Author: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
5 * Copyright: (c) 1998, 1999 Arnaldo Carvalho de Melo
7 * Based on sdla_x25.c by Gene Kozin <genek@compuserve.com>
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version.
13 * ============================================================================
14 * 1999/08/10 acme serialized access to the card thru a spinlock
15 * in x25_exec
16 * 1999/08/09 acme removed per channel spinlocks
17 * removed references to enable_tx_int
18 * 1999/05/28 acme fixed nibble_to_byte, ackvc now properly treated
19 * if_send simplified
20 * 1999/05/25 acme fixed t1, t2, t21 & t23 configuration
21 * use spinlocks instead of cli/sti in some points
22 * 1999/05/24 acme finished the x25_get_stat function
23 * 1999/05/23 acme dev->type = ARPHRD_X25 (tcpdump only works,
24 * AFAIT, with ARPHRD_ETHER). This seems to be
25 * needed to use socket(AF_X25)...
26 * Now the config file must specify a peer media
27 * address for svc channes over a crossover cable.
28 * Removed hold_timeout from x25_channel_t,
29 * not used.
30 * A little enhancement in the DEBUG processing
31 * 1999/05/22 acme go to DISCONNECTED in disconnect_confirm_intr,
32 * instead of chan_disc.
33 * 1999/05/16 marcelo fixed timer initialization in SVCs
34 * 1999/01/05 acme x25_configure now get (most of) all
35 * parameters...
36 * 1999/01/05 acme pktlen now (correctly) uses log2 (value
37 * configured)
38 * 1999/01/03 acme judicious use of data types (u8, u16, u32, etc)
39 * 1999/01/03 acme cyx_isr: reset dpmbase to acknowledge
40 * indication (interrupt from cyclom 2x)
41 * 1999/01/02 acme cyx_isr: first hackings...
42 * 1999/01/0203 acme when initializing an array don't give less
43 * elements than declared...
44 * example: char send_cmd[6] = "?\xFF\x10";
45 * you'll gonna lose a couple hours, 'cause your
46 * brain won't admit that there's an error in the
47 * above declaration... the side effect is that
48 * memset is put into the unresolved symbols
49 * instead of using the inline memset functions...
50 * 1999/01/02 acme began chan_connect, chan_send, x25_send
51 * Dec 31, 1998 Arnaldo x25_configure
52 * this code can be compiled as non module
53 * Dec 27, 1998 Arnaldo code cleanup
54 * IPX code wiped out! let's decrease code
55 * complexity for now, remember: I'm learning! :)
56 * bps_to_speed_code OK
57 * Dec 26, 1998 Arnaldo Minimal debug code cleanup
58 * Aug 08, 1998 Arnaldo Initial version.
60 #define CYCLOMX_X25_DEBUG 1
62 #include <linux/version.h>
63 #include <linux/kernel.h> /* printk(), and other useful stuff */
64 #include <linux/stddef.h> /* offsetof(), etc. */
65 #include <linux/errno.h> /* return codes */
66 #include <linux/string.h> /* inline memset(), etc. */
67 #include <linux/malloc.h> /* kmalloc(), kfree() */
68 #include <linux/wanrouter.h> /* WAN router definitions */
69 #include <asm/byteorder.h> /* htons(), etc. */
70 #include <linux/if_arp.h> /* ARPHRD_X25 */
71 #include <linux/cyclomx.h> /* CYCLOM X common user API definitions */
72 #include <linux/cycx_x25.h> /* X.25 firmware API definitions */
74 /* Defines & Macros */
75 #define MAX_CMD_RETRY 5
76 #define X25_CHAN_MTU 2048 /* unfragmented logical channel MTU */
78 /* Data Structures */
79 /* This is an extention of the 'struct net_device' we create for each network
80 interface to keep the rest of X.25 channel-specific data. */
81 typedef struct x25_channel {
82 char name[WAN_IFNAME_SZ+1]; /* interface name, ASCIIZ */
83 char addr[WAN_ADDRESS_SZ+1]; /* media address, ASCIIZ */
84 char *local_addr; /* local media address, ASCIIZ -
85 svc thru crossover cable */
86 s16 lcn; /* logical channel number/conn.req.key*/
87 u8 link;
88 struct timer_list timer; /* timer used for svc channel disc. */
89 u16 protocol; /* ethertype, 0 - multiplexed */
90 u8 svc; /* 0 - permanent, 1 - switched */
91 u8 state; /* channel state */
92 u8 drop_sequence; /* mark sequence for dropping */
93 u32 idle_tmout; /* sec, before disconnecting */
94 struct sk_buff *rx_skb; /* receive socket buffer */
95 cycx_t *card; /* -> owner */
96 struct enet_statistics ifstats; /* interface statistics */
97 } x25_channel_t;
99 /* Function Prototypes */
100 /* WAN link driver entry points. These are called by the WAN router module. */
101 static int update (wan_device_t *wandev),
102 new_if (wan_device_t *wandev, struct net_device *dev,wanif_conf_t *conf),
103 del_if (wan_device_t *wandev, struct net_device *dev);
105 /* Network device interface */
106 static int if_init (struct net_device *dev),
107 if_open (struct net_device *dev),
108 if_close (struct net_device *dev),
109 if_header (struct sk_buff *skb, struct net_device *dev,
110 u16 type, void *daddr, void *saddr, unsigned len),
111 if_rebuild_hdr (struct sk_buff *skb),
112 if_send (struct sk_buff *skb, struct net_device *dev);
114 static struct net_device_stats * if_stats (struct net_device *dev);
116 /* Interrupt handlers */
117 static void cyx_isr (cycx_t *card),
118 tx_intr (cycx_t *card, TX25Cmd *cmd),
119 rx_intr (cycx_t *card, TX25Cmd *cmd),
120 log_intr (cycx_t *card, TX25Cmd *cmd),
121 stat_intr (cycx_t *card, TX25Cmd *cmd),
122 connect_confirm_intr (cycx_t *card, TX25Cmd *cmd),
123 disconnect_confirm_intr (cycx_t *card, TX25Cmd *cmd),
124 connect_intr (cycx_t *card, TX25Cmd *cmd),
125 disconnect_intr (cycx_t *card, TX25Cmd *cmd),
126 spur_intr (cycx_t *card, TX25Cmd *cmd);
128 /* X.25 firmware interface functions */
129 static int x25_configure (cycx_t *card, TX25Config *conf),
130 x25_get_stats (cycx_t *card),
131 x25_send (cycx_t *card, u8 link, u8 lcn, u8 bitm, int len,void *buf),
132 x25_connect_response (cycx_t *card, x25_channel_t *chan),
133 x25_disconnect_response (cycx_t *card, u8 link, u8 lcn);
135 /* Miscellaneous functions */
136 static int chan_connect (struct net_device *dev),
137 chan_send (struct net_device *dev, struct sk_buff *skb);
139 static void set_chan_state (struct net_device *dev, u8 state),
140 nibble_to_byte (u8 *s, u8 *d, u8 len, u8 nibble),
141 reset_timer (struct net_device *dev),
142 chan_disc (struct net_device *dev),
143 chan_timer (unsigned long d);
145 static u8 bps_to_speed_code (u32 bps);
146 static u8 log2 (u32 n);
148 static unsigned dec_to_uint (u8 *str, int len);
150 static struct net_device *get_dev_by_lcn (wan_device_t *wandev, s16 lcn);
151 static struct net_device *get_dev_by_dte_addr (wan_device_t *wandev, char *dte);
153 #ifdef CYCLOMX_X25_DEBUG
154 static void hex_dump(char *msg, unsigned char *p, int len);
155 static void x25_dump_config(TX25Config *conf);
156 static void x25_dump_stats(TX25Stats *stats);
157 static void x25_dump_devs(wan_device_t *wandev);
158 #define dprintk(format, a...) printk(format, ##a)
159 #else
160 #define hex_dump(msg, p, len)
161 #define x25_dump_config(conf)
162 #define x25_dump_stats(stats)
163 #define x25_dump_devs(wandev)
164 #define dprintk(format, a...)
165 #endif
166 /* Public Functions */
168 /* X.25 Protocol Initialization routine.
170 * This routine is called by the main CYCLOM X module during setup. At this
171 * point adapter is completely initialized and X.25 firmware is running.
172 * o read firmware version (to make sure it's alive)
173 * o configure adapter
174 * o initialize protocol-specific fields of the adapter data space.
176 * Return: 0 o.k.
177 * < 0 failure. */
178 int cyx_init (cycx_t *card, wandev_conf_t *conf)
180 TX25Config cfg;
182 /* Verify configuration ID */
183 if (conf->config_id != WANCONFIG_X25) {
184 printk(KERN_INFO "%s: invalid configuration ID %u!\n",
185 card->devname, conf->config_id);
186 return -EINVAL;
189 /* Initialize protocol-specific fields */
190 card->mbox = card->hw.dpmbase + X25_MBOX_OFFS;
191 card->u.x.connection_keys = 0;
192 card->u.x.lock = SPIN_LOCK_UNLOCKED;
194 /* Configure adapter. Here we set resonable defaults, then parse
195 * device configuration structure and set configuration options.
196 * Most configuration options are verified and corrected (if
197 * necessary) since we can't rely on the adapter to do so and don't
198 * want it to fail either. */
199 memset(&cfg, 0, sizeof(cfg));
200 cfg.link = 0;
201 cfg.clock = conf->clocking == WANOPT_EXTERNAL ? 8 : 55;
202 cfg.speed = bps_to_speed_code(conf->bps);
203 cfg.n3win = 7;
204 cfg.n2win = 2;
205 cfg.n2 = 5;
206 cfg.nvc = 1;
207 cfg.npvc = 1;
208 cfg.flags = 0x02; /* default = V35 */
209 cfg.t1 = 10; /* line carrier timeout */
210 cfg.t2 = 29; /* tx timeout */
211 cfg.t21 = 180; /* CALL timeout */
212 cfg.t23 = 180; /* CLEAR timeout */
214 /* adjust MTU */
215 if (!conf->mtu || conf->mtu >= 512)
216 card->wandev.mtu = 512;
217 else if (conf->mtu >= 256)
218 card->wandev.mtu = 256;
219 else if (conf->mtu >= 128)
220 card->wandev.mtu = 128;
221 else
222 card->wandev.mtu = 64;
224 cfg.pktlen = log2(card->wandev.mtu);
226 if (conf->station == WANOPT_DTE) {
227 cfg.locaddr = 3; /* DTE */
228 cfg.remaddr = 1; /* DCE */
229 } else {
230 cfg.locaddr = 1; /* DCE */
231 cfg.remaddr = 3; /* DTE */
234 if (conf->interface == WANOPT_RS232)
235 cfg.flags = 0; /* FIXME just reset the 2nd bit */
237 if (conf->u.x25.hi_pvc) {
238 card->u.x.hi_pvc = min(conf->u.x25.hi_pvc, 4095);
239 card->u.x.lo_pvc = min(conf->u.x25.lo_pvc, card->u.x.hi_pvc);
242 if (conf->u.x25.hi_svc) {
243 card->u.x.hi_svc = min(conf->u.x25.hi_svc, 4095);
244 card->u.x.lo_svc = min(conf->u.x25.lo_svc, card->u.x.hi_svc);
247 if (card->u.x.lo_pvc == 255)
248 cfg.npvc = 0;
249 else
250 cfg.npvc = card->u.x.hi_pvc - card->u.x.lo_pvc + 1;
252 cfg.nvc = card->u.x.hi_svc - card->u.x.lo_svc + 1 + cfg.npvc;
254 if (conf->u.x25.hdlc_window)
255 cfg.n2win = min(conf->u.x25.hdlc_window, 7);
257 if (conf->u.x25.pkt_window)
258 cfg.n3win = min(conf->u.x25.pkt_window, 7);
260 if (conf->u.x25.t1)
261 cfg.t1 = min(conf->u.x25.t1, 30);
263 if (conf->u.x25.t2)
264 cfg.t2 = min(conf->u.x25.t2, 30);
266 if (conf->u.x25.t11_t21)
267 cfg.t21 = min(conf->u.x25.t11_t21, 30);
269 if (conf->u.x25.t13_t23)
270 cfg.t23 = min(conf->u.x25.t13_t23, 30);
272 if (conf->u.x25.n2)
273 cfg.n2 = min(conf->u.x25.n2, 30);
275 /* initialize adapter */
276 if (x25_configure(card, &cfg))
277 return -EIO;
279 /* Initialize protocol-specific fields of adapter data space */
280 card->wandev.bps = conf->bps;
281 card->wandev.interface = conf->interface;
282 card->wandev.clocking = conf->clocking;
283 card->wandev.station = conf->station;
284 card->isr = &cyx_isr;
285 card->exec = NULL;
286 card->wandev.update = &update;
287 card->wandev.new_if = &new_if;
288 card->wandev.del_if = &del_if;
289 card->wandev.state = WAN_DISCONNECTED;
290 return 0;
293 /* WAN Device Driver Entry Points */
294 /* Update device status & statistics. */
295 static int update (wan_device_t *wandev)
297 /* sanity checks */
298 if (!wandev || !wandev->private)
299 return -EFAULT;
301 if (wandev->state == WAN_UNCONFIGURED)
302 return -ENODEV;
304 x25_get_stats(wandev->private);
305 return 0;
308 /* Create new logical channel.
309 * This routine is called by the router when ROUTER_IFNEW IOCTL is being
310 * handled.
311 * o parse media- and hardware-specific configuration
312 * o make sure that a new channel can be created
313 * o allocate resources, if necessary
314 * o prepare network device structure for registaration.
316 * Return: 0 o.k.
317 * < 0 failure (channel will not be created) */
318 static int new_if (wan_device_t *wandev, struct net_device *dev, wanif_conf_t *conf)
320 cycx_t *card = wandev->private;
321 x25_channel_t *chan;
322 int err = 0;
324 if (conf->name[0] == '\0' || strlen(conf->name) > WAN_IFNAME_SZ) {
325 printk(KERN_INFO "%s: invalid interface name!\n",card->devname);
326 return -EINVAL;
329 /* allocate and initialize private data */
330 if ((chan = kmalloc(sizeof(x25_channel_t), GFP_KERNEL)) == NULL)
331 return -ENOMEM;
333 memset(chan, 0, sizeof(x25_channel_t));
334 strcpy(chan->name, conf->name);
335 chan->card = card;
336 chan->link = conf->port;
337 chan->protocol = ETH_P_IP;
338 chan->rx_skb = NULL;
339 /* only used in svc connected thru crossover cable */
340 chan->local_addr = NULL;
342 if (conf->addr[0] == '@') { /* SVC */
343 int len = strlen(conf->local_addr);
345 if (len) {
346 if (len > WAN_ADDRESS_SZ) {
347 printk(KERN_ERR "%s: %s local addr too long!\n",
348 wandev->name, chan->name);
349 kfree(chan);
350 return -EINVAL;
351 } else {
352 chan->local_addr = kmalloc(len + 1, GFP_KERNEL);
354 if (!chan->local_addr) {
355 kfree(chan);
356 return ENOMEM;
360 strncpy(chan->local_addr, conf->local_addr,
361 WAN_ADDRESS_SZ);
364 chan->svc = 1;
365 strncpy(chan->addr, &conf->addr[1], WAN_ADDRESS_SZ);
366 init_timer(&chan->timer);
367 chan->timer.function = chan_timer;
368 chan->timer.data = (unsigned long) dev;
370 /* Set channel timeouts (default if not specified) */
371 chan->idle_tmout = conf->idle_timeout ? conf->idle_timeout : 90;
372 } else if (is_digit(conf->addr[0])) { /* PVC */
373 s16 lcn = dec_to_uint(conf->addr, 0);
375 if (lcn >= card->u.x.lo_pvc && lcn <= card->u.x.hi_pvc)
376 chan->lcn = lcn;
377 else {
378 printk(KERN_ERR
379 "%s: PVC %u is out of range on interface %s!\n",
380 wandev->name, lcn, chan->name);
381 err = -EINVAL;
383 } else {
384 printk(KERN_ERR "%s: invalid media address on interface %s!\n",
385 wandev->name, chan->name);
386 err = -EINVAL;
389 if (err) {
390 if (chan->local_addr)
391 kfree(chan->local_addr);
393 kfree(chan);
394 return err;
397 /* prepare network device data space for registration */
398 dev->name = chan->name;
399 dev->init = &if_init;
400 dev->priv = chan;
401 return 0;
404 /* Delete logical channel. */
405 static int del_if (wan_device_t *wandev, struct net_device *dev)
407 if (!dev) {
408 printk(KERN_ERR "cycx_x25:del_if:dev == NULL!\n");
409 return 0;
412 if (dev->priv) {
413 x25_channel_t *chan = dev->priv;
415 if (chan->svc) {
416 if (chan->local_addr)
417 kfree(chan->local_addr);
419 if (chan->state == WAN_CONNECTED)
420 del_timer(&chan->timer);
423 kfree(chan);
424 dev->priv = NULL;
427 return 0;
430 /* Network Device Interface */
431 /* Initialize Linux network interface.
433 * This routine is called only once for each interface, during Linux network
434 * interface registration. Returning anything but zero will fail interface
435 * registration. */
436 static int if_init (struct net_device *dev)
438 x25_channel_t *chan = dev->priv;
439 cycx_t *card = chan->card;
440 wan_device_t *wandev = &card->wandev;
442 /* Initialize device driver entry points */
443 dev->open = &if_open;
444 dev->stop = &if_close;
445 dev->hard_header = &if_header;
446 dev->rebuild_header = &if_rebuild_hdr;
447 dev->hard_start_xmit = &if_send;
448 dev->get_stats = &if_stats;
450 /* Initialize media-specific parameters */
451 dev->mtu = X25_CHAN_MTU;
452 dev->type = ARPHRD_X25; /* ARP h/w type */
453 dev->hard_header_len = 0; /* media header length */
454 dev->addr_len = 0; /* hardware address length */
456 if (!chan->svc)
457 *(u16*)dev->dev_addr = htons(chan->lcn);
459 /* Initialize hardware parameters (just for reference) */
460 dev->irq = wandev->irq;
461 dev->dma = wandev->dma;
462 dev->base_addr = wandev->ioport;
463 dev->mem_start = (unsigned long)wandev->maddr;
464 dev->mem_end = (unsigned long)(wandev->maddr + wandev->msize - 1);
465 dev->flags |= IFF_NOARP;
467 /* Set transmit buffer queue length */
468 dev->tx_queue_len = 10;
470 /* Initialize socket buffers */
471 dev_init_buffers(dev);
472 set_chan_state(dev, WAN_DISCONNECTED);
473 return 0;
476 /* Open network interface.
477 * o prevent module from unloading by incrementing use count
478 * o if link is disconnected then initiate connection
480 * Return 0 if O.k. or errno. */
481 static int if_open (struct net_device *dev)
483 x25_channel_t *chan = dev->priv;
484 cycx_t *card = chan->card;
486 if (dev->start)
487 return -EBUSY; /* only one open is allowed */
489 dev->interrupt = 0;
490 dev->tbusy = 0;
491 dev->start = 1;
492 cyclomx_open(card);
494 return 0;
497 /* Close network interface.
498 * o reset flags.
499 * o if there's no more open channels then disconnect physical link. */
500 static int if_close (struct net_device *dev)
502 x25_channel_t *chan = dev->priv;
503 cycx_t *card = chan->card;
505 dev->start = 0;
507 if (chan->state == WAN_CONNECTED || chan->state == WAN_CONNECTING)
508 chan_disc(dev);
510 cyclomx_close(card);
511 return 0;
514 /* Build media header.
515 * o encapsulate packet according to encapsulation type.
517 * The trick here is to put packet type (Ethertype) into 'protocol' field of
518 * the socket buffer, so that we don't forget it. If encapsulation fails,
519 * set skb->protocol to 0 and discard packet later.
521 * Return: media header length. */
522 static int if_header (struct sk_buff *skb, struct net_device *dev,
523 u16 type, void *daddr, void *saddr, unsigned len)
525 skb->protocol = type;
526 return dev->hard_header_len;
529 /* * Re-build media header.
530 * Return: 1 physical address resolved.
531 * 0 physical address not resolved */
532 static int if_rebuild_hdr (struct sk_buff *skb)
534 return 1;
537 /* Send a packet on a network interface.
538 * o set tbusy flag (marks start of the transmission).
539 * o check link state. If link is not up, then drop the packet.
540 * o check channel status. If it's down then initiate a call.
541 * o pass a packet to corresponding WAN device.
542 * o free socket buffer
544 * Return: 0 complete (socket buffer must be freed)
545 * non-0 packet may be re-transmitted (tbusy must be set)
547 * Notes:
548 * 1. This routine is called either by the protocol stack or by the "net
549 * bottom half" (with interrupts enabled).
550 * 2. Setting tbusy flag will inhibit further transmit requests from the
551 * protocol stack and can be used for flow control with protocol layer. */
552 static int if_send (struct sk_buff *skb, struct net_device *dev)
554 x25_channel_t *chan = dev->priv;
555 cycx_t *card = chan->card;
557 if (dev->tbusy) {
558 ++chan->ifstats.rx_dropped;
559 return -EBUSY;
562 if (!chan->svc)
563 chan->protocol = skb->protocol;
565 if (card->wandev.state != WAN_CONNECTED)
566 ++chan->ifstats.tx_dropped;
567 else if (chan->svc && chan->protocol &&
568 chan->protocol != skb->protocol) {
569 printk(KERN_INFO
570 "%s: unsupported Ethertype 0x%04X on interface %s!\n",
571 card->devname, skb->protocol, dev->name);
572 ++chan->ifstats.tx_errors;
573 } else switch (chan->state) {
574 case WAN_DISCONNECTED:
575 if (chan_connect(dev)) {
576 dev->tbusy = 1;
577 return -EBUSY;
579 /* fall thru */
580 case WAN_CONNECTED:
581 reset_timer(dev);
582 dev->trans_start = jiffies;
583 dev->tbusy = 1;
585 if (chan_send(dev, skb)) {
586 return -EBUSY;
588 break;
589 default:
590 ++chan->ifstats.tx_dropped;
591 ++card->wandev.stats.tx_dropped;
594 dev_kfree_skb(skb);
595 return 0;
598 /* Get Ethernet-style interface statistics.
599 * Return a pointer to struct net_device_stats */
600 static struct net_device_stats *if_stats (struct net_device *dev)
602 x25_channel_t *chan = dev->priv;
604 return chan ? &chan->ifstats : NULL;
607 /* Interrupt Handlers */
608 /* X.25 Interrupt Service Routine. */
609 static void cyx_isr (cycx_t *card)
611 TX25Cmd cmd;
612 u16 z = 0;
614 card->in_isr = 1;
615 card->buff_int_mode_unbusy = 0;
616 cycx_peek(&card->hw, X25_RXMBOX_OFFS, &cmd, sizeof(cmd));
618 switch (cmd.command) {
619 case X25_DATA_INDICATION:
620 rx_intr(card, &cmd);
621 break;
622 case X25_ACK_FROM_VC:
623 tx_intr(card, &cmd);
624 break;
625 case X25_LOG:
626 log_intr(card, &cmd);
627 break;
628 case X25_STATISTIC:
629 stat_intr(card, &cmd);
630 break;
631 case X25_CONNECT_CONFIRM:
632 connect_confirm_intr(card, &cmd);
633 break;
634 case X25_CONNECT_INDICATION:
635 connect_intr(card, &cmd);
636 break;
637 case X25_DISCONNECT_INDICATION:
638 disconnect_intr(card, &cmd);
639 break;
640 case X25_DISCONNECT_CONFIRM:
641 disconnect_confirm_intr(card, &cmd);
642 break;
643 case X25_LINE_ON:
644 cyclomx_set_state(card, WAN_CONNECTED);
645 break;
646 case X25_LINE_OFF:
647 cyclomx_set_state(card, WAN_DISCONNECTED);
648 break;
649 default:
650 spur_intr(card, &cmd); /* unwanted interrupt */
653 cycx_poke(&card->hw, 0, &z, sizeof(z));
654 cycx_poke(&card->hw, X25_RXMBOX_OFFS, &z, sizeof(z));
655 card->in_isr = 0;
657 if (card->buff_int_mode_unbusy)
658 mark_bh(NET_BH);
661 /* Transmit interrupt handler.
662 * o Release socket buffer
663 * o Clear 'tbusy' flag */
664 static void tx_intr (cycx_t *card, TX25Cmd *cmd)
666 struct net_device *dev;
667 wan_device_t *wandev = &card->wandev;
668 u8 lcn;
670 cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
672 /* unbusy device and then dev_tint(); */
673 if ((dev = get_dev_by_lcn (wandev, lcn)) != NULL) {
674 card->buff_int_mode_unbusy = 1;
675 dev->tbusy = 0;
676 } else
677 printk(KERN_ERR "%s:ackvc for inexistent lcn %d\n",
678 card->devname, lcn);
681 /* Receive interrupt handler.
682 * This routine handles fragmented IP packets using M-bit according to the
683 * RFC1356.
684 * o map ligical channel number to network interface.
685 * o allocate socket buffer or append received packet to the existing one.
686 * o if M-bit is reset (i.e. it's the last packet in a sequence) then
687 * decapsulate packet and pass socket buffer to the protocol stack.
689 * Notes:
690 * 1. When allocating a socket buffer, if M-bit is set then more data is
691 * comming and we have to allocate buffer for the maximum IP packet size
692 * expected on this channel.
693 * 2. If something goes wrong and X.25 packet has to be dropped (e.g. no
694 * socket buffers available) the whole packet sequence must be discarded. */
695 static void rx_intr (cycx_t *card, TX25Cmd *cmd)
697 wan_device_t *wandev = &card->wandev;
698 struct net_device *dev;
699 x25_channel_t *chan;
700 struct sk_buff *skb;
701 u8 bitm, lcn;
702 int pktlen = cmd->len - 5;
704 cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
705 cycx_peek(&card->hw, cmd->buf + 4, &bitm, sizeof(bitm));
706 bitm &= 0x10;
708 if ((dev = get_dev_by_lcn(wandev, lcn)) == NULL) {
709 /* Invalid channel, discard packet */
710 printk(KERN_INFO "%s: receiving on orphaned LCN %d!\n",
711 card->devname, lcn);
712 return;
715 chan = dev->priv;
716 reset_timer(dev);
718 if (chan->drop_sequence) {
719 if (!bitm)
720 chan->drop_sequence = 0;
721 else
722 return;
725 if ((skb = chan->rx_skb) == NULL) {
726 /* Allocate new socket buffer */
727 int bufsize = bitm ? dev->mtu : pktlen;
729 if ((skb = dev_alloc_skb(bufsize +
730 dev->hard_header_len)) == NULL) {
731 printk(KERN_INFO "%s: no socket buffers available!\n",
732 card->devname);
733 chan->drop_sequence = 1;
734 ++chan->ifstats.rx_dropped;
735 return;
738 skb->dev = dev;
739 skb->protocol = htons(chan->protocol);
740 chan->rx_skb = skb;
743 if (skb_tailroom(skb) < pktlen) {
744 /* No room for the packet. Call off the whole thing! */
745 dev_kfree_skb(skb);
746 chan->rx_skb = NULL;
748 if (bitm)
749 chan->drop_sequence = 1;
751 printk(KERN_INFO "%s: unexpectedly long packet sequence "
752 "on interface %s!\n", card->devname, dev->name);
753 ++chan->ifstats.rx_length_errors;
754 return;
757 /* Append packet to the socket buffer */
758 cycx_peek(&card->hw, cmd->buf + 5, skb_put(skb, pktlen), pktlen);
760 if (bitm)
761 return; /* more data is coming */
763 dev->last_rx = jiffies; /* timestamp */
764 chan->rx_skb = NULL; /* dequeue packet */
766 skb->protocol = htons(ETH_P_IP);
767 skb->dev = dev;
768 skb->mac.raw = skb->data;
769 netif_rx(skb);
770 ++chan->ifstats.rx_packets;
771 chan->ifstats.rx_bytes += skb->len;
774 /* Connect interrupt handler. */
775 static void connect_intr (cycx_t *card, TX25Cmd *cmd)
777 wan_device_t *wandev = &card->wandev;
778 struct net_device *dev = NULL;
779 x25_channel_t *chan;
780 u8 d[32],
781 loc[24],
782 rem[24];
783 u8 lcn, sizeloc, sizerem;
785 cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
786 cycx_peek(&card->hw, cmd->buf + 5, &sizeloc, sizeof(sizeloc));
787 cycx_peek(&card->hw, cmd->buf + 6, d, cmd->len - 6);
789 sizerem = sizeloc >> 4;
790 sizeloc &= 0x0F;
792 loc[0] = rem[0] = '\0';
794 if (sizeloc)
795 nibble_to_byte(d, loc, sizeloc, 0);
797 if (sizerem)
798 nibble_to_byte(d + (sizeloc >> 1), rem, sizerem, sizeloc & 1);
800 dprintk(KERN_INFO "connect_intr:lcn=%d, local=%s, remote=%s\n",
801 lcn, loc, rem);
802 if ((dev = get_dev_by_dte_addr(wandev, rem)) == NULL) {
803 /* Invalid channel, discard packet */
804 printk(KERN_INFO "%s: connect not expected: remote %s!\n",
805 card->devname, rem);
806 return;
809 chan = dev->priv;
810 chan->lcn = lcn;
811 x25_connect_response(card, chan);
812 set_chan_state(dev, WAN_CONNECTED);
815 /* Connect confirm interrupt handler. */
816 static void connect_confirm_intr (cycx_t *card, TX25Cmd *cmd)
818 wan_device_t *wandev = &card->wandev;
819 struct net_device *dev;
820 x25_channel_t *chan;
821 u8 lcn, key;
823 cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
824 cycx_peek(&card->hw, cmd->buf + 1, &key, sizeof(key));
825 dprintk(KERN_INFO "%s: connect_confirm_intr:lcn=%d, key=%d\n",
826 card->devname, lcn, key);
827 if ((dev = get_dev_by_lcn(wandev, -key)) == NULL) {
828 /* Invalid channel, discard packet */
829 clear_bit(--key, (void*)&card->u.x.connection_keys);
830 printk(KERN_INFO "%s: connect confirm not expected: lcn %d, "
831 "key=%d!\n", card->devname, lcn, key);
832 return;
835 clear_bit(--key, (void*)&card->u.x.connection_keys);
836 chan = dev->priv;
837 chan->lcn = lcn;
838 set_chan_state(dev, WAN_CONNECTED);
841 /* Disonnect confirm interrupt handler. */
842 static void disconnect_confirm_intr (cycx_t *card, TX25Cmd *cmd)
844 wan_device_t *wandev = &card->wandev;
845 struct net_device *dev;
846 u8 lcn;
848 cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
849 dprintk(KERN_INFO "%s: disconnect_confirm_intr:lcn=%d\n",
850 card->devname, lcn);
851 if ((dev = get_dev_by_lcn(wandev, lcn)) == NULL) {
852 /* Invalid channel, discard packet */
853 printk(KERN_INFO "%s:disconnect confirm not expected!:lcn %d\n",
854 card->devname, lcn);
855 return;
858 set_chan_state(dev, WAN_DISCONNECTED);
861 /* disconnect interrupt handler. */
862 static void disconnect_intr (cycx_t *card, TX25Cmd *cmd)
864 wan_device_t *wandev = &card->wandev;
865 struct net_device *dev;
866 u8 lcn;
868 cycx_peek(&card->hw, cmd->buf, &lcn, sizeof(lcn));
869 dprintk(KERN_INFO "disconnect_intr:lcn=%d\n", lcn);
871 if ((dev = get_dev_by_lcn(wandev, lcn)) != NULL) {
872 x25_channel_t *chan = dev->priv;
874 x25_disconnect_response(card, chan->link, lcn);
875 set_chan_state(dev, WAN_DISCONNECTED);
876 } else
877 x25_disconnect_response(card, 0, lcn);
880 /* LOG interrupt handler. */
881 static void log_intr (cycx_t *card, TX25Cmd *cmd)
883 #if CYCLOMX_X25_DEBUG
884 char bf[20];
885 u16 size, toread, link, msg_code;
886 u8 code, routine;
888 cycx_peek(&card->hw, cmd->buf, &msg_code, sizeof(msg_code));
889 cycx_peek(&card->hw, cmd->buf + 2, &link, sizeof(link));
890 cycx_peek(&card->hw, cmd->buf + 4, &size, sizeof(size));
891 /* at most 20 bytes are available... thanx to Daniela :) */
892 toread = size < 20 ? size : 20;
893 cycx_peek(&card->hw, cmd->buf + 10, &bf, toread);
894 cycx_peek(&card->hw, cmd->buf + 10 + toread, &code, 1);
895 cycx_peek(&card->hw, cmd->buf + 10 + toread + 1, &routine, 1);
897 printk(KERN_INFO "cyx_isr: X25_LOG (0x4500) indic.:\n");
898 printk(KERN_INFO "cmd->buf=0x%X\n", cmd->buf);
899 printk(KERN_INFO "Log message code=0x%X\n", msg_code);
900 printk(KERN_INFO "Link=%d\n", link);
901 printk(KERN_INFO "log code=0x%X\n", code);
902 printk(KERN_INFO "log routine=0x%X\n", routine);
903 printk(KERN_INFO "Message size=%d\n", size);
904 hex_dump("Message", bf, toread);
905 #endif
908 /* STATISTIC interrupt handler. */
909 static void stat_intr (cycx_t *card, TX25Cmd *cmd)
911 cycx_peek(&card->hw, cmd->buf, &card->u.x.stats,
912 sizeof(card->u.x.stats));
913 hex_dump("stat_intr", (unsigned char*)&card->u.x.stats,
914 sizeof(card->u.x.stats));
915 x25_dump_stats(&card->u.x.stats);
916 wake_up_interruptible(&card->wait_stats);
919 /* Spurious interrupt handler.
920 * o print a warning
921 * If number of spurious interrupts exceeded some limit, then ??? */
922 static void spur_intr (cycx_t *card, TX25Cmd *cmd)
924 printk(KERN_INFO "%s: spurious interrupt (0x%X)!\n",
925 card->devname, cmd->command);
927 #ifdef CYCLOMX_X25_DEBUG
928 static void hex_dump(char *msg, unsigned char *p, int len)
930 unsigned char hex[1024],
931 * phex = hex;
933 if (len >= (sizeof(hex) / 2))
934 len = (sizeof(hex) / 2) - 1;
936 while (len--) {
937 sprintf(phex, "%02x", *p++);
938 phex += 2;
941 printk(KERN_INFO "%s: %s\n", msg, hex);
943 #endif
944 /* CYCLOM X Firmware-Specific Functions */
945 /* Exec x25 command. */
946 static int x25_exec (cycx_t *card, int command, int link,
947 void *d1, int len1, void *d2, int len2)
949 TX25Cmd c;
950 unsigned long flags;
951 u32 addr = 0x1200 + 0x2E0 * link + 0x1E2;
952 u8 retry = MAX_CMD_RETRY;
953 int err = 0;
955 c.command = command;
956 c.link = link;
957 c.len = len1 + len2;
959 spin_lock_irqsave(&card->u.x.lock, flags);
961 /* write command */
962 cycx_poke(&card->hw, X25_MBOX_OFFS, &c, sizeof(c) - sizeof(c.buf));
964 /* write x25 data */
965 if (d1) {
966 cycx_poke(&card->hw, addr, d1, len1);
968 if (d2) {
969 if (len2 > 254) {
970 u32 addr1 = 0xA00 + 0x400 * link;
972 cycx_poke(&card->hw, addr + len1, d2, 249);
973 cycx_poke(&card->hw, addr1, ((u8*) d2) + 249,
974 len2 - 249);
975 } else
976 cycx_poke(&card->hw, addr + len1, d2, len2);
980 /* generate interruption, executing command */
981 cycx_intr(&card->hw);
983 /* wait till card->mbox == 0 */
984 do {
985 err = cycx_exec(card->mbox);
986 } while (retry-- && err);
988 spin_unlock_irqrestore(&card->u.x.lock, flags);
990 return err;
993 /* Configure adapter. */
994 static int x25_configure (cycx_t *card, TX25Config *conf)
996 struct {
997 u16 nlinks;
998 TX25Config conf[2];
999 } x25_cmd_conf;
1001 memset (&x25_cmd_conf, 0, sizeof(x25_cmd_conf));
1002 x25_cmd_conf.nlinks = 2;
1003 x25_cmd_conf.conf[0] = *conf;
1004 /* FIXME: we need to find a way in the wanrouter framework
1005 to configure the second link, for now lets use it
1006 with the same config from the first link, fixing
1007 the interface type to RS232, the speed in 38400 and
1008 the clock to external */
1009 x25_cmd_conf.conf[1] = *conf;
1010 x25_cmd_conf.conf[1].link = 1;
1011 x25_cmd_conf.conf[1].speed = 5; /* 38400 */
1012 x25_cmd_conf.conf[1].clock = 8;
1013 x25_cmd_conf.conf[1].flags = 0; /* default = RS232 */
1015 x25_dump_config(&x25_cmd_conf.conf[0]);
1016 x25_dump_config(&x25_cmd_conf.conf[1]);
1018 return x25_exec(card, X25_CONFIG, 0,
1019 &x25_cmd_conf, sizeof(x25_cmd_conf), NULL, 0);
1022 /* Get protocol statistics. */
1023 static int x25_get_stats (cycx_t *card)
1025 /* the firmware expects 20 in the size field!!!
1026 thanx to Daniela */
1027 int err = x25_exec(card, X25_STATISTIC, 0, NULL, 20, NULL, 0);
1029 if (err)
1030 return err;
1032 interruptible_sleep_on(&card->wait_stats);
1034 if (signal_pending(current))
1035 return -EINTR;
1037 card->wandev.stats.rx_packets = card->u.x.stats.n2_rx_frames;
1038 card->wandev.stats.rx_over_errors = card->u.x.stats.rx_over_errors;
1039 card->wandev.stats.rx_crc_errors = card->u.x.stats.rx_crc_errors;
1040 card->wandev.stats.rx_length_errors = 0; /* not available from fw */
1041 card->wandev.stats.rx_frame_errors = 0; /* not available from fw */
1042 card->wandev.stats.rx_missed_errors = card->u.x.stats.rx_aborts;
1043 card->wandev.stats.rx_dropped = 0; /* not available from fw */
1044 card->wandev.stats.rx_errors = 0; /* not available from fw */
1045 card->wandev.stats.tx_packets = card->u.x.stats.n2_tx_frames;
1046 card->wandev.stats.tx_aborted_errors = card->u.x.stats.tx_aborts;
1047 card->wandev.stats.tx_dropped = 0; /* not available from fw */
1048 card->wandev.stats.collisions = 0; /* not available from fw */
1049 card->wandev.stats.tx_errors = 0; /* not available from fw */
1051 x25_dump_devs(&card->wandev);
1052 return 0;
1055 /* return the number of nibbles */
1056 static int byte_to_nibble(u8 *s, u8 *d, char *nibble)
1058 int i = 0;
1060 if (*nibble && *s) {
1061 d[i] |= *s++ - '0';
1062 *nibble = 0;
1063 ++i;
1066 while (*s) {
1067 d[i] = (*s - '0') << 4;
1068 if (*(s + 1))
1069 d[i] |= *(s + 1) - '0';
1070 else {
1071 *nibble = 1;
1072 break;
1074 ++i;
1075 s += 2;
1078 return i;
1081 static void nibble_to_byte(u8 *s, u8 *d, u8 len, u8 nibble)
1083 if (nibble) {
1084 *d++ = '0' + (*s++ & 0x0F);
1085 --len;
1088 while (len) {
1089 *d++ = '0' + (*s >> 4);
1091 if (--len) {
1092 *d++ = '0' + (*s & 0x0F);
1093 --len;
1094 } else break;
1096 ++s;
1099 *d = '\0';
1102 /* Place X.25 call. */
1103 static int x25_place_call (cycx_t *card, x25_channel_t *chan)
1105 int err = 0,
1106 len;
1107 char d[64],
1108 nibble = 0,
1109 mylen = chan->local_addr ? strlen(chan->local_addr) : 0,
1110 remotelen = strlen(chan->addr);
1111 u8 key;
1113 if (card->u.x.connection_keys == ~0UL) {
1114 printk(KERN_INFO "%s: too many simultaneous connection "
1115 "requests!\n", card->devname);
1116 return -EAGAIN;
1119 key = ffz(card->u.x.connection_keys);
1120 set_bit(key, (void*)&card->u.x.connection_keys);
1121 ++key;
1122 dprintk(KERN_INFO "%s:x25_place_call:key=%d\n", card->devname, key);
1123 memset(d, 0, sizeof(d));
1124 d[1] = key; /* user key */
1125 d[2] = 0x10;
1126 d[4] = 0x0B;
1128 len = byte_to_nibble(chan->addr, d + 6, &nibble);
1130 if (chan->local_addr)
1131 len += byte_to_nibble(chan->local_addr, d + 6 + len, &nibble);
1133 if (nibble)
1134 ++len;
1136 d[5] = mylen << 4 | remotelen;
1137 d[6 + len + 1] = 0xCC; /* TCP/IP over X.25, thanx to Daniela :) */
1139 if ((err = x25_exec(card, X25_CONNECT_REQUEST, chan->link,
1140 &d, 7 + len + 1, NULL, 0)) != 0)
1141 clear_bit(--key, (void*)&card->u.x.connection_keys);
1142 else {
1143 chan->lcn = -key;
1144 chan->protocol = ETH_P_IP;
1147 return err;
1150 /* Place X.25 CONNECT RESPONSE. */
1151 static int x25_connect_response (cycx_t *card, x25_channel_t *chan)
1153 u8 d[8];
1155 memset(d, 0, sizeof(d));
1156 d[0] = d[3] = chan->lcn;
1157 d[2] = 0x10;
1158 d[4] = 0x0F;
1159 d[7] = 0xCC; /* TCP/IP over X.25, thanx Daniela */
1161 return x25_exec(card, X25_CONNECT_RESPONSE, chan->link, &d, 8, NULL, 0);
1164 /* Place X.25 DISCONNECT RESPONSE. */
1165 static int x25_disconnect_response (cycx_t *card, u8 link, u8 lcn)
1167 char d[5];
1169 memset(d, 0, sizeof(d));
1170 d[0] = d[3] = lcn;
1171 d[2] = 0x10;
1172 d[4] = 0x17;
1173 return x25_exec(card, X25_DISCONNECT_RESPONSE, link, &d, 5, NULL, 0);
1176 /* Clear X.25 call. */
1177 static int x25_clear_call (cycx_t *card, u8 link, u8 lcn, u8 cause, u8 diagn)
1179 u8 d[7];
1181 memset(d, 0, sizeof(d));
1182 d[0] = d[3] = lcn;
1183 d[2] = 0x10;
1184 d[4] = 0x13;
1185 d[5] = cause;
1186 d[6] = diagn;
1188 return x25_exec(card, X25_DISCONNECT_REQUEST, link, d, 7, NULL, 0);
1191 /* Send X.25 data packet. */
1192 static int x25_send (cycx_t *card, u8 link, u8 lcn, u8 bitm, int len, void *buf)
1194 u8 d[] = "?\xFF\x10??";
1196 d[0] = d[3] = lcn;
1197 d[4] = bitm;
1199 return x25_exec(card, X25_DATA_REQUEST, link, &d, 5, buf, len);
1202 /* Miscellaneous */
1203 /* Find network device by its channel number. */
1204 static struct net_device *get_dev_by_lcn (wan_device_t *wandev, s16 lcn)
1206 struct net_device *dev = wandev->dev;
1208 for (; dev; dev = dev->slave)
1209 if (((x25_channel_t*)dev->priv)->lcn == lcn)
1210 break;
1211 return dev;
1214 /* Find network device by its remote dte address. */
1215 static struct net_device *get_dev_by_dte_addr (wan_device_t *wandev, char *dte)
1217 struct net_device *dev = wandev->dev;
1219 for (; dev; dev = dev->slave)
1220 if (!strcmp (((x25_channel_t*)dev->priv)->addr, dte))
1221 break;
1222 return dev;
1225 /* Initiate connection on the logical channel.
1226 * o for PVC we just get channel configuration
1227 * o for SVCs place an X.25 call
1229 * Return: 0 connected
1230 * >0 connection in progress
1231 * <0 failure */
1232 static int chan_connect (struct net_device *dev)
1234 x25_channel_t *chan = dev->priv;
1235 cycx_t *card = chan->card;
1237 if (chan->svc) {
1238 if (!chan->addr[0])
1239 return -EINVAL; /* no destination address */
1240 dprintk(KERN_INFO "%s: placing X.25 call to %s...\n",
1241 card->devname, chan->addr);
1242 if (x25_place_call(card, chan))
1243 return -EIO;
1244 set_chan_state(dev, WAN_CONNECTING);
1245 return 1;
1246 } else
1247 set_chan_state(dev, WAN_CONNECTED);
1249 return 0;
1252 /* Disconnect logical channel.
1253 * o if SVC then clear X.25 call */
1254 static void chan_disc (struct net_device *dev)
1256 x25_channel_t *chan = dev->priv;
1258 if (chan->svc) {
1259 x25_clear_call(chan->card, chan->link, chan->lcn, 0, 0);
1260 set_chan_state(dev, WAN_DISCONNECTING);
1261 } else
1262 set_chan_state(dev, WAN_DISCONNECTED);
1265 /* Called by kernel timer */
1266 static void chan_timer (unsigned long d)
1268 struct net_device *dev = (struct net_device*) d;
1269 x25_channel_t *chan = dev->priv;
1271 switch (chan->state) {
1272 case WAN_CONNECTED:
1273 chan_disc(dev);
1274 break;
1275 default:
1276 printk (KERN_ERR "%s: chan_timer for svc (%s) not "
1277 "connected!\n",
1278 chan->card->devname, dev->name);
1282 /* Set logical channel state. */
1283 static void set_chan_state (struct net_device *dev, u8 state)
1285 x25_channel_t *chan = dev->priv;
1286 cycx_t *card = chan->card;
1287 u32 flags = 0;
1289 spin_lock_irqsave(&card->lock, flags);
1291 if (chan->state != state) {
1292 if (chan->svc && chan->state == WAN_CONNECTED)
1293 del_timer(&chan->timer);
1295 switch (state) {
1296 case WAN_CONNECTED:
1297 printk (KERN_INFO "%s: interface %s "
1298 "connected!\n",
1299 card->devname, dev->name);
1300 *(u16*)dev->dev_addr = htons(chan->lcn);
1301 dev->tbusy = 0;
1302 reset_timer(dev);
1303 break;
1305 case WAN_CONNECTING:
1306 printk (KERN_INFO "%s: interface %s "
1307 "connecting...\n",
1308 card->devname, dev->name);
1309 break;
1311 case WAN_DISCONNECTING:
1312 printk (KERN_INFO "%s: interface %s "
1313 "disconnecting...\n",
1314 card->devname, dev->name);
1315 break;
1317 case WAN_DISCONNECTED:
1318 printk (KERN_INFO "%s: interface %s "
1319 "disconnected!\n",
1320 card->devname, dev->name);
1321 if (chan->svc) {
1322 *(unsigned short*)dev->dev_addr = 0;
1323 chan->lcn = 0;
1325 dev->tbusy = 0;
1326 break;
1329 chan->state = state;
1332 spin_unlock_irqrestore(&card->lock, flags);
1335 /* Send packet on a logical channel.
1336 * When this function is called, tx_skb field of the channel data space
1337 * points to the transmit socket buffer. When transmission is complete,
1338 * release socket buffer and reset 'tbusy' flag.
1340 * Return: 0 - transmission complete
1341 * 1 - busy
1343 * Notes:
1344 * 1. If packet length is greater than MTU for this channel, we'll fragment
1345 * the packet into 'complete sequence' using M-bit.
1346 * 2. When transmission is complete, an event notification should be issued
1347 * to the router. */
1348 static int chan_send (struct net_device *dev, struct sk_buff *skb)
1350 x25_channel_t *chan = dev->priv;
1351 cycx_t *card = chan->card;
1352 int bitm = 0; /* final packet */
1353 unsigned len = skb->len;
1355 if (skb->len > card->wandev.mtu) {
1356 len = card->wandev.mtu;
1357 bitm = 0x10; /* set M-bit (more data) */
1360 if (x25_send(card, chan->link, chan->lcn, bitm, len, skb->data))
1361 return 1;
1363 if (bitm) {
1364 skb_pull(skb, len);
1365 return 1;
1368 ++chan->ifstats.tx_packets;
1369 chan->ifstats.tx_bytes += len;
1370 return 0;
1373 /* Convert line speed in bps to a number used by cyclom 2x code. */
1374 static u8 bps_to_speed_code (u32 bps)
1376 u8 number = 0; /* defaults to the lowest (1200) speed ;> */
1378 if (bps >= 512000) number = 8;
1379 else if (bps >= 256000) number = 7;
1380 else if (bps >= 64000) number = 6;
1381 else if (bps >= 38400) number = 5;
1382 else if (bps >= 19200) number = 4;
1383 else if (bps >= 9600) number = 3;
1384 else if (bps >= 4800) number = 2;
1385 else if (bps >= 2400) number = 1;
1387 return number;
1390 /* log base 2 */
1391 static u8 log2 (u32 n)
1393 u8 log = 0;
1395 if (!n)
1396 return 0;
1398 while (n > 1) {
1399 n >>= 1;
1400 ++log;
1403 return log;
1406 /* Convert decimal string to unsigned integer.
1407 * If len != 0 then only 'len' characters of the string are converted. */
1408 static unsigned dec_to_uint (u8 *str, int len)
1410 unsigned val = 0;
1412 if (!len)
1413 len = strlen(str);
1415 for (; len && is_digit(*str); ++str, --len)
1416 val = (val * 10) + (*str - (unsigned)'0');
1418 return val;
1421 static void reset_timer(struct net_device *dev)
1423 x25_channel_t *chan = dev->priv;
1425 if (!chan->svc)
1426 return;
1428 del_timer(&chan->timer);
1429 chan->timer.expires = jiffies + chan->idle_tmout * HZ;
1430 add_timer(&chan->timer);
1432 #ifdef CYCLOMX_X25_DEBUG
1433 static void x25_dump_config(TX25Config *conf)
1435 printk (KERN_INFO "x25 configuration\n");
1436 printk (KERN_INFO "-----------------\n");
1437 printk (KERN_INFO "link number=%d\n", conf->link);
1438 printk (KERN_INFO "line speed=%d\n", conf->speed);
1439 printk (KERN_INFO "clock=%sternal\n", conf->clock == 8 ? "Ex" : "In");
1440 printk (KERN_INFO "# level 2 retransm.=%d\n", conf->n2);
1441 printk (KERN_INFO "level 2 window=%d\n", conf->n2win);
1442 printk (KERN_INFO "level 3 window=%d\n", conf->n3win);
1443 printk (KERN_INFO "# logical channels=%d\n", conf->nvc);
1444 printk (KERN_INFO "level 3 pkt len=%d\n", conf->pktlen);
1445 printk (KERN_INFO "my address=%d\n", conf->locaddr);
1446 printk (KERN_INFO "remote address=%d\n", conf->remaddr);
1447 printk (KERN_INFO "t1=%d seconds\n", conf->t1);
1448 printk (KERN_INFO "t2=%d seconds\n", conf->t2);
1449 printk (KERN_INFO "t21=%d seconds\n", conf->t21);
1450 printk (KERN_INFO "# PVCs=%d\n", conf->npvc);
1451 printk (KERN_INFO "t23=%d seconds\n", conf->t23);
1452 printk (KERN_INFO "flags=0x%x\n", conf->flags);
1455 static void x25_dump_stats(TX25Stats *stats)
1457 printk (KERN_INFO "x25 statistics\n");
1458 printk (KERN_INFO "--------------\n");
1459 printk (KERN_INFO "rx_crc_errors=%d\n", stats->rx_crc_errors);
1460 printk (KERN_INFO "rx_over_errors=%d\n", stats->rx_over_errors);
1461 printk (KERN_INFO "n2_tx_frames=%d\n", stats->n2_tx_frames);
1462 printk (KERN_INFO "n2_rx_frames=%d\n", stats->n2_rx_frames);
1463 printk (KERN_INFO "tx_timeouts=%d\n", stats->tx_timeouts);
1464 printk (KERN_INFO "rx_timeouts=%d\n", stats->rx_timeouts);
1465 printk (KERN_INFO "n3_tx_packets=%d\n", stats->n3_tx_packets);
1466 printk (KERN_INFO "n3_rx_packets=%d\n", stats->n3_rx_packets);
1467 printk (KERN_INFO "tx_aborts=%d\n", stats->tx_aborts);
1468 printk (KERN_INFO "rx_aborts=%d\n", stats->rx_aborts);
1471 static void x25_dump_devs(wan_device_t *wandev)
1473 struct net_device *dev = wandev->dev;
1475 printk (KERN_INFO "x25 dev states\n");
1476 printk (KERN_INFO "name: addr: tbusy:\n");
1477 printk (KERN_INFO "----------------------------\n");
1479 for (; dev; dev = dev->slave) {
1480 x25_channel_t *chan = dev->priv;
1482 printk (KERN_INFO "%-5.5s %-15.15s %ld\n",
1483 chan->name, chan->addr, dev->tbusy);
1487 #endif /* CYCLOMX_X25_DEBUG */
1488 /* End */