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.
15 extern int indicate_status(int, int, unsigned long, char *);
16 extern int startproc(int);
17 extern int reset(int);
18 extern int send_and_receive(int, unsigned int, unsigned char,unsigned char,
19 unsigned char,unsigned char,
20 unsigned char, unsigned char *, RspMessage
*, int);
22 extern board
*sc_adapter
[];
25 static int GetStatus(int card
, boardInfo
*);
28 * Process private IOCTL messages (typically from scctrl)
30 int sc_ioctl(int card
, scs_ioctl
*data
)
39 rcvmsg
= kmalloc(sizeof(RspMessage
), GFP_KERNEL
);
43 switch(data
->command
) {
44 case SCIOCRESET
: /* Perform a hard reset of the adapter */
46 pr_debug("%s: SCIOCRESET: ioctl received\n",
47 sc_adapter
[card
]->devicename
);
48 sc_adapter
[card
]->StartOnReset
= 0;
57 srec
= kmalloc(SCIOC_SRECSIZE
, GFP_KERNEL
);
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
);
73 * Get the SRec from user space
75 if (copy_from_user(srec
, data
->dataptr
, SCIOC_SRECSIZE
)) {
81 status
= send_and_receive(card
, CMPID
, cmReqType2
, cmReqClass0
, cmReqLoadProc
,
82 0, SCIOC_SRECSIZE
, srec
, rcvmsg
, SAR_TIMEOUT
);
87 pr_debug("%s: SCIOCLOAD: command failed, status = %d\n",
88 sc_adapter
[card
]->devicename
, status
);
92 pr_debug("%s: SCIOCLOAD: command successful\n",
93 sc_adapter
[card
]->devicename
);
101 pr_debug("%s: SCIOSTART: ioctl received\n",
102 sc_adapter
[card
]->devicename
);
103 if(sc_adapter
[card
]->EngineUp
) {
104 pr_debug("%s: SCIOCSTART: command failed, engine already running.\n",
105 sc_adapter
[card
]->devicename
);
109 sc_adapter
[card
]->StartOnReset
= 1;
116 pr_debug("%s: SCIOSETSWITCH: ioctl received\n",
117 sc_adapter
[card
]->devicename
);
120 * Get the switch type from user space
122 if (copy_from_user(&switchtype
, data
->dataptr
, sizeof(char))) {
127 pr_debug("%s: SCIOCSETSWITCH: setting switch type to %d\n",
128 sc_adapter
[card
]->devicename
,
130 status
= send_and_receive(card
, CEPID
, ceReqTypeCall
, ceReqClass0
, ceReqCallSetSwitchType
,
131 0, sizeof(char),&switchtype
, rcvmsg
, SAR_TIMEOUT
);
132 if(!status
&& !(rcvmsg
->rsp_status
)) {
133 pr_debug("%s: SCIOCSETSWITCH: command successful\n",
134 sc_adapter
[card
]->devicename
);
139 pr_debug("%s: SCIOCSETSWITCH: command failed (status = %d)\n",
140 sc_adapter
[card
]->devicename
, status
);
148 pr_debug("%s: SCIOGETSWITCH: ioctl received\n",
149 sc_adapter
[card
]->devicename
);
152 * Get the switch type from the board
154 status
= send_and_receive(card
, CEPID
, ceReqTypeCall
, ceReqClass0
,
155 ceReqCallGetSwitchType
, 0, 0, NULL
, rcvmsg
, SAR_TIMEOUT
);
156 if (!status
&& !(rcvmsg
->rsp_status
)) {
157 pr_debug("%s: SCIOCGETSWITCH: command successful\n",
158 sc_adapter
[card
]->devicename
);
161 pr_debug("%s: SCIOCGETSWITCH: command failed (status = %d)\n",
162 sc_adapter
[card
]->devicename
, status
);
167 switchtype
= rcvmsg
->msg_data
.byte_array
[0];
170 * Package the switch type and send to user space
172 if (copy_to_user(data
->dataptr
, &switchtype
,
184 pr_debug("%s: SCIOGETSPID: ioctl received\n",
185 sc_adapter
[card
]->devicename
);
187 spid
= kmalloc(SCIOC_SPIDSIZE
, GFP_KERNEL
);
193 * Get the spid from the board
195 status
= send_and_receive(card
, CEPID
, ceReqTypeCall
, ceReqClass0
, ceReqCallGetSPID
,
196 data
->channel
, 0, NULL
, rcvmsg
, SAR_TIMEOUT
);
198 pr_debug("%s: SCIOCGETSPID: command successful\n",
199 sc_adapter
[card
]->devicename
);
201 pr_debug("%s: SCIOCGETSPID: command failed (status = %d)\n",
202 sc_adapter
[card
]->devicename
, status
);
207 strcpy(spid
, rcvmsg
->msg_data
.byte_array
);
210 * Package the switch type and send to user space
212 if (copy_to_user(data
->dataptr
, spid
, SCIOC_SPIDSIZE
)) {
225 pr_debug("%s: DCBIOSETSPID: ioctl received\n",
226 sc_adapter
[card
]->devicename
);
228 spid
= kmalloc(SCIOC_SPIDSIZE
, GFP_KERNEL
);
235 * Get the spid from user space
237 if (copy_from_user(spid
, data
->dataptr
, SCIOC_SPIDSIZE
)) {
242 pr_debug("%s: SCIOCSETSPID: setting channel %d spid to %s\n",
243 sc_adapter
[card
]->devicename
, data
->channel
, spid
);
244 status
= send_and_receive(card
, CEPID
, ceReqTypeCall
,
245 ceReqClass0
, ceReqCallSetSPID
, data
->channel
,
246 strlen(spid
), spid
, rcvmsg
, SAR_TIMEOUT
);
247 if(!status
&& !(rcvmsg
->rsp_status
)) {
248 pr_debug("%s: SCIOCSETSPID: command successful\n",
249 sc_adapter
[card
]->devicename
);
255 pr_debug("%s: SCIOCSETSPID: command failed (status = %d)\n",
256 sc_adapter
[card
]->devicename
, status
);
265 pr_debug("%s: SCIOGETDN: ioctl received\n",
266 sc_adapter
[card
]->devicename
);
269 * Get the dn from the board
271 status
= send_and_receive(card
, CEPID
, ceReqTypeCall
, ceReqClass0
, ceReqCallGetMyNumber
,
272 data
->channel
, 0, NULL
, rcvmsg
, SAR_TIMEOUT
);
274 pr_debug("%s: SCIOCGETDN: command successful\n",
275 sc_adapter
[card
]->devicename
);
278 pr_debug("%s: SCIOCGETDN: command failed (status = %d)\n",
279 sc_adapter
[card
]->devicename
, status
);
284 dn
= kmalloc(SCIOC_DNSIZE
, GFP_KERNEL
);
289 strcpy(dn
, rcvmsg
->msg_data
.byte_array
);
293 * Package the dn and send to user space
295 if (copy_to_user(data
->dataptr
, dn
, SCIOC_DNSIZE
)) {
305 pr_debug("%s: SCIOSETDN: ioctl received\n",
306 sc_adapter
[card
]->devicename
);
308 dn
= kmalloc(SCIOC_DNSIZE
, GFP_KERNEL
);
314 * Get the spid from user space
316 if (copy_from_user(dn
, data
->dataptr
, SCIOC_DNSIZE
)) {
322 pr_debug("%s: SCIOCSETDN: setting channel %d dn to %s\n",
323 sc_adapter
[card
]->devicename
, data
->channel
, dn
);
324 status
= send_and_receive(card
, CEPID
, ceReqTypeCall
,
325 ceReqClass0
, ceReqCallSetMyNumber
, data
->channel
,
326 strlen(dn
),dn
,rcvmsg
, SAR_TIMEOUT
);
327 if(!status
&& !(rcvmsg
->rsp_status
)) {
328 pr_debug("%s: SCIOCSETDN: command successful\n",
329 sc_adapter
[card
]->devicename
);
335 pr_debug("%s: SCIOCSETDN: command failed (status = %d)\n",
336 sc_adapter
[card
]->devicename
, status
);
345 pr_debug("%s: SCIOTRACE: ioctl received\n",
346 sc_adapter
[card
]->devicename
);
347 /* sc_adapter[card]->trace = !sc_adapter[card]->trace;
348 pr_debug("%s: SCIOCTRACE: tracing turned %s\n",
349 sc_adapter[card]->devicename,
350 sc_adapter[card]->trace ? "ON" : "OFF"); */
357 pr_debug("%s: SCIOSTAT: ioctl received\n",
358 sc_adapter
[card
]->devicename
);
360 bi
= kmalloc (sizeof(boardInfo
), GFP_KERNEL
);
369 if (copy_to_user(data
->dataptr
, bi
, sizeof(boardInfo
))) {
380 pr_debug("%s: SCIOGETSPEED: ioctl received\n",
381 sc_adapter
[card
]->devicename
);
384 * Get the speed from the board
386 status
= send_and_receive(card
, CEPID
, ceReqTypeCall
, ceReqClass0
,
387 ceReqCallGetCallType
, data
->channel
, 0, NULL
, rcvmsg
, SAR_TIMEOUT
);
388 if (!status
&& !(rcvmsg
->rsp_status
)) {
389 pr_debug("%s: SCIOCGETSPEED: command successful\n",
390 sc_adapter
[card
]->devicename
);
393 pr_debug("%s: SCIOCGETSPEED: command failed (status = %d)\n",
394 sc_adapter
[card
]->devicename
, status
);
399 speed
= rcvmsg
->msg_data
.byte_array
[0];
404 * Package the switch type and send to user space
407 if (copy_to_user(data
->dataptr
, &speed
, sizeof(char)))
414 pr_debug("%s: SCIOCSETSPEED: ioctl received\n",
415 sc_adapter
[card
]->devicename
);
419 pr_debug("%s: SCIOCLOOPTST: ioctl received\n",
420 sc_adapter
[card
]->devicename
);
432 static int GetStatus(int card
, boardInfo
*bi
)
438 * Fill in some of the basic info about the board
440 bi
->modelid
= sc_adapter
[card
]->model
;
441 strcpy(bi
->serial_no
, sc_adapter
[card
]->hwconfig
.serial_no
);
442 strcpy(bi
->part_no
, sc_adapter
[card
]->hwconfig
.part_no
);
443 bi
->iobase
= sc_adapter
[card
]->iobase
;
444 bi
->rambase
= sc_adapter
[card
]->rambase
;
445 bi
->irq
= sc_adapter
[card
]->interrupt
;
446 bi
->ramsize
= sc_adapter
[card
]->hwconfig
.ram_size
;
447 bi
->interface
= sc_adapter
[card
]->hwconfig
.st_u_sense
;
448 strcpy(bi
->load_ver
, sc_adapter
[card
]->load_ver
);
449 strcpy(bi
->proc_ver
, sc_adapter
[card
]->proc_ver
);
452 * Get the current PhyStats and LnkStats
454 status
= send_and_receive(card
, CEPID
, ceReqTypePhy
, ceReqClass2
,
455 ceReqPhyStatus
, 0, 0, NULL
, &rcvmsg
, SAR_TIMEOUT
);
457 if(sc_adapter
[card
]->model
< PRI_BOARD
) {
458 bi
->l1_status
= rcvmsg
.msg_data
.byte_array
[2];
459 for(i
= 0 ; i
< BRI_CHANNELS
; i
++)
460 bi
->status
.bristats
[i
].phy_stat
=
461 rcvmsg
.msg_data
.byte_array
[i
];
464 bi
->l1_status
= rcvmsg
.msg_data
.byte_array
[0];
465 bi
->l2_status
= rcvmsg
.msg_data
.byte_array
[1];
466 for(i
= 0 ; i
< PRI_CHANNELS
; i
++)
467 bi
->status
.pristats
[i
].phy_stat
=
468 rcvmsg
.msg_data
.byte_array
[i
+2];
473 * Get the call types for each channel
475 for (i
= 0 ; i
< sc_adapter
[card
]->nChannels
; i
++) {
476 status
= send_and_receive(card
, CEPID
, ceReqTypeCall
, ceReqClass0
,
477 ceReqCallGetCallType
, 0, 0, NULL
, &rcvmsg
, SAR_TIMEOUT
);
479 if (sc_adapter
[card
]->model
== PRI_BOARD
) {
480 bi
->status
.pristats
[i
].call_type
=
481 rcvmsg
.msg_data
.byte_array
[0];
484 bi
->status
.bristats
[i
].call_type
=
485 rcvmsg
.msg_data
.byte_array
[0];
491 * If PRI, get the call states and service states for each channel
493 if (sc_adapter
[card
]->model
== PRI_BOARD
) {
495 * Get the call states
497 status
= send_and_receive(card
, CEPID
, ceReqTypeStat
, ceReqClass2
,
498 ceReqPhyChCallState
, 0, 0, NULL
, &rcvmsg
, SAR_TIMEOUT
);
500 for( i
= 0 ; i
< PRI_CHANNELS
; i
++ )
501 bi
->status
.pristats
[i
].call_state
=
502 rcvmsg
.msg_data
.byte_array
[i
];
506 * Get the service states
508 status
= send_and_receive(card
, CEPID
, ceReqTypeStat
, ceReqClass2
,
509 ceReqPhyChServState
, 0, 0, NULL
, &rcvmsg
, SAR_TIMEOUT
);
511 for( i
= 0 ; i
< PRI_CHANNELS
; i
++ )
512 bi
->status
.pristats
[i
].serv_state
=
513 rcvmsg
.msg_data
.byte_array
[i
];
517 * Get the link stats for the channels
519 for (i
= 1 ; i
<= PRI_CHANNELS
; i
++) {
520 status
= send_and_receive(card
, CEPID
, ceReqTypeLnk
, ceReqClass0
,
521 ceReqLnkGetStats
, i
, 0, NULL
, &rcvmsg
, SAR_TIMEOUT
);
523 bi
->status
.pristats
[i
-1].link_stats
.tx_good
=
524 (unsigned long)rcvmsg
.msg_data
.byte_array
[0];
525 bi
->status
.pristats
[i
-1].link_stats
.tx_bad
=
526 (unsigned long)rcvmsg
.msg_data
.byte_array
[4];
527 bi
->status
.pristats
[i
-1].link_stats
.rx_good
=
528 (unsigned long)rcvmsg
.msg_data
.byte_array
[8];
529 bi
->status
.pristats
[i
-1].link_stats
.rx_bad
=
530 (unsigned long)rcvmsg
.msg_data
.byte_array
[12];
535 * Link stats for the D channel
537 status
= send_and_receive(card
, CEPID
, ceReqTypeLnk
, ceReqClass0
,
538 ceReqLnkGetStats
, 0, 0, NULL
, &rcvmsg
, SAR_TIMEOUT
);
540 bi
->dch_stats
.tx_good
= (unsigned long)rcvmsg
.msg_data
.byte_array
[0];
541 bi
->dch_stats
.tx_bad
= (unsigned long)rcvmsg
.msg_data
.byte_array
[4];
542 bi
->dch_stats
.rx_good
= (unsigned long)rcvmsg
.msg_data
.byte_array
[8];
543 bi
->dch_stats
.rx_bad
= (unsigned long)rcvmsg
.msg_data
.byte_array
[12];
550 * If BRI or POTS, Get SPID, DN and call types for each channel
554 * Get the link stats for the channels
556 status
= send_and_receive(card
, CEPID
, ceReqTypeLnk
, ceReqClass0
,
557 ceReqLnkGetStats
, 0, 0, NULL
, &rcvmsg
, SAR_TIMEOUT
);
559 bi
->dch_stats
.tx_good
= (unsigned long)rcvmsg
.msg_data
.byte_array
[0];
560 bi
->dch_stats
.tx_bad
= (unsigned long)rcvmsg
.msg_data
.byte_array
[4];
561 bi
->dch_stats
.rx_good
= (unsigned long)rcvmsg
.msg_data
.byte_array
[8];
562 bi
->dch_stats
.rx_bad
= (unsigned long)rcvmsg
.msg_data
.byte_array
[12];
563 bi
->status
.bristats
[0].link_stats
.tx_good
=
564 (unsigned long)rcvmsg
.msg_data
.byte_array
[16];
565 bi
->status
.bristats
[0].link_stats
.tx_bad
=
566 (unsigned long)rcvmsg
.msg_data
.byte_array
[20];
567 bi
->status
.bristats
[0].link_stats
.rx_good
=
568 (unsigned long)rcvmsg
.msg_data
.byte_array
[24];
569 bi
->status
.bristats
[0].link_stats
.rx_bad
=
570 (unsigned long)rcvmsg
.msg_data
.byte_array
[28];
571 bi
->status
.bristats
[1].link_stats
.tx_good
=
572 (unsigned long)rcvmsg
.msg_data
.byte_array
[32];
573 bi
->status
.bristats
[1].link_stats
.tx_bad
=
574 (unsigned long)rcvmsg
.msg_data
.byte_array
[36];
575 bi
->status
.bristats
[1].link_stats
.rx_good
=
576 (unsigned long)rcvmsg
.msg_data
.byte_array
[40];
577 bi
->status
.bristats
[1].link_stats
.rx_bad
=
578 (unsigned long)rcvmsg
.msg_data
.byte_array
[44];
584 for (i
= 0 ; i
< BRI_CHANNELS
; i
++) {
585 status
= send_and_receive(card
, CEPID
, ceReqTypeCall
, ceReqClass0
,
586 ceReqCallGetSPID
, i
+1, 0, NULL
, &rcvmsg
, SAR_TIMEOUT
);
588 strcpy(bi
->status
.bristats
[i
].spid
, rcvmsg
.msg_data
.byte_array
);
594 for (i
= 0 ; i
< BRI_CHANNELS
; i
++) {
595 status
= send_and_receive(card
, CEPID
, ceReqTypeCall
, ceReqClass0
,
596 ceReqCallGetMyNumber
, i
+1, 0, NULL
, &rcvmsg
, SAR_TIMEOUT
);
598 strcpy(bi
->status
.bristats
[i
].dn
, rcvmsg
.msg_data
.byte_array
);