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