[TG3]: Set minimal hw interrupt mitigation.
[linux-2.6/verdex.git] / drivers / isdn / sc / ioctl.c
blob1371a990416a4fcc8d95f42a947cf74c6e070044
1 /*
2 * Copyright (C) 1996 SpellCaster Telecommunications Inc.
4 * This software may be used and distributed according to the terms
5 * of the GNU General Public License, incorporated herein by reference.
7 */
9 #include "includes.h"
10 #include "hardware.h"
11 #include "message.h"
12 #include "card.h"
13 #include "scioc.h"
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);
23 extern board *sc_adapter[];
26 int GetStatus(int card, boardInfo *);
29 * Process private IOCTL messages (typically from scctrl)
31 int sc_ioctl(int card, scs_ioctl *data)
33 int status;
34 RspMessage *rcvmsg;
35 char *spid;
36 char *dn;
37 char switchtype;
38 char speed;
40 rcvmsg = kmalloc(sizeof(RspMessage), GFP_KERNEL);
41 if (!rcvmsg)
42 return -ENOMEM;
44 switch(data->command) {
45 case SCIOCRESET: /* Perform a hard reset of the adapter */
47 pr_debug("%s: SCIOCRESET: ioctl received\n",
48 sc_adapter[card]->devicename);
49 sc_adapter[card]->StartOnReset = 0;
50 return (reset(card));
53 case SCIOCLOAD:
55 char *srec;
57 srec = kmalloc(SCIOC_SRECSIZE, GFP_KERNEL);
58 if (!srec) {
59 kfree(rcvmsg);
60 return -ENOMEM;
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;
73 * Get the SRec from user space
75 if (copy_from_user(srec, data->dataptr, sizeof(srec))) {
76 kfree(rcvmsg);
77 kfree(srec);
78 return -EFAULT;
81 status = send_and_receive(card, CMPID, cmReqType2, cmReqClass0, cmReqLoadProc,
82 0, sizeof(srec), srec, rcvmsg, SAR_TIMEOUT);
83 kfree(rcvmsg);
84 kfree(srec);
86 if(status) {
87 pr_debug("%s: SCIOCLOAD: command failed, status = %d\n",
88 sc_adapter[card]->devicename, status);
89 return -1;
91 else {
92 pr_debug("%s: SCIOCLOAD: command successful\n",
93 sc_adapter[card]->devicename);
94 return 0;
98 case SCIOCSTART:
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;
108 sc_adapter[card]->StartOnReset = 1;
109 startproc(card);
110 return 0;
113 case SCIOCSETSWITCH:
115 pr_debug("%s: SCIOSETSWITCH: ioctl received\n",
116 sc_adapter[card]->devicename);
119 * Get the switch type from user space
121 if (copy_from_user(&switchtype, data->dataptr, sizeof(char))) {
122 kfree(rcvmsg);
123 return -EFAULT;
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;
137 else {
138 pr_debug("%s: SCIOCSETSWITCH: command failed (status = %d)\n",
139 sc_adapter[card]->devicename, status);
140 kfree(rcvmsg);
141 return status;
145 case SCIOCGETSWITCH:
147 pr_debug("%s: SCIOGETSWITCH: ioctl received\n",
148 sc_adapter[card]->devicename);
151 * Get the switch type from the board
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);
159 else {
160 pr_debug("%s: SCIOCGETSWITCH: command failed (status = %d)\n",
161 sc_adapter[card]->devicename, status);
162 kfree(rcvmsg);
163 return status;
166 switchtype = rcvmsg->msg_data.byte_array[0];
169 * Package the switch type and send to user space
171 if (copy_to_user(data->dataptr, &switchtype,
172 sizeof(char))) {
173 kfree(rcvmsg);
174 return -EFAULT;
177 kfree(rcvmsg);
178 return 0;
181 case SCIOCGETSPID:
183 pr_debug("%s: SCIOGETSPID: ioctl received\n",
184 sc_adapter[card]->devicename);
186 spid = kmalloc(SCIOC_SPIDSIZE, GFP_KERNEL);
187 if(!spid) {
188 kfree(rcvmsg);
189 return -ENOMEM;
192 * Get the spid from the board
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);
200 else {
201 pr_debug("%s: SCIOCGETSPID: command failed (status = %d)\n",
202 sc_adapter[card]->devicename, status);
203 kfree(rcvmsg);
204 return status;
206 strcpy(spid, rcvmsg->msg_data.byte_array);
209 * Package the switch type and send to user space
211 if (copy_to_user(data->dataptr, spid, SCIOC_SPIDSIZE)) {
212 kfree(spid);
213 kfree(rcvmsg);
214 return -EFAULT;
217 kfree(spid);
218 kfree(rcvmsg);
219 return 0;
222 case SCIOCSETSPID:
224 pr_debug("%s: DCBIOSETSPID: ioctl received\n",
225 sc_adapter[card]->devicename);
227 spid = kmalloc(SCIOC_SPIDSIZE, GFP_KERNEL);
228 if(!spid) {
229 kfree(rcvmsg);
230 return -ENOMEM;
234 * Get the spid from user space
236 if (copy_from_user(spid, data->dataptr, SCIOC_SPIDSIZE)) {
237 kfree(rcvmsg);
238 return -EFAULT;
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;
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;
262 case SCIOCGETDN:
264 pr_debug("%s: SCIOGETDN: ioctl received\n",
265 sc_adapter[card]->devicename);
268 * Get the dn from the board
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);
276 else {
277 pr_debug("%s: SCIOCGETDN: command failed (status = %d)\n",
278 sc_adapter[card]->devicename, status);
279 kfree(rcvmsg);
280 return status;
283 dn = kmalloc(SCIOC_DNSIZE, GFP_KERNEL);
284 if (!dn) {
285 kfree(rcvmsg);
286 return -ENOMEM;
288 strcpy(dn, rcvmsg->msg_data.byte_array);
289 kfree(rcvmsg);
292 * Package the dn and send to user space
294 if (copy_to_user(data->dataptr, dn, SCIOC_DNSIZE)) {
295 kfree(dn);
296 return -EFAULT;
298 kfree(dn);
299 return 0;
302 case SCIOCSETDN:
304 pr_debug("%s: SCIOSETDN: ioctl received\n",
305 sc_adapter[card]->devicename);
307 dn = kmalloc(SCIOC_DNSIZE, GFP_KERNEL);
308 if (!dn) {
309 kfree(rcvmsg);
310 return -ENOMEM;
313 * Get the spid from user space
315 if (copy_from_user(dn, data->dataptr, SCIOC_DNSIZE)) {
316 kfree(rcvmsg);
317 kfree(dn);
318 return -EFAULT;
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;
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;
342 case SCIOCTRACE:
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;
352 case SCIOCSTAT:
354 boardInfo *bi;
356 pr_debug("%s: SCIOSTAT: ioctl received\n",
357 sc_adapter[card]->devicename);
359 bi = kmalloc (sizeof(boardInfo), GFP_KERNEL);
360 if (!bi) {
361 kfree(rcvmsg);
362 return -ENOMEM;
365 kfree(rcvmsg);
366 GetStatus(card, bi);
368 if (copy_to_user(data->dataptr, bi, sizeof(boardInfo))) {
369 kfree(bi);
370 return -EFAULT;
373 kfree(bi);
374 return 0;
377 case SCIOCGETSPEED:
379 pr_debug("%s: SCIOGETSPEED: ioctl received\n",
380 sc_adapter[card]->devicename);
383 * Get the speed from the board
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);
391 else {
392 pr_debug("%s: SCIOCGETSPEED: command failed (status = %d)\n",
393 sc_adapter[card]->devicename, status);
394 kfree(rcvmsg);
395 return status;
398 speed = rcvmsg->msg_data.byte_array[0];
400 kfree(rcvmsg);
403 * Package the switch type and send to user space
406 if (copy_to_user(data->dataptr, &speed, sizeof(char)))
407 return -EFAULT;
409 return 0;
412 case SCIOCSETSPEED:
413 pr_debug("%s: SCIOCSETSPEED: ioctl received\n",
414 sc_adapter[card]->devicename);
415 break;
417 case SCIOCLOOPTST:
418 pr_debug("%s: SCIOCLOOPTST: ioctl received\n",
419 sc_adapter[card]->devicename);
420 break;
422 default:
423 kfree(rcvmsg);
424 return -1;
427 kfree(rcvmsg);
428 return 0;
431 int GetStatus(int card, boardInfo *bi)
433 RspMessage rcvmsg;
434 int i, status;
437 * Fill in some of the basic info about the board
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);
451 * Get the current PhyStats and LnkStats
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];
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];
472 * Get the call types for each channel
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];
482 else {
483 bi->status.bristats[i].call_type =
484 rcvmsg.msg_data.byte_array[0];
490 * If PRI, get the call states and service states for each channel
492 if (sc_adapter[card]->model == PRI_BOARD) {
494 * Get the call states
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];
505 * Get the service states
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];
516 * Get the link stats for the channels
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];
534 * Link stats for the D channel
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];
545 return 0;
549 * If BRI or POTS, Get SPID, DN and call types for each channel
553 * Get the link stats for the channels
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];
581 * Get the SPIDs
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);
591 * Get the DNs
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);
600 return 0;