• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 1996  SpellCaster Telecommunications Inc.
3  *
4  * This software may be used and distributed according to the terms
5  * of the GNU General Public License, incorporated herein by reference.
6  *
7  */
8 
9 #include "includes.h"
10 #include "hardware.h"
11 #include "message.h"
12 #include "card.h"
13 #include "scioc.h"
14 
15 static int GetStatus(int card, boardInfo *);
16 
17 /*
18  * Process private IOCTL messages (typically from scctrl)
19  */
sc_ioctl(int card,scs_ioctl * data)20 int sc_ioctl(int card, scs_ioctl *data)
21 {
22 	int		status;
23 	RspMessage	*rcvmsg;
24 	char		*spid;
25 	char		*dn;
26 	char		switchtype;
27 	char		speed;
28 
29 	rcvmsg = kmalloc(sizeof(RspMessage), GFP_KERNEL);
30 	if (!rcvmsg)
31 		return -ENOMEM;
32 
33 	switch (data->command) {
34 	case SCIOCRESET:	/* Perform a hard reset of the adapter */
35 	{
36 		pr_debug("%s: SCIOCRESET: ioctl received\n",
37 			 sc_adapter[card]->devicename);
38 		sc_adapter[card]->StartOnReset = 0;
39 		kfree(rcvmsg);
40 		return reset(card);
41 	}
42 
43 	case SCIOCLOAD:
44 	{
45 		char *srec;
46 
47 		srec = kmalloc(SCIOC_SRECSIZE, GFP_KERNEL);
48 		if (!srec) {
49 			kfree(rcvmsg);
50 			return -ENOMEM;
51 		}
52 		pr_debug("%s: SCIOLOAD: ioctl received\n",
53 			 sc_adapter[card]->devicename);
54 		if (sc_adapter[card]->EngineUp) {
55 			pr_debug("%s: SCIOCLOAD: command failed, LoadProc while engine running.\n",
56 				 sc_adapter[card]->devicename);
57 			kfree(rcvmsg);
58 			kfree(srec);
59 			return -1;
60 		}
61 
62 		/*
63 		 * Get the SRec from user space
64 		 */
65 		if (copy_from_user(srec, data->dataptr, SCIOC_SRECSIZE)) {
66 			kfree(rcvmsg);
67 			kfree(srec);
68 			return -EFAULT;
69 		}
70 
71 		status = send_and_receive(card, CMPID, cmReqType2, cmReqClass0, cmReqLoadProc,
72 					  0, SCIOC_SRECSIZE, srec, rcvmsg, SAR_TIMEOUT);
73 		kfree(rcvmsg);
74 		kfree(srec);
75 
76 		if (status) {
77 			pr_debug("%s: SCIOCLOAD: command failed, status = %d\n",
78 				 sc_adapter[card]->devicename, status);
79 			return -1;
80 		}
81 		else {
82 			pr_debug("%s: SCIOCLOAD: command successful\n",
83 				 sc_adapter[card]->devicename);
84 			return 0;
85 		}
86 	}
87 
88 	case SCIOCSTART:
89 	{
90 		kfree(rcvmsg);
91 		pr_debug("%s: SCIOSTART: ioctl received\n",
92 			 sc_adapter[card]->devicename);
93 		if (sc_adapter[card]->EngineUp) {
94 			pr_debug("%s: SCIOCSTART: command failed, engine already running.\n",
95 				 sc_adapter[card]->devicename);
96 			return -1;
97 		}
98 
99 		sc_adapter[card]->StartOnReset = 1;
100 		startproc(card);
101 		return 0;
102 	}
103 
104 	case SCIOCSETSWITCH:
105 	{
106 		pr_debug("%s: SCIOSETSWITCH: ioctl received\n",
107 			 sc_adapter[card]->devicename);
108 
109 		/*
110 		 * Get the switch type from user space
111 		 */
112 		if (copy_from_user(&switchtype, data->dataptr, sizeof(char))) {
113 			kfree(rcvmsg);
114 			return -EFAULT;
115 		}
116 
117 		pr_debug("%s: SCIOCSETSWITCH: setting switch type to %d\n",
118 			 sc_adapter[card]->devicename,
119 			 switchtype);
120 		status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallSetSwitchType,
121 					  0, sizeof(char), &switchtype, rcvmsg, SAR_TIMEOUT);
122 		if (!status && !(rcvmsg->rsp_status)) {
123 			pr_debug("%s: SCIOCSETSWITCH: command successful\n",
124 				 sc_adapter[card]->devicename);
125 			kfree(rcvmsg);
126 			return 0;
127 		}
128 		else {
129 			pr_debug("%s: SCIOCSETSWITCH: command failed (status = %d)\n",
130 				 sc_adapter[card]->devicename, status);
131 			kfree(rcvmsg);
132 			return status;
133 		}
134 	}
135 
136 	case SCIOCGETSWITCH:
137 	{
138 		pr_debug("%s: SCIOGETSWITCH: ioctl received\n",
139 			 sc_adapter[card]->devicename);
140 
141 		/*
142 		 * Get the switch type from the board
143 		 */
144 		status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0,
145 					  ceReqCallGetSwitchType, 0, 0, NULL, rcvmsg, SAR_TIMEOUT);
146 		if (!status && !(rcvmsg->rsp_status)) {
147 			pr_debug("%s: SCIOCGETSWITCH: command successful\n",
148 				 sc_adapter[card]->devicename);
149 		}
150 		else {
151 			pr_debug("%s: SCIOCGETSWITCH: command failed (status = %d)\n",
152 				 sc_adapter[card]->devicename, status);
153 			kfree(rcvmsg);
154 			return status;
155 		}
156 
157 		switchtype = rcvmsg->msg_data.byte_array[0];
158 
159 		/*
160 		 * Package the switch type and send to user space
161 		 */
162 		if (copy_to_user(data->dataptr, &switchtype,
163 				 sizeof(char))) {
164 			kfree(rcvmsg);
165 			return -EFAULT;
166 		}
167 
168 		kfree(rcvmsg);
169 		return 0;
170 	}
171 
172 	case SCIOCGETSPID:
173 	{
174 		pr_debug("%s: SCIOGETSPID: ioctl received\n",
175 			 sc_adapter[card]->devicename);
176 
177 		spid = kzalloc(SCIOC_SPIDSIZE, GFP_KERNEL);
178 		if (!spid) {
179 			kfree(rcvmsg);
180 			return -ENOMEM;
181 		}
182 		/*
183 		 * Get the spid from the board
184 		 */
185 		status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetSPID,
186 					  data->channel, 0, NULL, rcvmsg, SAR_TIMEOUT);
187 		if (!status) {
188 			pr_debug("%s: SCIOCGETSPID: command successful\n",
189 				 sc_adapter[card]->devicename);
190 		} else {
191 			pr_debug("%s: SCIOCGETSPID: command failed (status = %d)\n",
192 				 sc_adapter[card]->devicename, status);
193 			kfree(spid);
194 			kfree(rcvmsg);
195 			return status;
196 		}
197 		strlcpy(spid, rcvmsg->msg_data.byte_array, SCIOC_SPIDSIZE);
198 
199 		/*
200 		 * Package the switch type and send to user space
201 		 */
202 		if (copy_to_user(data->dataptr, spid, SCIOC_SPIDSIZE)) {
203 			kfree(spid);
204 			kfree(rcvmsg);
205 			return -EFAULT;
206 		}
207 
208 		kfree(spid);
209 		kfree(rcvmsg);
210 		return 0;
211 	}
212 
213 	case SCIOCSETSPID:
214 	{
215 		pr_debug("%s: DCBIOSETSPID: ioctl received\n",
216 			 sc_adapter[card]->devicename);
217 
218 		/*
219 		 * Get the spid from user space
220 		 */
221 		spid = memdup_user(data->dataptr, SCIOC_SPIDSIZE);
222 		if (IS_ERR(spid)) {
223 			kfree(rcvmsg);
224 			return PTR_ERR(spid);
225 		}
226 
227 		pr_debug("%s: SCIOCSETSPID: setting channel %d spid to %s\n",
228 			 sc_adapter[card]->devicename, data->channel, spid);
229 		status = send_and_receive(card, CEPID, ceReqTypeCall,
230 					  ceReqClass0, ceReqCallSetSPID, data->channel,
231 					  strlen(spid), spid, rcvmsg, SAR_TIMEOUT);
232 		if (!status && !(rcvmsg->rsp_status)) {
233 			pr_debug("%s: SCIOCSETSPID: command successful\n",
234 				 sc_adapter[card]->devicename);
235 			kfree(rcvmsg);
236 			kfree(spid);
237 			return 0;
238 		}
239 		else {
240 			pr_debug("%s: SCIOCSETSPID: command failed (status = %d)\n",
241 				 sc_adapter[card]->devicename, status);
242 			kfree(rcvmsg);
243 			kfree(spid);
244 			return status;
245 		}
246 	}
247 
248 	case SCIOCGETDN:
249 	{
250 		pr_debug("%s: SCIOGETDN: ioctl received\n",
251 			 sc_adapter[card]->devicename);
252 
253 		/*
254 		 * Get the dn from the board
255 		 */
256 		status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetMyNumber,
257 					  data->channel, 0, NULL, rcvmsg, SAR_TIMEOUT);
258 		if (!status) {
259 			pr_debug("%s: SCIOCGETDN: command successful\n",
260 				 sc_adapter[card]->devicename);
261 		}
262 		else {
263 			pr_debug("%s: SCIOCGETDN: command failed (status = %d)\n",
264 				 sc_adapter[card]->devicename, status);
265 			kfree(rcvmsg);
266 			return status;
267 		}
268 
269 		dn = kzalloc(SCIOC_DNSIZE, GFP_KERNEL);
270 		if (!dn) {
271 			kfree(rcvmsg);
272 			return -ENOMEM;
273 		}
274 		strlcpy(dn, rcvmsg->msg_data.byte_array, SCIOC_DNSIZE);
275 		kfree(rcvmsg);
276 
277 		/*
278 		 * Package the dn and send to user space
279 		 */
280 		if (copy_to_user(data->dataptr, dn, SCIOC_DNSIZE)) {
281 			kfree(dn);
282 			return -EFAULT;
283 		}
284 		kfree(dn);
285 		return 0;
286 	}
287 
288 	case SCIOCSETDN:
289 	{
290 		pr_debug("%s: SCIOSETDN: ioctl received\n",
291 			 sc_adapter[card]->devicename);
292 
293 		/*
294 		 * Get the spid from user space
295 		 */
296 		dn = memdup_user(data->dataptr, SCIOC_DNSIZE);
297 		if (IS_ERR(dn)) {
298 			kfree(rcvmsg);
299 			return PTR_ERR(dn);
300 		}
301 
302 		pr_debug("%s: SCIOCSETDN: setting channel %d dn to %s\n",
303 			 sc_adapter[card]->devicename, data->channel, dn);
304 		status = send_and_receive(card, CEPID, ceReqTypeCall,
305 					  ceReqClass0, ceReqCallSetMyNumber, data->channel,
306 					  strlen(dn), dn, rcvmsg, SAR_TIMEOUT);
307 		if (!status && !(rcvmsg->rsp_status)) {
308 			pr_debug("%s: SCIOCSETDN: command successful\n",
309 				 sc_adapter[card]->devicename);
310 			kfree(rcvmsg);
311 			kfree(dn);
312 			return 0;
313 		}
314 		else {
315 			pr_debug("%s: SCIOCSETDN: command failed (status = %d)\n",
316 				 sc_adapter[card]->devicename, status);
317 			kfree(rcvmsg);
318 			kfree(dn);
319 			return status;
320 		}
321 	}
322 
323 	case SCIOCTRACE:
324 
325 		pr_debug("%s: SCIOTRACE: ioctl received\n",
326 			 sc_adapter[card]->devicename);
327 /*		sc_adapter[card]->trace = !sc_adapter[card]->trace;
328 		pr_debug("%s: SCIOCTRACE: tracing turned %s\n",
329 		sc_adapter[card]->devicename,
330 		sc_adapter[card]->trace ? "ON" : "OFF"); */
331 		break;
332 
333 	case SCIOCSTAT:
334 	{
335 		boardInfo *bi;
336 
337 		pr_debug("%s: SCIOSTAT: ioctl received\n",
338 			 sc_adapter[card]->devicename);
339 
340 		bi = kzalloc(sizeof(boardInfo), GFP_KERNEL);
341 		if (!bi) {
342 			kfree(rcvmsg);
343 			return -ENOMEM;
344 		}
345 
346 		kfree(rcvmsg);
347 		GetStatus(card, bi);
348 
349 		if (copy_to_user(data->dataptr, bi, sizeof(boardInfo))) {
350 			kfree(bi);
351 			return -EFAULT;
352 		}
353 
354 		kfree(bi);
355 		return 0;
356 	}
357 
358 	case SCIOCGETSPEED:
359 	{
360 		pr_debug("%s: SCIOGETSPEED: ioctl received\n",
361 			 sc_adapter[card]->devicename);
362 
363 		/*
364 		 * Get the speed from the board
365 		 */
366 		status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0,
367 					  ceReqCallGetCallType, data->channel, 0, NULL, rcvmsg, SAR_TIMEOUT);
368 		if (!status && !(rcvmsg->rsp_status)) {
369 			pr_debug("%s: SCIOCGETSPEED: command successful\n",
370 				 sc_adapter[card]->devicename);
371 		}
372 		else {
373 			pr_debug("%s: SCIOCGETSPEED: command failed (status = %d)\n",
374 				 sc_adapter[card]->devicename, status);
375 			kfree(rcvmsg);
376 			return status;
377 		}
378 
379 		speed = rcvmsg->msg_data.byte_array[0];
380 
381 		kfree(rcvmsg);
382 
383 		/*
384 		 * Package the switch type and send to user space
385 		 */
386 
387 		if (copy_to_user(data->dataptr, &speed, sizeof(char)))
388 			return -EFAULT;
389 
390 		return 0;
391 	}
392 
393 	case SCIOCSETSPEED:
394 		pr_debug("%s: SCIOCSETSPEED: ioctl received\n",
395 			 sc_adapter[card]->devicename);
396 		break;
397 
398 	case SCIOCLOOPTST:
399 		pr_debug("%s: SCIOCLOOPTST: ioctl received\n",
400 			 sc_adapter[card]->devicename);
401 		break;
402 
403 	default:
404 		kfree(rcvmsg);
405 		return -1;
406 	}
407 
408 	kfree(rcvmsg);
409 	return 0;
410 }
411 
GetStatus(int card,boardInfo * bi)412 static int GetStatus(int card, boardInfo *bi)
413 {
414 	RspMessage rcvmsg;
415 	int i, status;
416 
417 	/*
418 	 * Fill in some of the basic info about the board
419 	 */
420 	bi->modelid = sc_adapter[card]->model;
421 	strcpy(bi->serial_no, sc_adapter[card]->hwconfig.serial_no);
422 	strcpy(bi->part_no, sc_adapter[card]->hwconfig.part_no);
423 	bi->iobase = sc_adapter[card]->iobase;
424 	bi->rambase = sc_adapter[card]->rambase;
425 	bi->irq = sc_adapter[card]->interrupt;
426 	bi->ramsize = sc_adapter[card]->hwconfig.ram_size;
427 	bi->interface = sc_adapter[card]->hwconfig.st_u_sense;
428 	strcpy(bi->load_ver, sc_adapter[card]->load_ver);
429 	strcpy(bi->proc_ver, sc_adapter[card]->proc_ver);
430 
431 	/*
432 	 * Get the current PhyStats and LnkStats
433 	 */
434 	status = send_and_receive(card, CEPID, ceReqTypePhy, ceReqClass2,
435 				  ceReqPhyStatus, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT);
436 	if (!status) {
437 		if (sc_adapter[card]->model < PRI_BOARD) {
438 			bi->l1_status = rcvmsg.msg_data.byte_array[2];
439 			for (i = 0; i < BRI_CHANNELS; i++)
440 				bi->status.bristats[i].phy_stat =
441 					rcvmsg.msg_data.byte_array[i];
442 		}
443 		else {
444 			bi->l1_status = rcvmsg.msg_data.byte_array[0];
445 			bi->l2_status = rcvmsg.msg_data.byte_array[1];
446 			for (i = 0; i < PRI_CHANNELS; i++)
447 				bi->status.pristats[i].phy_stat =
448 					rcvmsg.msg_data.byte_array[i + 2];
449 		}
450 	}
451 
452 	/*
453 	 * Get the call types for each channel
454 	 */
455 	for (i = 0; i < sc_adapter[card]->nChannels; i++) {
456 		status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0,
457 					  ceReqCallGetCallType, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT);
458 		if (!status) {
459 			if (sc_adapter[card]->model == PRI_BOARD) {
460 				bi->status.pristats[i].call_type =
461 					rcvmsg.msg_data.byte_array[0];
462 			}
463 			else {
464 				bi->status.bristats[i].call_type =
465 					rcvmsg.msg_data.byte_array[0];
466 			}
467 		}
468 	}
469 
470 	/*
471 	 * If PRI, get the call states and service states for each channel
472 	 */
473 	if (sc_adapter[card]->model == PRI_BOARD) {
474 		/*
475 		 * Get the call states
476 		 */
477 		status = send_and_receive(card, CEPID, ceReqTypeStat, ceReqClass2,
478 					  ceReqPhyChCallState, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT);
479 		if (!status) {
480 			for (i = 0; i < PRI_CHANNELS; i++)
481 				bi->status.pristats[i].call_state =
482 					rcvmsg.msg_data.byte_array[i];
483 		}
484 
485 		/*
486 		 * Get the service states
487 		 */
488 		status = send_and_receive(card, CEPID, ceReqTypeStat, ceReqClass2,
489 					  ceReqPhyChServState, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT);
490 		if (!status) {
491 			for (i = 0; i < PRI_CHANNELS; i++)
492 				bi->status.pristats[i].serv_state =
493 					rcvmsg.msg_data.byte_array[i];
494 		}
495 
496 		/*
497 		 * Get the link stats for the channels
498 		 */
499 		for (i = 1; i <= PRI_CHANNELS; i++) {
500 			status = send_and_receive(card, CEPID, ceReqTypeLnk, ceReqClass0,
501 						  ceReqLnkGetStats, i, 0, NULL, &rcvmsg, SAR_TIMEOUT);
502 			if (!status) {
503 				bi->status.pristats[i - 1].link_stats.tx_good =
504 					(unsigned long)rcvmsg.msg_data.byte_array[0];
505 				bi->status.pristats[i - 1].link_stats.tx_bad =
506 					(unsigned long)rcvmsg.msg_data.byte_array[4];
507 				bi->status.pristats[i - 1].link_stats.rx_good =
508 					(unsigned long)rcvmsg.msg_data.byte_array[8];
509 				bi->status.pristats[i - 1].link_stats.rx_bad =
510 					(unsigned long)rcvmsg.msg_data.byte_array[12];
511 			}
512 		}
513 
514 		/*
515 		 * Link stats for the D channel
516 		 */
517 		status = send_and_receive(card, CEPID, ceReqTypeLnk, ceReqClass0,
518 					  ceReqLnkGetStats, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT);
519 		if (!status) {
520 			bi->dch_stats.tx_good = (unsigned long)rcvmsg.msg_data.byte_array[0];
521 			bi->dch_stats.tx_bad = (unsigned long)rcvmsg.msg_data.byte_array[4];
522 			bi->dch_stats.rx_good = (unsigned long)rcvmsg.msg_data.byte_array[8];
523 			bi->dch_stats.rx_bad = (unsigned long)rcvmsg.msg_data.byte_array[12];
524 		}
525 
526 		return 0;
527 	}
528 
529 	/*
530 	 * If BRI or POTS, Get SPID, DN and call types for each channel
531 	 */
532 
533 	/*
534 	 * Get the link stats for the channels
535 	 */
536 	status = send_and_receive(card, CEPID, ceReqTypeLnk, ceReqClass0,
537 				  ceReqLnkGetStats, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT);
538 	if (!status) {
539 		bi->dch_stats.tx_good = (unsigned long)rcvmsg.msg_data.byte_array[0];
540 		bi->dch_stats.tx_bad = (unsigned long)rcvmsg.msg_data.byte_array[4];
541 		bi->dch_stats.rx_good = (unsigned long)rcvmsg.msg_data.byte_array[8];
542 		bi->dch_stats.rx_bad = (unsigned long)rcvmsg.msg_data.byte_array[12];
543 		bi->status.bristats[0].link_stats.tx_good =
544 			(unsigned long)rcvmsg.msg_data.byte_array[16];
545 		bi->status.bristats[0].link_stats.tx_bad =
546 			(unsigned long)rcvmsg.msg_data.byte_array[20];
547 		bi->status.bristats[0].link_stats.rx_good =
548 			(unsigned long)rcvmsg.msg_data.byte_array[24];
549 		bi->status.bristats[0].link_stats.rx_bad =
550 			(unsigned long)rcvmsg.msg_data.byte_array[28];
551 		bi->status.bristats[1].link_stats.tx_good =
552 			(unsigned long)rcvmsg.msg_data.byte_array[32];
553 		bi->status.bristats[1].link_stats.tx_bad =
554 			(unsigned long)rcvmsg.msg_data.byte_array[36];
555 		bi->status.bristats[1].link_stats.rx_good =
556 			(unsigned long)rcvmsg.msg_data.byte_array[40];
557 		bi->status.bristats[1].link_stats.rx_bad =
558 			(unsigned long)rcvmsg.msg_data.byte_array[44];
559 	}
560 
561 	/*
562 	 * Get the SPIDs
563 	 */
564 	for (i = 0; i < BRI_CHANNELS; i++) {
565 		status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0,
566 					  ceReqCallGetSPID, i + 1, 0, NULL, &rcvmsg, SAR_TIMEOUT);
567 		if (!status)
568 			strcpy(bi->status.bristats[i].spid, rcvmsg.msg_data.byte_array);
569 	}
570 
571 	/*
572 	 * Get the DNs
573 	 */
574 	for (i = 0; i < BRI_CHANNELS; i++) {
575 		status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0,
576 					  ceReqCallGetMyNumber, i + 1, 0, NULL, &rcvmsg, SAR_TIMEOUT);
577 		if (!status)
578 			strcpy(bi->status.bristats[i].dn, rcvmsg.msg_data.byte_array);
579 	}
580 
581 	return 0;
582 }
583