* better
[mascara-docs.git] / i386 / linux-2.3.21 / drivers / isdn / sc / command.c
blob28accdc0fbf77aba03e92700c3ef24848d38ba50
1 /*
2 * $Id: command.c,v 1.4 1997/03/30 16:51:34 calle Exp $
3 * Copyright (C) 1996 SpellCaster Telecommunications Inc.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 * For more information, please contact gpl-info@spellcast.com or write:
21 * SpellCaster Telecommunications Inc.
22 * 5621 Finch Avenue East, Unit #3
23 * Scarborough, Ontario Canada
24 * M1B 2T9
25 * +1 (416) 297-8565
26 * +1 (416) 297-6433 Facsimile
29 #define __NO_VERSION__
30 #include "includes.h" /* This must be first */
31 #include "hardware.h"
32 #include "message.h"
33 #include "card.h"
34 #include "scioc.h"
36 int dial(int card, unsigned long channel, setup_parm setup);
37 int hangup(int card, unsigned long channel);
38 int answer(int card, unsigned long channel);
39 int clreaz(int card, unsigned long channel);
40 int seteaz(int card, unsigned long channel, char *);
41 int geteaz(int card, unsigned long channel, char *);
42 int setsil(int card, unsigned long channel, char *);
43 int getsil(int card, unsigned long channel, char *);
44 int setl2(int card, unsigned long arg);
45 int getl2(int card, unsigned long arg);
46 int setl3(int card, unsigned long arg);
47 int getl3(int card, unsigned long arg);
48 int lock(void);
49 int unlock(void);
50 int acceptb(int card, unsigned long channel);
52 extern int cinst;
53 extern board *adapter[];
55 extern int sc_ioctl(int, scs_ioctl *);
56 extern int setup_buffers(int, int, unsigned int);
57 extern int indicate_status(int, int,ulong,char*);
58 extern void check_reset(unsigned long);
59 extern int send_and_receive(int, unsigned int, unsigned char, unsigned char,
60 unsigned char, unsigned char, unsigned char, unsigned char *,
61 RspMessage *, int);
62 extern int sendmessage(int, unsigned int, unsigned int, unsigned int,
63 unsigned int, unsigned int, unsigned int, unsigned int *);
64 extern inline void pullphone(char *, char *);
66 #ifdef DEBUG
68 * Translate command codes to strings
70 static char *commands[] = { "ISDN_CMD_IOCTL",
71 "ISDN_CMD_DIAL",
72 "ISDN_CMD_ACCEPTB",
73 "ISDN_CMD_ACCEPTB",
74 "ISDN_CMD_HANGUP",
75 "ISDN_CMD_CLREAZ",
76 "ISDN_CMD_SETEAZ",
77 "ISDN_CMD_GETEAZ",
78 "ISDN_CMD_SETSIL",
79 "ISDN_CMD_GETSIL",
80 "ISDN_CMD_SETL2",
81 "ISDN_CMD_GETL2",
82 "ISDN_CMD_SETL3",
83 "ISDN_CMD_GETL3",
84 "ISDN_CMD_LOCK",
85 "ISDN_CMD_UNLOCK",
86 "ISDN_CMD_SUSPEND",
87 "ISDN_CMD_RESUME" };
90 * Translates ISDN4Linux protocol codes to strings for debug messages
92 static char *l3protos[] = { "ISDN_PROTO_L3_TRANS" };
93 static char *l2protos[] = { "ISDN_PROTO_L2_X75I",
94 "ISDN_PROTO_L2_X75UI",
95 "ISDN_PROTO_L2_X75BUI",
96 "ISDN_PROTO_L2_HDLC",
97 "ISDN_PROTO_L2_TRANS" };
98 #endif
100 int get_card_from_id(int driver)
102 int i;
104 for(i = 0 ; i < cinst ; i++) {
105 if(adapter[i]->driverId == driver)
106 return i;
108 return -NODEV;
112 * command
115 int command(isdn_ctrl *cmd)
117 int card;
119 card = get_card_from_id(cmd->driver);
120 if(!IS_VALID_CARD(card)) {
121 pr_debug("Invalid param: %d is not a valid card id\n", card);
122 return -ENODEV;
125 pr_debug("%s: Received %s command from Link Layer\n",
126 adapter[card]->devicename, commands[cmd->command]);
129 * Dispatch the command
131 switch(cmd->command) {
132 case ISDN_CMD_IOCTL:
134 unsigned long cmdptr;
135 scs_ioctl ioc;
136 int err;
138 memcpy(&cmdptr, cmd->parm.num, sizeof(unsigned long));
139 if((err = copy_from_user(&ioc, (scs_ioctl *) cmdptr,
140 sizeof(scs_ioctl)))) {
141 pr_debug("%s: Failed to verify user space 0x%x\n",
142 adapter[card]->devicename, cmdptr);
143 return err;
145 return sc_ioctl(card, &ioc);
147 case ISDN_CMD_DIAL:
148 return dial(card, cmd->arg, cmd->parm.setup);
149 case ISDN_CMD_HANGUP:
150 return hangup(card, cmd->arg);
151 case ISDN_CMD_ACCEPTD:
152 return answer(card, cmd->arg);
153 case ISDN_CMD_ACCEPTB:
154 return acceptb(card, cmd->arg);
155 case ISDN_CMD_CLREAZ:
156 return clreaz(card, cmd->arg);
157 case ISDN_CMD_SETEAZ:
158 return seteaz(card, cmd->arg, cmd->parm.num);
159 case ISDN_CMD_GETEAZ:
160 return geteaz(card, cmd->arg, cmd->parm.num);
161 case ISDN_CMD_SETSIL:
162 return setsil(card, cmd->arg, cmd->parm.num);
163 case ISDN_CMD_GETSIL:
164 return getsil(card, cmd->arg, cmd->parm.num);
165 case ISDN_CMD_SETL2:
166 return setl2(card, cmd->arg);
167 case ISDN_CMD_GETL2:
168 return getl2(card, cmd->arg);
169 case ISDN_CMD_SETL3:
170 return setl3(card, cmd->arg);
171 case ISDN_CMD_GETL3:
172 return getl3(card, cmd->arg);
173 case ISDN_CMD_LOCK:
174 return lock();
175 case ISDN_CMD_UNLOCK:
176 return unlock();
177 default:
178 return -EINVAL;
180 return 0;
184 * Confirm our ability to communicate with the board. This test assumes no
185 * other message activity is present
187 int loopback(int card)
190 int status;
191 static char testmsg[] = "Test Message";
192 RspMessage rspmsg;
194 if(!IS_VALID_CARD(card)) {
195 pr_debug("Invalid param: %d is not a valid card id\n", card);
196 return -ENODEV;
199 pr_debug("%s: Sending loopback message\n", adapter[card]->devicename);
203 * Send the loopback message to confirm that memory transfer is
204 * operational
206 status = send_and_receive(card, CMPID, cmReqType1,
207 cmReqClass0,
208 cmReqMsgLpbk,
210 (unsigned char) strlen(testmsg),
211 (unsigned char *)testmsg,
212 &rspmsg, SAR_TIMEOUT);
215 if (!status) {
216 pr_debug("%s: Loopback message successfully sent\n",
217 adapter[card]->devicename);
218 if(strcmp(rspmsg.msg_data.byte_array, testmsg)) {
219 pr_debug("%s: Loopback return != sent\n",
220 adapter[card]->devicename);
221 return -EIO;
223 return 0;
225 else {
226 pr_debug("%s: Send loopback message failed\n",
227 adapter[card]->devicename);
228 return -EIO;
234 * start the onboard firmware
236 int startproc(int card)
238 int status;
240 if(!IS_VALID_CARD(card)) {
241 pr_debug("Invalid param: %d is not a valid card id\n", card);
242 return -ENODEV;
246 * send start msg
248 status = sendmessage(card, CMPID,cmReqType2,
249 cmReqClass0,
250 cmReqStartProc,
251 0,0,0);
252 pr_debug("%s: Sent startProc\n", adapter[card]->devicename);
254 return status;
258 int loadproc(int card, char *data)
260 return -1;
265 * Dials the number passed in
267 int dial(int card, unsigned long channel, setup_parm setup)
269 int status;
270 char Phone[48];
272 if(!IS_VALID_CARD(card)) {
273 pr_debug("Invalid param: %d is not a valid card id\n", card);
274 return -ENODEV;
277 /*extract ISDN number to dial from eaz/msn string*/
278 strcpy(Phone,setup.phone);
280 /*send the connection message*/
281 status = sendmessage(card, CEPID,ceReqTypePhy,
282 ceReqClass1,
283 ceReqPhyConnect,
284 (unsigned char) channel+1,
285 strlen(Phone),
286 (unsigned int *) Phone);
288 pr_debug("%s: Dialing %s on channel %d\n",
289 adapter[card]->devicename, Phone, channel+1);
291 return status;
295 * Answer an incoming call
297 int answer(int card, unsigned long channel)
299 if(!IS_VALID_CARD(card)) {
300 pr_debug("Invalid param: %d is not a valid card id\n", card);
301 return -ENODEV;
304 if(setup_buffers(card, channel+1, BUFFER_SIZE)) {
305 hangup(card, channel+1);
306 return -ENOBUFS;
309 indicate_status(card, ISDN_STAT_BCONN,channel,NULL);
310 pr_debug("%s: Answered incoming call on channel %s\n",
311 adapter[card]->devicename, channel+1);
312 return 0;
316 * Hangup up the call on specified channel
318 int hangup(int card, unsigned long channel)
320 int status;
322 if(!IS_VALID_CARD(card)) {
323 pr_debug("Invalid param: %d is not a valid card id\n", card);
324 return -ENODEV;
327 status = sendmessage(card, CEPID, ceReqTypePhy,
328 ceReqClass1,
329 ceReqPhyDisconnect,
330 (unsigned char) channel+1,
332 NULL);
333 pr_debug("%s: Sent HANGUP message to channel %d\n",
334 adapter[card]->devicename, channel+1);
335 return status;
339 * Set the layer 2 protocol (X.25, HDLC, Raw)
341 int setl2(int card, unsigned long arg)
343 int status =0;
344 int protocol,channel;
346 if(!IS_VALID_CARD(card)) {
347 pr_debug("Invalid param: %d is not a valid card id\n", card);
348 return -ENODEV;
350 protocol = arg >> 8;
351 channel = arg & 0xff;
352 adapter[card]->channel[channel].l2_proto = protocol;
353 pr_debug("%s: Level 2 protocol for channel %d set to %s from %d\n",
354 adapter[card]->devicename, channel+1,l2protos[adapter[card]->channel[channel].l2_proto],protocol);
357 * check that the adapter is also set to the correct protocol
359 pr_debug("%s: Sending GetFrameFormat for channel %d\n",
360 adapter[card]->devicename, channel+1);
361 status = sendmessage(card, CEPID, ceReqTypeCall,
362 ceReqClass0,
363 ceReqCallGetFrameFormat,
364 (unsigned char)channel+1,
366 (unsigned int *) protocol);
367 if(status)
368 return status;
369 return 0;
373 * Get the layer 2 protocol
375 int getl2(int card, unsigned long channel) {
377 if(!IS_VALID_CARD(card)) {
378 pr_debug("Invalid param: %d is not a valid card id\n", card);
379 return -ENODEV;
382 pr_debug("%s: Level 2 protocol for channel %d reported as %s\n",
383 adapter[card]->devicename, channel+1,
384 l2protos[adapter[card]->channel[channel].l2_proto]);
386 return adapter[card]->channel[channel].l2_proto;
390 * Set the layer 3 protocol
392 int setl3(int card, unsigned long channel)
394 int protocol = channel >> 8;
396 if(!IS_VALID_CARD(card)) {
397 pr_debug("Invalid param: %d is not a valid card id\n", card);
398 return -ENODEV;
401 adapter[card]->channel[channel].l3_proto = protocol;
402 pr_debug("%s: Level 3 protocol for channel %d set to %s\n",
403 adapter[card]->devicename, channel+1, l3protos[protocol]);
404 return 0;
408 * Get the layer 3 protocol
410 int getl3(int card, unsigned long arg)
412 if(!IS_VALID_CARD(card)) {
413 pr_debug("Invalid param: %d is not a valid card id\n", card);
414 return -ENODEV;
417 pr_debug("%s: Level 3 protocol for channel %d reported as %s\n",
418 adapter[card]->devicename, arg+1,
419 l3protos[adapter[card]->channel[arg].l3_proto]);
420 return adapter[card]->channel[arg].l3_proto;
424 int acceptb(int card, unsigned long channel)
426 if(!IS_VALID_CARD(card)) {
427 pr_debug("Invalid param: %d is not a valid card id\n", card);
428 return -ENODEV;
431 if(setup_buffers(card, channel+1, BUFFER_SIZE))
433 hangup(card, channel+1);
434 return -ENOBUFS;
437 pr_debug("%s: B-Channel connection accepted on channel %d\n",
438 adapter[card]->devicename, channel+1);
439 indicate_status(card, ISDN_STAT_BCONN, channel, NULL);
440 return 0;
443 int clreaz(int card, unsigned long arg)
445 if(!IS_VALID_CARD(card)) {
446 pr_debug("Invalid param: %d is not a valid card id\n", card);
447 return -ENODEV;
450 strcpy(adapter[card]->channel[arg].eazlist, "");
451 adapter[card]->channel[arg].eazclear = 1;
452 pr_debug("%s: EAZ List cleared for channel %d\n",
453 adapter[card]->devicename, arg+1);
454 return 0;
457 int seteaz(int card, unsigned long arg, char *num)
459 if(!IS_VALID_CARD(card)) {
460 pr_debug("Invalid param: %d is not a valid card id\n", card);
461 return -ENODEV;
464 strcpy(adapter[card]->channel[arg].eazlist, num);
465 adapter[card]->channel[arg].eazclear = 0;
466 pr_debug("%s: EAZ list for channel %d set to: %s\n",
467 adapter[card]->devicename, arg+1,
468 adapter[card]->channel[arg].eazlist);
469 return 0;
472 int geteaz(int card, unsigned long arg, char *num)
474 if(!IS_VALID_CARD(card)) {
475 pr_debug("Invalid param: %d is not a valid card id\n", card);
476 return -ENODEV;
479 strcpy(num, adapter[card]->channel[arg].eazlist);
480 pr_debug("%s: EAZ List for channel %d reported: %s\n",
481 adapter[card]->devicename, arg+1,
482 adapter[card]->channel[arg].eazlist);
483 return 0;
486 int setsil(int card, unsigned long arg, char *num)
488 if(!IS_VALID_CARD(card)) {
489 pr_debug("Invalid param: %d is not a valid card id\n", card);
490 return -ENODEV;
493 strcpy(adapter[card]->channel[arg].sillist, num);
494 pr_debug("%s: Service Indicators for channel %d set: %s\n",
495 adapter[card]->devicename, arg+1,
496 adapter[card]->channel[arg].sillist);
497 return 0;
500 int getsil(int card, unsigned long arg, char *num)
502 if(!IS_VALID_CARD(card)) {
503 pr_debug("Invalid param: %d is not a valid card id\n", card);
504 return -ENODEV;
507 strcpy(num, adapter[card]->channel[arg].sillist);
508 pr_debug("%s: SIL for channel %d reported: %s\n",
509 adapter[card]->devicename, arg+1,
510 adapter[card]->channel[arg].sillist);
511 return 0;
515 int lock()
517 MOD_INC_USE_COUNT;
518 return 0;
521 int unlock()
523 MOD_DEC_USE_COUNT;
524 return 0;
527 int reset(int card)
529 unsigned long flags;
531 if(!IS_VALID_CARD(card)) {
532 pr_debug("Invalid param: %d is not a valid card id\n", card);
533 return -ENODEV;
536 indicate_status(card, ISDN_STAT_STOP, 0, NULL);
538 if(adapter[card]->EngineUp) {
539 del_timer(&adapter[card]->stat_timer);
542 adapter[card]->EngineUp = 0;
544 save_flags(flags);
545 cli();
546 init_timer(&adapter[card]->reset_timer);
547 adapter[card]->reset_timer.function = check_reset;
548 adapter[card]->reset_timer.data = card;
549 adapter[card]->reset_timer.expires = jiffies + CHECKRESET_TIME;
550 add_timer(&adapter[card]->reset_timer);
551 restore_flags(flags);
553 outb(0x1,adapter[card]->ioport[SFT_RESET]);
555 pr_debug("%s: Adapter Reset\n", adapter[card]->devicename);
556 return 0;
559 void flushreadfifo (int card)
561 while(inb(adapter[card]->ioport[FIFO_STATUS]) & RF_HAS_DATA)
562 inb(adapter[card]->ioport[FIFO_READ]);