OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [trunk/] [linux-2.6/] [linux-2.6.24/] [net/] [rose/] [rose_link.c] - Blame information for rev 17

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 3 xianfeng
/*
2
 * This program is free software; you can redistribute it and/or modify
3
 * it under the terms of the GNU General Public License as published by
4
 * the Free Software Foundation; either version 2 of the License, or
5
 * (at your option) any later version.
6
 *
7
 * Copyright (C) Jonathan Naylor G4KLX (g4klx@g4klx.demon.co.uk)
8
 */
9
#include <linux/errno.h>
10
#include <linux/types.h>
11
#include <linux/socket.h>
12
#include <linux/in.h>
13
#include <linux/kernel.h>
14
#include <linux/jiffies.h>
15
#include <linux/timer.h>
16
#include <linux/string.h>
17
#include <linux/sockios.h>
18
#include <linux/net.h>
19
#include <net/ax25.h>
20
#include <linux/inet.h>
21
#include <linux/netdevice.h>
22
#include <linux/skbuff.h>
23
#include <net/sock.h>
24
#include <asm/system.h>
25
#include <linux/fcntl.h>
26
#include <linux/mm.h>
27
#include <linux/interrupt.h>
28
#include <linux/netfilter.h>
29
#include <net/rose.h>
30
 
31
static void rose_ftimer_expiry(unsigned long);
32
static void rose_t0timer_expiry(unsigned long);
33
 
34
static void rose_transmit_restart_confirmation(struct rose_neigh *neigh);
35
static void rose_transmit_restart_request(struct rose_neigh *neigh);
36
 
37
void rose_start_ftimer(struct rose_neigh *neigh)
38
{
39
        del_timer(&neigh->ftimer);
40
 
41
        neigh->ftimer.data     = (unsigned long)neigh;
42
        neigh->ftimer.function = &rose_ftimer_expiry;
43
        neigh->ftimer.expires  =
44
                jiffies + msecs_to_jiffies(sysctl_rose_link_fail_timeout);
45
 
46
        add_timer(&neigh->ftimer);
47
}
48
 
49
static void rose_start_t0timer(struct rose_neigh *neigh)
50
{
51
        del_timer(&neigh->t0timer);
52
 
53
        neigh->t0timer.data     = (unsigned long)neigh;
54
        neigh->t0timer.function = &rose_t0timer_expiry;
55
        neigh->t0timer.expires  =
56
                jiffies + msecs_to_jiffies(sysctl_rose_restart_request_timeout);
57
 
58
        add_timer(&neigh->t0timer);
59
}
60
 
61
void rose_stop_ftimer(struct rose_neigh *neigh)
62
{
63
        del_timer(&neigh->ftimer);
64
}
65
 
66
void rose_stop_t0timer(struct rose_neigh *neigh)
67
{
68
        del_timer(&neigh->t0timer);
69
}
70
 
71
int rose_ftimer_running(struct rose_neigh *neigh)
72
{
73
        return timer_pending(&neigh->ftimer);
74
}
75
 
76
static int rose_t0timer_running(struct rose_neigh *neigh)
77
{
78
        return timer_pending(&neigh->t0timer);
79
}
80
 
81
static void rose_ftimer_expiry(unsigned long param)
82
{
83
}
84
 
85
static void rose_t0timer_expiry(unsigned long param)
86
{
87
        struct rose_neigh *neigh = (struct rose_neigh *)param;
88
 
89
        rose_transmit_restart_request(neigh);
90
 
91
        neigh->dce_mode = 0;
92
 
93
        rose_start_t0timer(neigh);
94
}
95
 
96
/*
97
 *      Interface to ax25_send_frame. Changes my level 2 callsign depending
98
 *      on whether we have a global ROSE callsign or use the default port
99
 *      callsign.
100
 */
101
static int rose_send_frame(struct sk_buff *skb, struct rose_neigh *neigh)
102
{
103
        ax25_address *rose_call;
104
 
105
        if (ax25cmp(&rose_callsign, &null_ax25_address) == 0)
106
                rose_call = (ax25_address *)neigh->dev->dev_addr;
107
        else
108
                rose_call = &rose_callsign;
109
 
110
        neigh->ax25 = ax25_send_frame(skb, 260, rose_call, &neigh->callsign, neigh->digipeat, neigh->dev);
111
 
112
        return (neigh->ax25 != NULL);
113
}
114
 
115
/*
116
 *      Interface to ax25_link_up. Changes my level 2 callsign depending
117
 *      on whether we have a global ROSE callsign or use the default port
118
 *      callsign.
119
 */
120
static int rose_link_up(struct rose_neigh *neigh)
121
{
122
        ax25_address *rose_call;
123
 
124
        if (ax25cmp(&rose_callsign, &null_ax25_address) == 0)
125
                rose_call = (ax25_address *)neigh->dev->dev_addr;
126
        else
127
                rose_call = &rose_callsign;
128
 
129
        neigh->ax25 = ax25_find_cb(rose_call, &neigh->callsign, neigh->digipeat, neigh->dev);
130
 
131
        return (neigh->ax25 != NULL);
132
}
133
 
134
/*
135
 *      This handles all restart and diagnostic frames.
136
 */
