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 */
sc_ioctl(int card,scs_ioctl * data)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
GetStatus(int card,boardInfo * bi)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 }
519