• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
get_card_from_id(int driver)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 
command(isdn_ctrl * cmd)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  */
startproc(int card)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  */
dial(int card,unsigned long channel,setup_parm setup)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  */
answer(int card,unsigned long channel)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  */
hangup(int card,unsigned long channel)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  */
setl2(int card,unsigned long arg)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  */
setl3(int card,unsigned long channel)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 
acceptb(int card,unsigned long channel)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 
clreaz(int card,unsigned long arg)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 
seteaz(int card,unsigned long arg,char * num)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 
reset(int card)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 
flushreadfifo(int card)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