Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/isdn/sc/command.c
15111 views
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 [email protected] 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
}
364
365