~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/isdn/sc/command.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* $Id: command.c,v 1.4.10.1 2001/09/23 22:24:59 kai Exp $
 
2
 *
 
3
 * Copyright (C) 1996  SpellCaster Telecommunications Inc.
 
4
 *
 
5
 * This software may be used and distributed according to the terms
 
6
 * of the GNU General Public License, incorporated herein by reference.
 
7
 *
 
8
 * For more information, please contact gpl-info@spellcast.com or write:
 
9
 *
 
10
 *     SpellCaster Telecommunications Inc.
 
11
 *     5621 Finch Avenue East, Unit #3
 
12
 *     Scarborough, Ontario  Canada
 
13
 *     M1B 2T9
 
14
 *     +1 (416) 297-8565
 
15
 *     +1 (416) 297-6433 Facsimile
 
16
 */
 
17
 
 
18
#include <linux/module.h>
 
19
#include "includes.h"           /* This must be first */
 
20
#include "hardware.h"
 
21
#include "message.h"
 
22
#include "card.h"
 
23
#include "scioc.h"
 
24
 
 
25
static int dial(int card, unsigned long channel, setup_parm setup);
 
26
static int hangup(int card, unsigned long channel);
 
27
static int answer(int card, unsigned long channel);
 
28
static int clreaz(int card, unsigned long channel);
 
29
static int seteaz(int card, unsigned long channel, char *);
 
30
static int setl2(int card, unsigned long arg);
 
31
static int setl3(int card, unsigned long arg);
 
32
static int acceptb(int card, unsigned long channel);
 
33
 
 
34
#ifdef DEBUG
 
35
/*
 
36
 * Translate command codes to strings
 
37
 */
 
38
static char *commands[] = { "ISDN_CMD_IOCTL",
 
39
                            "ISDN_CMD_DIAL",
 
40
                            "ISDN_CMD_ACCEPTB",
 
41
                            "ISDN_CMD_ACCEPTB",
 
42
                            "ISDN_CMD_HANGUP",
 
43
                            "ISDN_CMD_CLREAZ",
 
44
                            "ISDN_CMD_SETEAZ",
 
45
                            NULL,
 
46
                            NULL,
 
47
                            NULL,
 
48
                            "ISDN_CMD_SETL2",
 
49
                            NULL,
 
50
                            "ISDN_CMD_SETL3",
 
51
                            NULL,
 
52
                            NULL,
 
53
                            NULL,
 
54
                            NULL,
 
55
                            NULL, };
 
56
 
 
57
/*
 
58
 * Translates ISDN4Linux protocol codes to strings for debug messages
 
59
 */
 
60
static char *l3protos[] = { "ISDN_PROTO_L3_TRANS" };
 
61
static char *l2protos[] = { "ISDN_PROTO_L2_X75I",
 
62
                            "ISDN_PROTO_L2_X75UI",
 
63
                            "ISDN_PROTO_L2_X75BUI",
 
64
                            "ISDN_PROTO_L2_HDLC",
 
65
                            "ISDN_PROTO_L2_TRANS" };
 
66
#endif
 
67
 
 
68
int get_card_from_id(int driver)
 
69
{
 
70
        int i;
 
71
 
 
72
        for(i = 0 ; i < cinst ; i++) {
 
73
                if(sc_adapter[i]->driverId == driver)
 
74
                        return i;
 
75
        }
 
76
        return -ENODEV;
 
77
}
 
78
 
 
79
/* 
 
80
 * command
 
81
 */
 
82
 
 
83
int command(isdn_ctrl *cmd)
 
84
{
 
85
        int card;
 
86
 
 
87
        card = get_card_from_id(cmd->driver);
 
88
        if(!IS_VALID_CARD(card)) {
 
89
                pr_debug("Invalid param: %d is not a valid card id\n", card);
 
90
                return -ENODEV;
 
91
        }
 
92
 
 
93
        /*
 
94
         * Dispatch the command
 
95
         */
 
96
        switch(cmd->command) {
 
97
        case ISDN_CMD_IOCTL:
 
98
        {
 
99
                unsigned long   cmdptr;
 
100
                scs_ioctl       ioc;
 
101
 
 
102
                memcpy(&cmdptr, cmd->parm.num, sizeof(unsigned long));
 
103
                if (copy_from_user(&ioc, (scs_ioctl __user *)cmdptr,
 
104
                                   sizeof(scs_ioctl))) {
 
105
                        pr_debug("%s: Failed to verify user space 0x%lx\n",
 
106
                                sc_adapter[card]->devicename, cmdptr);
 
107
                        return -EFAULT;
 
108
                }
 
109
                return sc_ioctl(card, &ioc);
 
110
        }
 
111
        case ISDN_CMD_DIAL:
 
112
                return dial(card, cmd->arg, cmd->parm.setup);
 
113
        case ISDN_CMD_HANGUP:
 
114
                return hangup(card, cmd->arg);
 
115
        case ISDN_CMD_ACCEPTD:
 
116
                return answer(card, cmd->arg);
 
117
        case ISDN_CMD_ACCEPTB:
 
118
                return acceptb(card, cmd->arg);
 
119
        case ISDN_CMD_CLREAZ:
 
120
                return clreaz(card, cmd->arg);
 
121
        case ISDN_CMD_SETEAZ:
 
122
                return seteaz(card, cmd->arg, cmd->parm.num);
 
123
        case ISDN_CMD_SETL2:
 
124
                return setl2(card, cmd->arg);
 
125
        case ISDN_CMD_SETL3:
 
126
                return setl3(card, cmd->arg);
 
127
        default:
 
128
                return -EINVAL;
 
129
        }
 
130
        return 0;
 
131
}
 
