Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ]
Version: [ 2.6.11.8 ] [ 2.6.25 ] [ 2.6.25.8 ] [ 2.6.31.13 ] Architecture: [ i386 ]
  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 }
364 
  This page was automatically generated by the LXR engine.