]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
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 | } |