1 /*****************************************************************************
2 * sdla_chdlc.c WANPIPE(tm) Multiprotocol WAN Link Driver. Cisco HDLC module.
4 * Authors: Nenad Corbic <ncorbic@sangoma.com>
7 * Copyright: (c) 1995-1999 Sangoma Technologies Inc.
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 * Sep 30, 1999 Nenad Corbic Fixed dynamic IP and route setup.
15 * Sep 23, 1999 Nenad Corbic Added SMP support, fixed tracing
16 * Sep 13, 1999 Nenad Corbic Split up Port 0 and 1 into separate devices.
17 * Jun 02, 1999 Gideon Hack Added support for the S514 adapter.
18 * Oct 30, 1998 Jaspreet Singh Added Support for CHDLC API (HDLC STREAMING).
19 * Oct 28, 1998 Jaspreet Singh Added Support for Dual Port CHDLC.
20 * Aug 07, 1998 David Fong Initial version.
21 *****************************************************************************/
23 #include <linux/module.h>
24 #include <linux/kernel.h> /* printk(), and other useful stuff */
25 #include <linux/stddef.h> /* offsetof(), etc. */
26 #include <linux/errno.h> /* return codes */
27 #include <linux/string.h> /* inline memset(), etc. */
28 #include <linux/slab.h> /* kmalloc(), kfree() */
29 #include <linux/wanrouter.h> /* WAN router definitions */
30 #include <linux/wanpipe.h> /* WANPIPE common user API definitions */
31 #include <linux/if_arp.h> /* ARPHRD_* defines */
33 #include <linux/inetdevice.h>
34 #include <asm/uaccess.h>
36 #include <linux/in.h> /* sockaddr_in */
37 #include <linux/inet.h>
39 #include <asm/byteorder.h> /* htons(), etc. */
40 #include <linux/sdlapci.h>
43 #include <linux/sdla_chdlc.h> /* CHDLC firmware API definitions */
45 /****** Defines & Macros ****************************************************/
47 /* reasons for enabling the timer interrupt on the adapter */
48 #define TMR_INT_ENABLED_UDP 0x0001
49 #define TMR_INT_ENABLED_UPDATE 0x0002
51 #define CHDLC_DFLT_DATA_LEN 1500 /* default MTU */
52 #define CHDLC_HDR_LEN 1
54 #define IFF_POINTTOPOINT 0x10
58 #define CHDLC_API 0x01
60 #define PORT(x) (x == 0 ? "PRIMARY" : "SECONDARY" )
63 /******Data Structures*****************************************************/
65 /* This structure is placed in the private data area of the device structure.
66 * The card structure used to occupy the private area but now the following
67 * structure will incorporate the card structure along with CHDLC specific data
70 typedef struct chdlc_private_area
72 struct net_device
*slave
;
74 int TracingEnabled
; /* For enabling Tracing */
75 unsigned long curr_trace_addr
; /* Used for Tracing */
76 unsigned long start_trace_addr
;
77 unsigned long end_trace_addr
;
78 unsigned long base_addr_trace_buffer
;
79 unsigned long end_addr_trace_buffer
;
80 unsigned short number_trace_elements
;
81 unsigned available_buffer_space
;
82 unsigned long router_start_time
;
83 unsigned char route_status
;
84 unsigned char route_removed
;
85 unsigned long tick_counter
; /* For 5s timeout counter */
86 unsigned long router_up_time
;
87 u32 IP_address
; /* IP addressing */
89 unsigned char mc
; /* Mulitcast support on/off */
90 unsigned short udp_pkt_lgth
; /* udp packet processing */
92 char udp_pkt_data
[MAX_LGTH_UDP_MGNT_PKT
];
93 unsigned short timer_int_enabled
;
94 char update_comms_stats
; /* updating comms stats */
95 //FIXME: add driver stats as per frame relay!
97 } chdlc_private_area_t
;
99 /* Route Status options */
100 #define NO_ROUTE 0x00
101 #define ADD_ROUTE 0x01
102 #define ROUTE_ADDED 0x02
103 #define REMOVE_ROUTE 0x03
106 /****** Function Prototypes *************************************************/
107 /* WAN link driver entry points. These are called by the WAN router module. */
108 static int wpft1_exec (struct sdla
*card
, void *u_cmd
, void *u_data
);
109 static int chdlc_read_version (sdla_t
* card
, char* str
);
110 static int chdlc_error (sdla_t
*card
, int err
, CHDLC_MAILBOX_STRUCT
*mb
);
112 /****** Public Functions ****************************************************/
114 /*============================================================================
115 * Cisco HDLC protocol initialization routine.
117 * This routine is called by the main WANPIPE module during setup. At this
118 * point adapter is completely initialized and firmware is running.
119 * o read firmware version (to make sure it's alive)
120 * o configure adapter
121 * o initialize protocol-specific fields of the adapter data space.
126 int wpft1_init (sdla_t
* card
, wandev_conf_t
* conf
)
128 unsigned char port_num
;
135 volatile CHDLC_MAILBOX_STRUCT
* mb
;
136 CHDLC_MAILBOX_STRUCT
* mb1
;
137 unsigned long timeout
;
139 /* Verify configuration ID */
140 if (conf
->config_id
!= WANCONFIG_CHDLC
) {
141 printk(KERN_INFO
"%s: invalid configuration ID %u!\n",
142 card
->devname
, conf
->config_id
);
146 /* Use primary port */
147 card
->u
.c
.comm_port
= 0;
150 /* Initialize protocol-specific fields */
151 if(card
->hw
.type
!= SDLA_S514
){
152 card
->mbox
= (void *) card
->hw
.dpmbase
;
154 card
->mbox
= (void *) card
->hw
.dpmbase
+ PRI_BASE_ADDR_MB_STRUCT
;
157 mb
= mb1
= card
->mbox
;
159 if (!card
->configured
){
161 /* The board will place an 'I' in the return code to indicate that it is
162 ready to accept commands. We expect this to be completed in less
166 while (mb
->return_code
!= 'I') /* Wait 1s for board to initialize */
167 if ((jiffies
- timeout
) > 1*HZ
) break;
169 if (mb
->return_code
!= 'I') {
171 "%s: Initialization not completed by adapter\n",
173 printk(KERN_INFO
"Please contact Sangoma representative.\n");
178 /* Read firmware version. Note that when adapter initializes, it
179 * clears the mailbox, so it may appear that the first command was
180 * executed successfully when in fact it was merely erased. To work
181 * around this, we execute the first command twice.
184 if (chdlc_read_version(card
, u
.str
))
187 printk(KERN_INFO
"%s: Running FT1 Configuration firmware v%s\n",
188 card
->devname
, u
.str
);
192 card
->exec
= &wpft1_exec
;
193 card
->wandev
.update
= NULL
;
194 card
->wandev
.new_if
= NULL
;
195 card
->wandev
.del_if
= NULL
;
196 card
->wandev
.state
= WAN_DUALPORT
;
197 card
->wandev
.udp_port
= conf
->udp_port
;
199 card
->wandev
.new_if_cnt
= 0;
201 /* This is for the ports link state */
202 card
->u
.c
.state
= WAN_DISCONNECTED
;
204 /* reset the number of times the 'update()' proc has been called */
205 card
->u
.c
.update_call_count
= 0;
207 card
->wandev
.ttl
= 0x7F;
208 card
->wandev
.interface
= 0;
210 card
->wandev
.clocking
= 0;
212 port_num
= card
->u
.c
.comm_port
;
216 card
->wandev
.bps
= 0;
218 card
->wandev
.mtu
= MIN_LGTH_CHDLC_DATA_CFG
;
220 /* Set up the interrupt status area */
221 /* Read the CHDLC Configuration and obtain:
222 * Ptr to shared memory infor struct
223 * Use this pointer to calculate the value of card->u.c.flags !
225 mb1
->buffer_length
= 0;
226 mb1
->command
= READ_CHDLC_CONFIGURATION
;
227 err
= sdla_exec(mb1
) ? mb1
->return_code
: CMD_TIMEOUT
;
228 if(err
!= COMMAND_OK
) {
229 chdlc_error(card
, err
, mb1
);
233 if(card
->hw
.type
== SDLA_S514
){
234 card
->u
.c
.flags
= (void *)(card
->hw
.dpmbase
+
235 (((CHDLC_CONFIGURATION_STRUCT
*)mb1
->data
)->
236 ptr_shared_mem_info_struct
));
238 card
->u
.c
.flags
= (void *)(card
->hw
.dpmbase
+
239 (((CHDLC_CONFIGURATION_STRUCT
*)mb1
->data
)->
240 ptr_shared_mem_info_struct
% SDLA_WINDOWSIZE
));
243 card
->wandev
.state
= WAN_FT1_READY
;
244 printk(KERN_INFO
"%s: FT1 Config Ready !\n",card
->devname
);
249 static int wpft1_exec(sdla_t
*card
, void *u_cmd
, void *u_data
)
251 CHDLC_MAILBOX_STRUCT
* mbox
= card
->mbox
;
254 if (copy_from_user((void*)&mbox
->command
, u_cmd
, sizeof(ft1_exec_cmd_t
))){
258 len
= mbox
->buffer_length
;
261 if( copy_from_user((void*)&mbox
->data
, u_data
, len
)){
266 /* execute command */
267 if (!sdla_exec(mbox
)){
272 if( copy_to_user(u_cmd
, (void*)&mbox
->command
, sizeof(ft1_exec_cmd_t
))){
276 len
= mbox
->buffer_length
;
278 if (len
&& u_data
&& copy_to_user(u_data
, (void*)&mbox
->data
, len
)){
286 /*============================================================================
287 * Read firmware code version.
288 * Put code version as ASCII string in str.
290 static int chdlc_read_version (sdla_t
* card
, char* str
)
292 CHDLC_MAILBOX_STRUCT
* mb
= card
->mbox
;
295 mb
->buffer_length
= 0;
296 mb
->command
= READ_CHDLC_CODE_VERSION
;
297 err
= sdla_exec(mb
) ? mb
->return_code
: CMD_TIMEOUT
;
299 if(err
!= COMMAND_OK
) {
300 chdlc_error(card
,err
,mb
);
302 else if (str
) { /* is not null */
303 len
= mb
->buffer_length
;
304 memcpy(str
, mb
->data
, len
);
310 /*============================================================================
311 * Firmware error handler.
312 * This routine is called whenever firmware command returns non-zero
315 * Return zero if previous command has to be cancelled.
317 static int chdlc_error (sdla_t
*card
, int err
, CHDLC_MAILBOX_STRUCT
*mb
)
319 unsigned cmd
= mb
->command
;
324 printk(KERN_ERR
"%s: command 0x%02X timed out!\n",
328 case S514_BOTH_PORTS_SAME_CLK_MODE
:
329 if(cmd
== SET_CHDLC_CONFIGURATION
) {
331 "%s: Configure both ports for the same clock source\n",
337 printk(KERN_INFO
"%s: command 0x%02X returned 0x%02X!\n",
338 card
->devname
, cmd
, err
);
344 MODULE_LICENSE("GPL");