]> pilppa.org Git - linux-2.6-omap-h63xx.git/blob - drivers/isdn/sc/command.c
[PATCH] ARM SMP: TLB implementations only affect local CPU
[linux-2.6-omap-h63xx.git] / drivers / isdn / sc / command.c
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 extern int cinst;
35 extern board *sc_adapter[];
36
37 extern int sc_ioctl(int, scs_ioctl *);
38 extern int setup_buffers(int, int, unsigned int);
39 extern int indicate_status(int, int,ulong,char*);
40 extern void check_reset(unsigned long);
41 extern int send_and_receive(int, unsigned int, unsigned char, unsigned char,
42                 unsigned char, unsigned char, unsigned char, unsigned char *,
43                 RspMessage *, int);
44 extern int sendmessage(int, unsigned int, unsigned int, unsigned int,
45                 unsigned int, unsigned int, unsigned int, unsigned int *);
46 extern inline void pullphone(char *, char *);
47
48 #ifdef DEBUG
49 /*
50  * Translate command codes to strings
51  */
52 static char *commands[] = { "ISDN_CMD_IOCTL",
53                             "ISDN_CMD_DIAL",
54                             "ISDN_CMD_ACCEPTB",
55                             "ISDN_CMD_ACCEPTB",
56                             "ISDN_CMD_HANGUP",
57                             "ISDN_CMD_CLREAZ",
58                             "ISDN_CMD_SETEAZ",
59                             NULL,
60                             NULL,
61                             NULL,
62                             "ISDN_CMD_SETL2",
63                             NULL,
64                             "ISDN_CMD_SETL3",
65                             NULL,
66                             NULL,
67                             NULL,
68                             NULL,
69                             NULL, };
70
71 /*
72  * Translates ISDN4Linux protocol codes to strings for debug messages
73  */
74 static char *l3protos[] = { "ISDN_PROTO_L3_TRANS" };
75 static char *l2protos[] = { "ISDN_PROTO_L2_X75I",
76                             "ISDN_PROTO_L2_X75UI",
77                             "ISDN_PROTO_L2_X75BUI",
78                             "ISDN_PROTO_L2_HDLC",
79                             "ISDN_PROTO_L2_TRANS" };
80 #endif
81
82 int get_card_from_id(int driver)
83 {
84         int i;
85
86         for(i = 0 ; i < cinst ; i++) {
87                 if(sc_adapter[i]->driverId == driver)
88                         return i;
89         }
90         return -ENODEV;
91 }
92
93 /* 
94  * command
95  */
96
97 int command(isdn_ctrl *cmd)
98 {
99         int card;
100
101         card = get_card_from_id(cmd->driver);
102         if(!IS_VALID_CARD(card)) {
103                 pr_debug("Invalid param: %d is not a valid card id\n", card);
104                 return -ENODEV;
105         }
106
107         pr_debug("%s: Received %s command from Link Layer\n",
108                 sc_adapter[card]->devicename, commands[cmd->command]);
109
110         /*
111          * Dispatch the command
112          */
113         switch(cmd->command) {
114         case ISDN_CMD_IOCTL:
115         {
116                 unsigned long   cmdptr;
117                 scs_ioctl       ioc;
118
119                 memcpy(&cmdptr, cmd->parm.num, sizeof(unsigned long));
120                 if (copy_from_user(&ioc, (scs_ioctl __user *)cmdptr,
121                                    sizeof(scs_ioctl))) {
122                         pr_debug("%s: Failed to verify user space 0x%x\n",
123                                 sc_adapter[card]->devicename, cmdptr);
124                         return -EFAULT;
125                 }
126                 return sc_ioctl(card, &ioc);
127         }
128         case ISDN_CMD_DIAL:
129                 return dial(card, cmd->arg, cmd->parm.setup);
130         case ISDN_CMD_HANGUP:
131                 return hangup(card, cmd->arg);
132         case ISDN_CMD_ACCEPTD:
133                 return answer(card, cmd->arg);
134         case ISDN_CMD_ACCEPTB:
135                 return acceptb(card, cmd->arg);
136         case ISDN_CMD_CLREAZ:
137                 return clreaz(card, cmd->arg);
138         case ISDN_CMD_SETEAZ:
139                 return seteaz(card, cmd->arg, cmd->parm.num);
140         case ISDN_CMD_SETL2:
141                 return setl2(card, cmd->arg);
142         case ISDN_CMD_SETL3:
143                 return setl3(card, cmd->arg);
144         default:
145                 return -EINVAL;
146         }
147         return 0;
148 }
149
150 /*
151  * start the onboard firmware
152  */
153 int startproc(int card) 
154 {
155         int status;
156
157         if(!IS_VALID_CARD(card)) {
158                 pr_debug("Invalid param: %d is not a valid card id\n", card);
159                 return -ENODEV;
160         }
161
162         /*
163          * send start msg 
164          */
165         status = sendmessage(card, CMPID,cmReqType2,
166                           cmReqClass0,
167                           cmReqStartProc,
168                           0,0,NULL);
169         pr_debug("%s: Sent startProc\n", sc_adapter[card]->devicename);
170         
171         return status;
172 }
173
174
175 /*
176  * Dials the number passed in 
177  */
178 static int dial(int card, unsigned long channel, setup_parm setup)
179 {
180         int status;
181         char Phone[48];
182   
183         if(!IS_VALID_CARD(card)) {
184                 pr_debug("Invalid param: %d is not a valid card id\n", card);
185                 return -ENODEV;
186         }
187
188         /*extract ISDN number to dial from eaz/msn string*/ 
189         strcpy(Phone,setup.phone); 
190
191         /*send the connection message*/
192         status = sendmessage(card, CEPID,ceReqTypePhy,
193                                 ceReqClass1,
194                                 ceReqPhyConnect,
195                                 (unsigned char) channel+1, 
196                                 strlen(Phone),
197                                 (unsigned int *) Phone);
198
199         pr_debug("%s: Dialing %s on channel %d\n",
200                 sc_adapter[card]->devicename, Phone, channel+1);
201         
202         return status;
203 }
204
205 /*
206  * Answer an incoming call 
207  */
208 static int answer(int card, unsigned long channel)
209 {
210         if(!IS_VALID_CARD(card)) {
211                 pr_debug("Invalid param: %d is not a valid card id\n", card);
212                 return -ENODEV;
213         }
214
215         if(setup_buffers(card, channel+1, BUFFER_SIZE)) {
216                 hangup(card, channel+1);
217                 return -ENOBUFS;
218         }
219
220         indicate_status(card, ISDN_STAT_BCONN,channel,NULL);
221         pr_debug("%s: Answered incoming call on channel %s\n",
222                 sc_adapter[card]->devicename, channel+1);
223         return 0;
224 }
225
226 /*
227  * Hangup up the call on specified channel
228  */
229 static int hangup(int card, unsigned long channel)
230 {
231         int status;
232
233         if(!IS_VALID_CARD(card)) {
234                 pr_debug("Invalid param: %d is not a valid card id\n", card);
235                 return -ENODEV;
236         }
237
238         status = sendmessage(card, CEPID, ceReqTypePhy,
239                                                  ceReqClass1,
240                                                  ceReqPhyDisconnect,
241                                                  (unsigned char) channel+1,
242                                                  0,
243                                                  NULL);
244         pr_debug("%s: Sent HANGUP message to channel %d\n",
245                 sc_adapter[card]->devicename, channel+1);
246         return status;
247 }
248
249 /*
250  * Set the layer 2 protocol (X.25, HDLC, Raw)
251  */
252 static int setl2(int card, unsigned long arg)
253 {
254         int status =0;
255         int protocol,channel;
256
257         if(!IS_VALID_CARD(card)) {
258                 pr_debug("Invalid param: %d is not a valid card id\n", card);
259                 return -ENODEV;
260         }
261         protocol = arg >> 8;
262         channel = arg & 0xff;
263         sc_adapter[card]->channel[channel].l2_proto = protocol;
264         pr_debug("%s: Level 2 protocol for channel %d set to %s from %d\n",
265                 sc_adapter[card]->devicename, channel+1,
266                 l2protos[sc_adapter[card]->channel[channel].l2_proto],protocol);
267
268         /*
269          * check that the adapter is also set to the correct protocol
270          */
271         pr_debug("%s: Sending GetFrameFormat for channel %d\n",
272                 sc_adapter[card]->devicename, channel+1);
273         status = sendmessage(card, CEPID, ceReqTypeCall,
274                                 ceReqClass0,
275                                 ceReqCallGetFrameFormat,
276                                 (unsigned char)channel+1,
277                                 1,
278                                 (unsigned int *) protocol);
279         if(status) 
280                 return status;
281         return 0;
282 }
283
284 /*
285  * Set the layer 3 protocol
286  */
287 static int setl3(int card, unsigned long channel)
288 {
289         int protocol = channel >> 8;
290
291         if(!IS_VALID_CARD(card)) {
292                 pr_debug("Invalid param: %d is not a valid card id\n", card);
293                 return -ENODEV;
294         }
295
296         sc_adapter[card]->channel[channel].l3_proto = protocol;
297         pr_debug("%s: Level 3 protocol for channel %d set to %s\n",
298                 sc_adapter[card]->devicename, channel+1, l3protos[protocol]);
299         return 0;
300 }
301
302 static int acceptb(int card, unsigned long channel)
303 {
304         if(!IS_VALID_CARD(card)) {
305                 pr_debug("Invalid param: %d is not a valid card id\n", card);
306                 return -ENODEV;
307         }
308
309         if(setup_buffers(card, channel+1, BUFFER_SIZE))
310         {
311                 hangup(card, channel+1);
312                 return -ENOBUFS;
313         }
314
315         pr_debug("%s: B-Channel connection accepted on channel %d\n",
316                 sc_adapter[card]->devicename, channel+1);
317         indicate_status(card, ISDN_STAT_BCONN, channel, NULL);
318         return 0;
319 }
320
321 static int clreaz(int card, unsigned long arg)
322 {
323         if(!IS_VALID_CARD(card)) {
324                 pr_debug("Invalid param: %d is not a valid card id\n", card);
325                 return -ENODEV;
326         }
327
328         strcpy(sc_adapter[card]->channel[arg].eazlist, "");
329         sc_adapter[card]->channel[arg].eazclear = 1;
330         pr_debug("%s: EAZ List cleared for channel %d\n",
331                 sc_adapter[card]->devicename, arg+1);
332         return 0;
333 }
334
335 static int seteaz(int card, unsigned long arg, char *num)
336 {
337         if(!IS_VALID_CARD(card)) {
338                 pr_debug("Invalid param: %d is not a valid card id\n", card);
339                 return -ENODEV;
340         }
341
342         strcpy(sc_adapter[card]->channel[arg].eazlist, num);
343         sc_adapter[card]->channel[arg].eazclear = 0;
344         pr_debug("%s: EAZ list for channel %d set to: %s\n",
345                 sc_adapter[card]->devicename, arg+1,
346                 sc_adapter[card]->channel[arg].eazlist);
347         return 0;
348 }
349
350 int reset(int card)
351 {
352         unsigned long flags;
353
354         if(!IS_VALID_CARD(card)) {
355                 pr_debug("Invalid param: %d is not a valid card id\n", card);
356                 return -ENODEV;
357         }
358
359         indicate_status(card, ISDN_STAT_STOP, 0, NULL);
360
361         if(sc_adapter[card]->EngineUp) {
362                 del_timer(&sc_adapter[card]->stat_timer);
363         }
364
365         sc_adapter[card]->EngineUp = 0;
366
367         spin_lock_irqsave(&sc_adapter[card]->lock, flags);
368         init_timer(&sc_adapter[card]->reset_timer);
369         sc_adapter[card]->reset_timer.function = check_reset;
370         sc_adapter[card]->reset_timer.data = card;
371         sc_adapter[card]->reset_timer.expires = jiffies + CHECKRESET_TIME;
372         add_timer(&sc_adapter[card]->reset_timer);
373         spin_unlock_irqrestore(&sc_adapter[card]->lock, flags);
374
375         outb(0x1,sc_adapter[card]->ioport[SFT_RESET]);
376
377         pr_debug("%s: Adapter Reset\n", sc_adapter[card]->devicename);
378         return 0;
379 }
380
381 void flushreadfifo (int card)
382 {
383         while(inb(sc_adapter[card]->ioport[FIFO_STATUS]) & RF_HAS_DATA)
384                 inb(sc_adapter[card]->ioport[FIFO_READ]);
385 }