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 */
32 #include <linux/jiffies.h> /* time_after() macro */
34 #include <linux/inetdevice.h>
35 #include <asm/uaccess.h>
37 #include <linux/in.h> /* sockaddr_in */
38 #include <linux/inet.h>
40 #include <asm/byteorder.h> /* htons(), etc. */
41 #include <linux/sdlapci.h>
44 #include <linux/sdla_chdlc.h> /* CHDLC firmware API definitions */
46 /****** Defines & Macros ****************************************************/
48 /* reasons for enabling the timer interrupt on the adapter */
49 #define TMR_INT_ENABLED_UDP 0x0001
50 #define TMR_INT_ENABLED_UPDATE 0x0002
52 #define CHDLC_DFLT_DATA_LEN 1500 /* default MTU */
53 #define CHDLC_HDR_LEN 1
55 #define IFF_POINTTOPOINT 0x10
59 #define CHDLC_API 0x01
61 #define PORT(x) (x == 0 ? "PRIMARY" : "SECONDARY" )
64 /******Data Structures*****************************************************/
66 /* This structure is placed in the private data area of the device structure.
67 * The card structure used to occupy the private area but now the following
68 * structure will incorporate the card structure along with CHDLC specific data
71 typedef struct chdlc_private_area
73 struct net_device *slave;
75 int TracingEnabled; /* For enabling Tracing */
76 unsigned long curr_trace_addr; /* Used for Tracing */
77 unsigned long start_trace_addr;
78 unsigned long end_trace_addr;
79 unsigned long base_addr_trace_buffer;
80 unsigned long end_addr_trace_buffer;
81 unsigned short number_trace_elements;
82 unsigned available_buffer_space;
83 unsigned long router_start_time;
84 unsigned char route_status;
85 unsigned char route_removed;
86 unsigned long tick_counter; /* For 5s timeout counter */
87 unsigned long router_up_time;
88 u32 IP_address; /* IP addressing */
90 unsigned char mc; /* Mulitcast support on/off */
91 unsigned short udp_pkt_lgth; /* udp packet processing */
93 char udp_pkt_data[MAX_LGTH_UDP_MGNT_PKT];
94 unsigned short timer_int_enabled;
95 char update_comms_stats; /* updating comms stats */
96 //FIXME: add driver stats as per frame relay!
98 } chdlc_private_area_t;
100 /* Route Status options */
101 #define NO_ROUTE 0x00
102 #define ADD_ROUTE 0x01
103 #define ROUTE_ADDED 0x02
104 #define REMOVE_ROUTE 0x03
107 /****** Function Prototypes *************************************************/
108 /* WAN link driver entry points. These are called by the WAN router module. */
109 static int wpft1_exec (struct sdla *card, void *u_cmd, void *u_data);
110 static int chdlc_read_version (sdla_t* card, char* str);
111 static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb);
113 /****** Public Functions ****************************************************/
115 /*============================================================================
116 * Cisco HDLC protocol initialization routine.
118 * This routine is called by the main WANPIPE module during setup. At this
119 * point adapter is completely initialized and firmware is running.
120 * o read firmware version (to make sure it's alive)
121 * o configure adapter
122 * o initialize protocol-specific fields of the adapter data space.
127 int wpft1_init (sdla_t* card, wandev_conf_t* conf)
129 unsigned char port_num;
136 volatile CHDLC_MAILBOX_STRUCT* mb;
137 CHDLC_MAILBOX_STRUCT* mb1;
138 unsigned long timeout;
140 /* Verify configuration ID */
141 if (conf->config_id != WANCONFIG_CHDLC) {
142 printk(KERN_INFO "%s: invalid configuration ID %u!\n",
143 card->devname, conf->config_id);
147 /* Use primary port */
148 card->u.c.comm_port = 0;
151 /* Initialize protocol-specific fields */
152 if(card->hw.type != SDLA_S514){
153 card->mbox = (void *) card->hw.dpmbase;
155 card->mbox = (void *) card->hw.dpmbase + PRI_BASE_ADDR_MB_STRUCT;
158 mb = mb1 = card->mbox;
160 if (!card->configured){
162 /* The board will place an 'I' in the return code to indicate that it is
163 ready to accept commands. We expect this to be completed in less
167 while (mb->return_code != 'I') /* Wait 1s for board to initialize */
168 if (time_after(jiffies, timeout + 1*HZ)) break;
170 if (mb->return_code != 'I') {
172 "%s: Initialization not completed by adapter\n",
174 printk(KERN_INFO "Please contact Sangoma representative.\n");
179 /* Read firmware version. Note that when adapter initializes, it
180 * clears the mailbox, so it may appear that the first command was
181 * executed successfully when in fact it was merely erased. To work
182 * around this, we execute the first command twice.
185 if (chdlc_read_version(card, u.str))
188 printk(KERN_INFO "%s: Running FT1 Configuration firmware v%s\n",
189 card->devname, u.str);
193 card->exec = &wpft1_exec;
194 card->wandev.update = NULL;
195 card->wandev.new_if = NULL;
196 card->wandev.del_if = NULL;
197 card->wandev.state = WAN_DUALPORT;
198 card->wandev.udp_port = conf->udp_port;
200 card->wandev.new_if_cnt = 0;
202 /* This is for the ports link state */
203 card->u.c.state = WAN_DISCONNECTED;
205 /* reset the number of times the 'update()' proc has been called */
206 card->u.c.update_call_count = 0;
208 card->wandev.ttl = 0x7F;
209 card->wandev.interface = 0;
211 card->wandev.clocking = 0;
213 port_num = card->u.c.comm_port;
217 card->wandev.bps = 0;
219 card->wandev.mtu = MIN_LGTH_CHDLC_DATA_CFG;
221 /* Set up the interrupt status area */
222 /* Read the CHDLC Configuration and obtain:
223 * Ptr to shared memory infor struct
224 * Use this pointer to calculate the value of card->u.c.flags !
226 mb1->buffer_length = 0;
227 mb1->command = READ_CHDLC_CONFIGURATION;
228 err = sdla_exec(mb1) ? mb1->return_code : CMD_TIMEOUT;
229 if(err != COMMAND_OK) {
230 chdlc_error(card, err, mb1);
234 if(card->hw.type == SDLA_S514){
235 card->u.c.flags = (void *)(card->hw.dpmbase +
236 (((CHDLC_CONFIGURATION_STRUCT *)mb1->data)->
237 ptr_shared_mem_info_struct));
239 card->u.c.flags = (void *)(card->hw.dpmbase +
240 (((CHDLC_CONFIGURATION_STRUCT *)mb1->data)->
241 ptr_shared_mem_info_struct % SDLA_WINDOWSIZE));
244 card->wandev.state = WAN_FT1_READY;
245 printk(KERN_INFO "%s: FT1 Config Ready !\n",card->devname);
250 static int wpft1_exec(sdla_t *card, void *u_cmd, void *u_data)
252 CHDLC_MAILBOX_STRUCT* mbox = card->mbox;
255 if (copy_from_user((void*)&mbox->command, u_cmd, sizeof(ft1_exec_cmd_t))){
259 len = mbox->buffer_length;
262 if( copy_from_user((void*)&mbox->data, u_data, len)){
267 /* execute command */
268 if (!sdla_exec(mbox)){
273 if( copy_to_user(u_cmd, (void*)&mbox->command, sizeof(ft1_exec_cmd_t))){
277 len = mbox->buffer_length;
279 if (len && u_data && copy_to_user(u_data, (void*)&mbox->data, len)){
287 /*============================================================================
288 * Read firmware code version.
289 * Put code version as ASCII string in str.
291 static int chdlc_read_version (sdla_t* card, char* str)
293 CHDLC_MAILBOX_STRUCT* mb = card->mbox;
296 mb->buffer_length = 0;
297 mb->command = READ_CHDLC_CODE_VERSION;
298 err = sdla_exec(mb) ? mb->return_code : CMD_TIMEOUT;
300 if(err != COMMAND_OK) {
301 chdlc_error(card,err,mb);
303 else if (str) { /* is not null */
304 len = mb->buffer_length;
305 memcpy(str, mb->data, len);
311 /*============================================================================
312 * Firmware error handler.
313 * This routine is called whenever firmware command returns non-zero
316 * Return zero if previous command has to be cancelled.
318 static int chdlc_error (sdla_t *card, int err, CHDLC_MAILBOX_STRUCT *mb)
320 unsigned cmd = mb->command;
325 printk(KERN_ERR "%s: command 0x%02X timed out!\n",
329 case S514_BOTH_PORTS_SAME_CLK_MODE:
330 if(cmd == SET_CHDLC_CONFIGURATION) {
332 "%s: Configure both ports for the same clock source\n",
338 printk(KERN_INFO "%s: command 0x%02X returned 0x%02X!\n",
339 card->devname, cmd, err);
345 MODULE_LICENSE("GPL");