137
void rose_link_rx_restart(struct sk_buff *skb, struct rose_neigh *neigh, unsigned short frametype)
138
{
139
        struct sk_buff *skbn;
140
 
141
        switch (frametype) {
142
        case ROSE_RESTART_REQUEST:
143
                rose_stop_t0timer(neigh);
144
                neigh->restarted = 1;
145
                neigh->dce_mode  = (skb->data[3] == ROSE_DTE_ORIGINATED);
146
                rose_transmit_restart_confirmation(neigh);
147
                break;
148
 
149
        case ROSE_RESTART_CONFIRMATION:
150
                rose_stop_t0timer(neigh);
151
                neigh->restarted = 1;
152
                break;
153
 
154
        case ROSE_DIAGNOSTIC:
155
                printk(KERN_WARNING "ROSE: received diagnostic #%d - %02X %02X %02X\n", skb->data[3], skb->data[4], skb->data[5], skb->data[6]);
156
                break;
157
 
158
        default:
159
                printk(KERN_WARNING "ROSE: received unknown %02X with LCI 000\n", frametype);
160
                break;
161
        }
162
 
163
        if (neigh->restarted) {
164
                while ((skbn = skb_dequeue(&neigh->queue)) != NULL)
165
                        if (!rose_send_frame(skbn, neigh))
166
                                kfree_skb(skbn);
167
        }
168
}
169
 
170
/*
171
 *      This routine is called when a Restart Request is needed
172
 */
173
static void rose_transmit_restart_request(struct rose_neigh *neigh)
174
{
175
        struct sk_buff *skb;
176
        unsigned char *dptr;
177
        int len;
178
 
179
        len = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN + 3;
180
 
181
        if ((skb = alloc_skb(len, GFP_ATOMIC)) == NULL)
182
                return;
183
 
184
        skb_reserve(skb, AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN);
185
 
186
        dptr = skb_put(skb, ROSE_MIN_LEN + 3);
187
 
188
        *dptr++ = AX25_P_ROSE;
189
        *dptr++ = ROSE_GFI;
190
        *dptr++ = 0x00;
191
        *dptr++ = ROSE_RESTART_REQUEST;
192
        *dptr++ = ROSE_DTE_ORIGINATED;
193
        *dptr++ = 0;
194
 
195
        if (!rose_send_frame(skb, neigh))
196
                kfree_skb(skb);
197
}
198
 
199
/*
200
 * This routine is called when a Restart Confirmation is needed
201
 */
202
static void rose_transmit_restart_confirmation(struct rose_neigh *neigh)
203
{
204
        struct sk_buff *skb;
205
        unsigned char *dptr;
206
        int len;
207
 
208
        len = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN + 1;
209
 
210
        if ((skb = alloc_skb(len, GFP_ATOMIC)) == NULL)
211
                return;
212
 
213
        skb_reserve(skb, AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN);
214
 
215
        dptr = skb_put(skb, ROSE_MIN_LEN + 1);
216
 
217
        *dptr++ = AX25_P_ROSE;
218
        *dptr++ = ROSE_GFI;
219
        *dptr++ = 0x00;
220
        *dptr++ = ROSE_RESTART_CONFIRMATION;
221
 
222
        if (!rose_send_frame(skb, neigh))
223
                kfree_skb(skb);
224
}
225
 
226
/*
227
 * This routine is called when a Clear Request is needed outside of the context
228
 * of a connected socket.
229
 */
230
void rose_transmit_clear_request(struct rose_neigh *neigh, unsigned int lci, unsigned char cause, unsigned char diagnostic)
231
{
232
        struct sk_buff *skb;
233
        unsigned char *dptr;
234
        int len;
235
 
236
        len = AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN + ROSE_MIN_LEN + 3;
237
 
238
        if ((skb = alloc_skb(len, GFP_ATOMIC)) == NULL)
239
                return;
240
 
241
        skb_reserve(skb, AX25_BPQ_HEADER_LEN + AX25_MAX_HEADER_LEN);
242
 
243
        dptr = skb_put(skb, ROSE_MIN_LEN + 3);
244
 
245
        *dptr++ = AX25_P_ROSE;
246
        *dptr++ = ((lci >> 8) & 0x0F) | ROSE_GFI;
247
        *dptr++ = ((lci >> 0) & 0xFF);
248
        *dptr++ = ROSE_CLEAR_REQUEST;
249
        *dptr++ = cause;
250
        *dptr++ = diagnostic;
251
 
252
        if (!rose_send_frame(skb, neigh))
253
                kfree_skb(skb);
254
}
255
 
256
void rose_transmit_link(struct sk_buff *skb, struct rose_neigh *neigh)
257
{
258
        unsigned char *dptr;
259
 
260
#if 0
261
        if (call_fw_firewall(PF_ROSE, skb->dev, skb->data, NULL, &skb) != FW_ACCEPT) {
262
                kfree_skb(skb);
263
                return;
264
        }
265
#endif
266
 
267
        if (neigh->loopback) {
268
                rose_loopback_queue(skb, neigh);
269
                return;
270
        }
271
 
272
        if (!rose_link_up(neigh))
273
                neigh->restarted = 0;
274
 
275
        dptr = skb_push(skb, 1);
276
        *dptr++ = AX25_P_ROSE;
277
 
278
        if (neigh->restarted) {
279
                if (!rose_send_frame(skb, neigh))
280
                        kfree_skb(skb);
281
        } else {
282
                skb_queue_tail(&neigh->queue, skb);
283
 
284
                if (!rose_t0timer_running(neigh)) {
285
                        rose_transmit_restart_request(neigh);
286
                        neigh->dce_mode = 0;
287
                        rose_start_t0timer(neigh);
288
                }
289
        }
290
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.