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