1 /* $Id: command.c,v 1.1.4.1 2001/11/20 14:19:37 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 #define __NO_VERSION__
19 #include <linux/module.h>
20 #include "includes.h"		/* This must be first */
21 #include "hardware.h"
22 #include "message.h"
23 #include "card.h"
24 #include "scioc.h"
25 
26 int dial(int card, unsigned long channel, setup_parm setup);
27 int hangup(int card, unsigned long channel);
28 int answer(int card, unsigned long channel);
29 int clreaz(int card, unsigned long channel);
30 int seteaz(int card, unsigned long channel, char *);
31 int geteaz(int card, unsigned long channel, char *);
32 int setsil(int card, unsigned long channel, char *);
33 int getsil(int card, unsigned long channel, char *);
34 int setl2(int card, unsigned long arg);
35 int getl2(int card, unsigned long arg);
36 int setl3(int card, unsigned long arg);
37 int getl3(int card, unsigned long arg);
38 int lock(void);
39 int unlock(void);
40 int acceptb(int card, unsigned long channel);
41 
42 extern int cinst;
43 extern board *adapter[];
44 
45 extern int sc_ioctl(int, scs_ioctl *);
46 extern int setup_buffers(int, int, unsigned int);
47 extern int indicate_status(int, int,ulong,char*);
48 extern void check_reset(unsigned long);
49 extern int send_and_receive(int, unsigned int, unsigned char, unsigned char,
50                 unsigned char, unsigned char, unsigned char, unsigned char *,
51                 RspMessage *, int);
52 extern int sendmessage(int, unsigned int, unsigned int, unsigned int,
53                 unsigned int, unsigned int, unsigned int, unsigned int *);
54 extern inline void pullphone(char *, char *);
55 
56 #ifdef DEBUG
57 /*
58  * Translate command codes to strings
59  */
60 static char *commands[] = { "ISDN_CMD_IOCTL",
61 			    "ISDN_CMD_DIAL",
62 			    "ISDN_CMD_ACCEPTB",
63 			    "ISDN_CMD_ACCEPTB",
64 			    "ISDN_CMD_HANGUP",
65 			    "ISDN_CMD_CLREAZ",
66 			    "ISDN_CMD_SETEAZ",
67 			    "ISDN_CMD_GETEAZ",
68 			    "ISDN_CMD_SETSIL",
69 			    "ISDN_CMD_GETSIL",
70 			    "ISDN_CMD_SETL2",
71 			    "ISDN_CMD_GETL2",
72 			    "ISDN_CMD_SETL3",
73 			    "ISDN_CMD_GETL3",
74 			    "ISDN_CMD_LOCK",
75 			    "ISDN_CMD_UNLOCK",
76 			    "ISDN_CMD_SUSPEND",
77 			    "ISDN_CMD_RESUME" };
78 
79 /*
80  * Translates ISDN4Linux protocol codes to strings for debug messages
81  */
82 static char *l3protos[] = { "ISDN_PROTO_L3_TRANS" };
83 static char *l2protos[] = { "ISDN_PROTO_L2_X75I",
84 			    "ISDN_PROTO_L2_X75UI",
85 			    "ISDN_PROTO_L2_X75BUI",
86 			    "ISDN_PROTO_L2_HDLC",
87 			    "ISDN_PROTO_L2_TRANS" };
88 #endif
89 
get_card_from_id(int driver)90 int get_card_from_id(int driver)
91 {
92 	int i;
93 
94 	for(i = 0 ; i < cinst ; i++) {
95 		if(adapter[i]->driverId == driver)
96 			return i;
97 	}
98 	return -ENODEV;
99 }
100 
101 /*
102  * command
103  */
104 
command(isdn_ctrl * cmd)105 int command(isdn_ctrl *cmd)
106 {
107 	int card;
108 
109 	card = get_card_from_id(cmd->driver);
110 	if(!IS_VALID_CARD(card)) {
111 		pr_debug("Invalid param: %d is not a valid card id\n", card);
112 		return -ENODEV;
113 	}
114 
115 	pr_debug("%s: Received %s command from Link Layer\n",
116 		adapter[card]->devicename, commands[cmd->command]);
117 
118 	/*
119 	 * Dispatch the command
120 	 */
121 	switch(cmd->command) {
122 	case ISDN_CMD_IOCTL:
123 	{
124 		unsigned long 	cmdptr;
125 		scs_ioctl	ioc;
126 		int		err;
127 
128 		memcpy(&cmdptr, cmd->parm.num, sizeof(unsigned long));
129 		if((err = copy_from_user(&ioc, (scs_ioctl *) cmdptr,
130 			sizeof(scs_ioctl)))) {
131 			pr_debug("%s: Failed to verify user space 0x%x\n",
132 				adapter[card]->devicename, cmdptr);
133 			return err;
134 		}
135 		return sc_ioctl(card, &ioc);
136 	}
137 	case ISDN_CMD_DIAL:
138 		return dial(card, cmd->arg, cmd->parm.setup);
139 	case ISDN_CMD_HANGUP:
140 		return hangup(card, cmd->arg);
141 	case ISDN_CMD_ACCEPTD:
142 		return answer(card, cmd->arg);
143 	case ISDN_CMD_ACCEPTB:
144 		return acceptb(card, cmd->arg);
145 	case ISDN_CMD_CLREAZ:
146 		return clreaz(card, cmd->arg);
147 	case ISDN_CMD_SETEAZ:
148 		return seteaz(card, cmd->arg, cmd->parm.num);
149 	case ISDN_CMD_GETEAZ:
150 		return geteaz(card, cmd->arg, cmd->parm.num);
151 	case ISDN_CMD_SETSIL:
152 		return setsil(card, cmd->arg, cmd->parm.num);
153 	case ISDN_CMD_GETSIL:
154 		return getsil(card, cmd->arg, cmd->parm.num);
155 	case ISDN_CMD_SETL2:
156 		return setl2(card, cmd->arg);
157 	case ISDN_CMD_GETL2:
158 		return getl2(card, cmd->arg);
159 	case ISDN_CMD_SETL3:
160 		return setl3(card, cmd->arg);
161 	case ISDN_CMD_GETL3:
162 		return getl3(card, cmd->arg);
163 	case ISDN_CMD_LOCK:
164 		return lock();
165 	case ISDN_CMD_UNLOCK:
166 		return unlock();
167 	default:
168 		return -EINVAL;
169 	}
170 	return 0;
171 }
172 
173 /*
174  * Confirm our ability to communicate with the board.  This test assumes no
175  * other message activity is present
176  */
loopback(int card)177 int loopback(int card)
178 {
179 
180 	int status;
181 	static char testmsg[] = "Test Message";
182 	RspMessage rspmsg;
183 
184 	if(!IS_VALID_CARD(card)) {
185 		pr_debug("Invalid param: %d is not a valid card id\n", card);
186 		return -ENODEV;
187 	}
188 
189 	pr_debug("%s: Sending loopback message\n", adapter[card]->devicename);
190 
191 
192 	/*
193 	 * Send the loopback message to confirm that memory transfer is
194 	 * operational
195 	 */
196 	status = send_and_receive(card, CMPID, cmReqType1,
197 				  cmReqClass0,
198 				  cmReqMsgLpbk,
199 				  0,
200 				  (unsigned char) strlen(testmsg),
201 				  (unsigned char *)testmsg,
202 				  &rspmsg, SAR_TIMEOUT);
203 
204 
205 	if (!status) {
206 		pr_debug("%s: Loopback message successfully sent\n",
207 			adapter[card]->devicename);
208 		if(strcmp(rspmsg.msg_data.byte_array, testmsg)) {
209 			pr_debug("%s: Loopback return != sent\n",
210 				adapter[card]->devicename);
211 			return -EIO;
212 		}
213 		return 0;
214 	}
215 	else {
216 		pr_debug("%s: Send loopback message failed\n",
217 			adapter[card]->devicename);
218 		return -EIO;
219 	}
220 
221 }
222 
223 /*
224  * start the onboard firmware
225  */
startproc(int card)226 int startproc(int card)
227 {
228 	int status;
229 
230 	if(!IS_VALID_CARD(card)) {
231 		pr_debug("Invalid param: %d is not a valid card id\n", card);
232 		return -ENODEV;
233 	}
234 
235 	/*
236 	 * send start msg
237 	 */
238        	status = sendmessage(card, CMPID,cmReqType2,
239 			  cmReqClass0,
240 			  cmReqStartProc,
241 			  0,0,0);
242 	pr_debug("%s: Sent startProc\n", adapter[card]->devicename);
243 
244 	return status;
245 }
246 
247 
loadproc(int card,char * data)248 int loadproc(int card, char *data)
249 {
250 	return -1;
251 }
252 
253 
254 /*
255  * Dials the number passed in
256  */
dial(int card,unsigned long channel,setup_parm setup)257 int dial(int card, unsigned long channel, setup_parm setup)
258 {
259 	int status;
260 	char Phone[48];
261 
262 	if(!IS_VALID_CARD(card)) {
263 		pr_debug("Invalid param: %d is not a valid card id\n", card);
264 		return -ENODEV;
265 	}
266 
267 	/*extract ISDN number to dial from eaz/msn string*/
268 	strcpy(Phone,setup.phone);
269 
270 	/*send the connection message*/
271 	status = sendmessage(card, CEPID,ceReqTypePhy,
272 				ceReqClass1,
273 				ceReqPhyConnect,
274 				(unsigned char) channel+1,
275 				strlen(Phone),
276 				(unsigned int *) Phone);
277 
278 	pr_debug("%s: Dialing %s on channel %d\n",
279 		adapter[card]->devicename, Phone, channel+1);
280 
281 	return status;
282 }
283 
284 /*
285  * Answer an incoming call
286  */
answer(int card,unsigned long channel)287 int answer(int card, unsigned long channel)
288 {
289 	if(!IS_VALID_CARD(card)) {
290 		pr_debug("Invalid param: %d is not a valid card id\n", card);
291 		return -ENODEV;
292 	}
293 
294 	if(setup_buffers(card, channel+1, BUFFER_SIZE)) {
295 		hangup(card, channel+1);
296 		return -ENOBUFS;
297 	}
298 
299 	indicate_status(card, ISDN_STAT_BCONN,channel,NULL);
300 	pr_debug("%s: Answered incoming call on channel %s\n",
301 		adapter[card]->devicename, channel+1);
302 	return 0;
303 }
304 
305 /*
306  * Hangup up the call on specified channel
307  */
hangup(int card,unsigned long channel)308 int hangup(int card, unsigned long channel)
309 {
310 	int status;
311 
312 	if(!IS_VALID_CARD(card)) {
313 		pr_debug("Invalid param: %d is not a valid card id\n", card);
314 		return -ENODEV;
315 	}
316 
317 	status = sendmessage(card, CEPID, ceReqTypePhy,
318 						 ceReqClass1,
319 						 ceReqPhyDisconnect,
320 						 (unsigned char) channel+1,
321 						 0,
322 						 NULL);
323 	pr_debug("%s: Sent HANGUP message to channel %d\n",
324 		adapter[card]->devicename, channel+1);
325 	return status;
326 }
327 
328 /*
329  * Set the layer 2 protocol (X.25, HDLC, Raw)
330  */
setl2(int card,unsigned long arg)331 int setl2(int card, unsigned long arg)
332 {
333 	int status =0;
334 	int protocol,channel;
335 
336 	if(!IS_VALID_CARD(card)) {
337 		pr_debug("Invalid param: %d is not a valid card id\n", card);
338 		return -ENODEV;
339 	}
340 	protocol = arg >> 8;
341 	channel = arg & 0xff;
342 	adapter[card]->channel[channel].l2_proto = protocol;
343 	pr_debug("%s: Level 2 protocol for channel %d set to %s from %d\n",
344 		adapter[card]->devicename, channel+1,l2protos[adapter[card]->channel[channel].l2_proto],protocol);
345 
346 	/*
347 	 * check that the adapter is also set to the correct protocol
348 	 */
349 	pr_debug("%s: Sending GetFrameFormat for channel %d\n",
350 		adapter[card]->devicename, channel+1);
351 	status = sendmessage(card, CEPID, ceReqTypeCall,
352  				ceReqClass0,
353  				ceReqCallGetFrameFormat,
354  				(unsigned char)channel+1,
355  				1,
356  				(unsigned int *) protocol);
357 	if(status)
358 		return status;
359 	return 0;
360 }
361 
362 /*
363  * Get the layer 2 protocol
364  */
getl2(int card,unsigned long channel)365 int getl2(int card, unsigned long channel) {
366 
367 	if(!IS_VALID_CARD(card)) {
368 		pr_debug("Invalid param: %d is not a valid card id\n", card);
369 		return -ENODEV;
370 	}
371 
372 	pr_debug("%s: Level 2 protocol for channel %d reported as %s\n",
373 		adapter[card]->devicename, channel+1,
374 		l2protos[adapter[card]->channel[channel].l2_proto]);
375 
376 	return adapter[card]->channel[channel].l2_proto;
377 }
378 
379 /*
380  * Set the layer 3 protocol
381  */
setl3(int card,unsigned long channel)382 int setl3(int card, unsigned long channel)
383 {
384 	int protocol = channel >> 8;
385 
386 	if(!IS_VALID_CARD(card)) {
387 		pr_debug("Invalid param: %d is not a valid card id\n", card);
388 		return -ENODEV;
389 	}
390 
391 	adapter[card]->channel[channel].l3_proto = protocol;
392 	pr_debug("%s: Level 3 protocol for channel %d set to %s\n",
393 		adapter[card]->devicename, channel+1, l3protos[protocol]);
394 	return 0;
395 }
396 
397 /*
398  * Get the layer 3 protocol
399  */
getl3(int card,unsigned long arg)400 int getl3(int card, unsigned long arg)
401 {
402 	if(!IS_VALID_CARD(card)) {
403 		pr_debug("Invalid param: %d is not a valid card id\n", card);
404 		return -ENODEV;
405 	}
406 
407 	pr_debug("%s: Level 3 protocol for channel %d reported as %s\n",
408 			adapter[card]->devicename, arg+1,
409 			l3protos[adapter[card]->channel[arg].l3_proto]);
410 	return adapter[card]->channel[arg].l3_proto;
411 }
412 
413 
acceptb(int card,unsigned long channel)414 int acceptb(int card, unsigned long channel)
415 {
416 	if(!IS_VALID_CARD(card)) {
417 		pr_debug("Invalid param: %d is not a valid card id\n", card);
418 		return -ENODEV;
419 	}
420 
421 	if(setup_buffers(card, channel+1, BUFFER_SIZE))
422 	{
423 		hangup(card, channel+1);
424 		return -ENOBUFS;
425 	}
426 
427 	pr_debug("%s: B-Channel connection accepted on channel %d\n",
428 		adapter[card]->devicename, channel+1);
429 	indicate_status(card, ISDN_STAT_BCONN, channel, NULL);
430 	return 0;
431 }
432 
clreaz(int card,unsigned long arg)433 int clreaz(int card, unsigned long arg)
434 {
435 	if(!IS_VALID_CARD(card)) {
436 		pr_debug("Invalid param: %d is not a valid card id\n", card);
437 		return -ENODEV;
438 	}
439 
440 	strcpy(adapter[card]->channel[arg].eazlist, "");
441 	adapter[card]->channel[arg].eazclear = 1;
442 	pr_debug("%s: EAZ List cleared for channel %d\n",
443 		adapter[card]->devicename, arg+1);
444 	return 0;
445 }
446 
seteaz(int card,unsigned long arg,char * num)447 int seteaz(int card, unsigned long arg, char *num)
448 {
449 	if(!IS_VALID_CARD(card)) {
450 		pr_debug("Invalid param: %d is not a valid card id\n", card);
451 		return -ENODEV;
452 	}
453 
454 	strcpy(adapter[card]->channel[arg].eazlist, num);
455 	adapter[card]->channel[arg].eazclear = 0;
456 	pr_debug("%s: EAZ list for channel %d set to: %s\n",
457 		adapter[card]->devicename, arg+1,
458 		adapter[card]->channel[arg].eazlist);
459 	return 0;
460 }
461 
geteaz(int card,unsigned long arg,char * num)462 int geteaz(int card, unsigned long arg, char *num)
463 {
464 	if(!IS_VALID_CARD(card)) {
465 		pr_debug("Invalid param: %d is not a valid card id\n", card);
466 		return -ENODEV;
467 	}
468 
469 	strcpy(num, adapter[card]->channel[arg].eazlist);
470 	pr_debug("%s: EAZ List for channel %d reported: %s\n",
471 		adapter[card]->devicename, arg+1,
472 		adapter[card]->channel[arg].eazlist);
473 	return 0;
474 }
475 
setsil(int card,unsigned long arg,char * num)476 int setsil(int card, unsigned long arg, char *num)
477 {
478 	if(!IS_VALID_CARD(card)) {
479 		pr_debug("Invalid param: %d is not a valid card id\n", card);
480 		return -ENODEV;
481 	}
482 
483 	strcpy(adapter[card]->channel[arg].sillist, num);
484 	pr_debug("%s: Service Indicators for channel %d set: %s\n",
485 		adapter[card]->devicename, arg+1,
486 		adapter[card]->channel[arg].sillist);
487 	return 0;
488 }
489 
getsil(int card,unsigned long arg,char * num)490 int getsil(int card, unsigned long arg, char *num)
491 {
492 	if(!IS_VALID_CARD(card)) {
493 		pr_debug("Invalid param: %d is not a valid card id\n", card);
494 		return -ENODEV;
495 	}
496 
497 	strcpy(num, adapter[card]->channel[arg].sillist);
498 	pr_debug("%s: SIL for channel %d reported: %s\n",
499 		adapter[card]->devicename, arg+1,
500 		adapter[card]->channel[arg].sillist);
501 	return 0;
502 }
503 
504 
lock()505 int lock()
506 {
507 	MOD_INC_USE_COUNT;
508 	return 0;
509 }
510 
unlock()511 int unlock()
512 {
513 	MOD_DEC_USE_COUNT;
514 	return 0;
515 }
516 
reset(int card)517 int reset(int card)
518 {
519 	unsigned long flags;
520 
521 	if(!IS_VALID_CARD(card)) {
522 		pr_debug("Invalid param: %d is not a valid card id\n", card);
523 		return -ENODEV;
524 	}
525 
526 	indicate_status(card, ISDN_STAT_STOP, 0, NULL);
527 
528 	if(adapter[card]->EngineUp) {
529 		del_timer(&adapter[card]->stat_timer);
530 	}
531 
532 	adapter[card]->EngineUp = 0;
533 
534 	save_flags(flags);
535 	cli();
536 	init_timer(&adapter[card]->reset_timer);
537 	adapter[card]->reset_timer.function = check_reset;
538 	adapter[card]->reset_timer.data = card;
539 	adapter[card]->reset_timer.expires = jiffies + CHECKRESET_TIME;
540 	add_timer(&adapter[card]->reset_timer);
541 	restore_flags(flags);
542 
543 	outb(0x1,adapter[card]->ioport[SFT_RESET]);
544 
545 	pr_debug("%s: Adapter Reset\n", adapter[card]->devicename);
546 	return 0;
547 }
548 
flushreadfifo(int card)549 void flushreadfifo (int card)
550 {
551 	while(inb(adapter[card]->ioport[FIFO_STATUS]) & RF_HAS_DATA)
552 		inb(adapter[card]->ioport[FIFO_READ]);
553 }
554