132
 
 
133
/*
 
134
 * start the onboard firmware
 
135
 */
 
136
int startproc(int card) 
 
137
{
 
138
        int status;
 
139
 
 
140
        if(!IS_VALID_CARD(card)) {
 
141
                pr_debug("Invalid param: %d is not a valid card id\n", card);
 
142
                return -ENODEV;
 
143
        }
 
144
 
 
145
        /*
 
146
         * send start msg 
 
147
         */
 
148
        status = sendmessage(card, CMPID,cmReqType2,
 
149
                          cmReqClass0,
 
150
                          cmReqStartProc,
 
151
                          0,0,NULL);
 
152
        pr_debug("%s: Sent startProc\n", sc_adapter[card]->devicename);
 
153
        
 
154
        return status;
 
155
}
 
156
 
 
157
 
 
158
/*
 
159
 * Dials the number passed in 
 
160
 */
 
161
static int dial(int card, unsigned long channel, setup_parm setup)
 
162
{
 
163
        int status;
 
164
        char Phone[48];
 
165
  
 
166
        if(!IS_VALID_CARD(card)) {
 
167
                pr_debug("Invalid param: %d is not a valid card id\n", card);
 
168
                return -ENODEV;
 
169
        }
 
170
 
 
171
        /*extract ISDN number to dial from eaz/msn string*/ 
 
172
        strcpy(Phone,setup.phone); 
 
173
 
 
174
        /*send the connection message*/
 
175
        status = sendmessage(card, CEPID,ceReqTypePhy,
 
176
                                ceReqClass1,
 
177
                                ceReqPhyConnect,
 
178
                                (unsigned char) channel+1, 
 
179
                                strlen(Phone),
 
180
                                (unsigned int *) Phone);
 
181
 
 
182
        pr_debug("%s: Dialing %s on channel %lu\n",
 
183
                sc_adapter[card]->devicename, Phone, channel+1);
 
184
        
 
185
        return status;
 
186
}
 
187
 
 
188
/*
 
189
 * Answer an incoming call 
 
190
 */
 
191
static int answer(int card, unsigned long channel)
 
192
{
 
193
        if(!IS_VALID_CARD(card)) {
 
194
                pr_debug("Invalid param: %d is not a valid card id\n", card);
 
195
                return -ENODEV;
 
196
        }
 
197
 
 
198
        if(setup_buffers(card, channel+1)) {
 
199
                hangup(card, channel+1);
 
200
                return -ENOBUFS;
 
201
        }
 
202
 
 
203
        indicate_status(card, ISDN_STAT_BCONN,channel,NULL);
 
204
        pr_debug("%s: Answered incoming call on channel %lu\n",
 
205
                sc_adapter[card]->devicename, channel+1);
 
206
        return 0;
 
207
}
 
208
 
 
209
/*
 
210
 * Hangup up the call on specified channel
 
211
 */
 
212
static int hangup(int card, unsigned long channel)
 
213
{
 
214
        int status;
 
215
 
 
216
        if(!IS_VALID_CARD(card)) {
 
217
                pr_debug("Invalid param: %d is not a valid card id\n", card);
 
218
                return -ENODEV;
 
219
        }
 
220
 
 
221
        status = sendmessage(card, CEPID, ceReqTypePhy,
 
222
                                                 ceReqClass1,
 
223
                                                 ceReqPhyDisconnect,
 
224
                                                 (unsigned char) channel+1,
 
225
                                                 0,
 
226
                                                 NULL);
 
227
        pr_debug("%s: Sent HANGUP message to channel %lu\n",
 
228
                sc_adapter[card]->devicename, channel+1);
 
229
        return status;
 
230
}
 
231
 
 
232
/*
 
233
 * Set the layer 2 protocol (X.25, HDLC, Raw)
 
234
 */
 
235
static int setl2(int card, unsigned long arg)
 
