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