236
{
 
237
        int status =0;
 
238
        int protocol,channel;
 
239
 
 
240
        if(!IS_VALID_CARD(card)) {
 
241
                pr_debug("Invalid param: %d is not a valid card id\n", card);
 
242
                return -ENODEV;
 
243
        }
 
244
        protocol = arg >> 8;
 
245
        channel = arg & 0xff;
 
246
        sc_adapter[card]->channel[channel].l2_proto = protocol;
 
247
 
 
248
        /*
 
249
         * check that the adapter is also set to the correct protocol
 
250
         */
 
251
        pr_debug("%s: Sending GetFrameFormat for channel %d\n",
 
252
                sc_adapter[card]->devicename, channel+1);
 
253
        status = sendmessage(card, CEPID, ceReqTypeCall,
 
254
                                ceReqClass0,
 
255
                                ceReqCallGetFrameFormat,
 
256
                                (unsigned char)channel+1,
 
257
                                1,
 
258
                                (unsigned int *) protocol);
 
259
        if(status) 
 
260
                return status;
 
261
        return 0;
 
262
}
 
263
 
 
264
/*
 
265
 * Set the layer 3 protocol
 
266
 */
 
267
static int setl3(int card, unsigned long channel)
 
268
{
 
269
        int protocol = channel >> 8;
 
270
 
 
271
        if(!IS_VALID_CARD(card)) {
 
272
                pr_debug("Invalid param: %d is not a valid card id\n", card);
 
273
                return -ENODEV;
 
274
        }
 
275
 
 
276
        sc_adapter[card]->channel[channel].l3_proto = protocol;
 
277
        return 0;
 
278
}
 
279
 
 
280
static int acceptb(int card, unsigned long channel)
 
281
{
 
282
        if(!IS_VALID_CARD(card)) {
 
283
                pr_debug("Invalid param: %d is not a valid card id\n", card);
 
284
                return -ENODEV;
 
285
        }
 
286
 
 
287
        if(setup_buffers(card, channel+1))
 
288
        {
 
289
                hangup(card, channel+1);
 
290
                return -ENOBUFS;
 
291
        }
 
292
 
 
293
        pr_debug("%s: B-Channel connection accepted on channel %lu\n",
 
294
                sc_adapter[card]->devicename, channel+1);
 
295
        indicate_status(card, ISDN_STAT_BCONN, channel, NULL);
 
296
        return 0;
 
297
}
 
298
 
 
299
static int clreaz(int card, unsigned long arg)
 
300
{
 
301
        if(!IS_VALID_CARD(card)) {
 
302
                pr_debug("Invalid param: %d is not a valid card id\n", card);
 
303
                return -ENODEV;
 
304
        }
 
305
 
 
306
        strcpy(sc_adapter[card]->channel[arg].eazlist, "");
 
307
        sc_adapter[card]->channel[arg].eazclear = 1;
 
308
        pr_debug("%s: EAZ List cleared for channel %lu\n",
 
309
                sc_adapter[card]->devicename, arg+1);
 
310
        return 0;
 
311
}
 
312
 
 
313
static int seteaz(int card, unsigned long arg, char *num)
 
314
{
 
315
        if(!IS_VALID_CARD(card)) {
 
316
                pr_debug("Invalid param: %d is not a valid card id\n", card);
 
317
                return -ENODEV;
 
318
        }
 
319
 
 
320
        strcpy(sc_adapter[card]->channel[arg].eazlist, num);
 
321
        sc_adapter[card]->channel[arg].eazclear = 0;
 
322
        pr_debug("%s: EAZ list for channel %lu set to: %s\n",
 
323
                sc_adapter[card]->devicename, arg+1,
 
324
                sc_adapter[card]->channel[arg].eazlist);
 
325
        return 0;
 
326
}
 
327
 
 
328
int reset(int card)
 
329
{
 
330
        unsigned long flags;
 
331
 
 
332
        if(!IS_VALID_CARD(card)) {
 
333
                pr_debug("Invalid param: %d is not a valid card id\n", card);
 
334
                return -ENODEV;
 
335
        }
 
336
 
 
337
        indicate_status(card, ISDN_STAT_STOP, 0, NULL);
 
338
 
 
339
        if(sc_adapter[card]->EngineUp) {
 
340
                del_timer(&sc_adapter[card]->stat_timer);
 
341
        }
 
342
 
 
343
        sc_adapter[card]->EngineUp = 0;
 
344
 
 
345
        spin_lock_irqsave(&sc_adapter[card]->lock, flags);
 
346
        init_timer(&sc_adapter[card]->reset_timer);
 
347
        sc_adapter[card]->reset_timer.function = sc_check_reset;
 
348
        sc_adapter[card]->reset_timer.data = card;
 
349
        sc_adapter[card]->reset_timer.expires = jiffies + CHECKRESET_TIME;
 
350
        add_timer(&sc_adapter[card]->reset_timer);
 
351
        spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
 
352
 
 
353
        outb(0x1,sc_adapter[card]->ioport[SFT_RESET]);
 
354
 
 
355
        pr_debug("%s: Adapter Reset\n", sc_adapter[card]->devicename);
 
356
        return 0;
 
357
}
 
358
 
 
359
void flushreadfifo (int card)
 
360
{
 
361
        while(inb(sc_adapter[card]->ioport[FIFO_STATUS]) & RF_HAS_DATA)
 
362
                inb(sc_adapter[card]->ioport[FIFO_READ]);
 
363
}