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 = kzalloc(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 strlcpy(spid, rcvmsg->msg_data.byte_array, SCIOC_SPIDSIZE); 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 /* 219 * Get the spid from user space 220 */ 221 spid = memdup_user(data->dataptr, SCIOC_SPIDSIZE); 222 if (IS_ERR(spid)) { 223 kfree(rcvmsg); 224 return PTR_ERR(spid); 225 } 226 227 pr_debug("%s: SCIOCSETSPID: setting channel %d spid to %s\n", 228 sc_adapter[card]->devicename, data->channel, spid); 229 status = send_and_receive(card, CEPID, ceReqTypeCall, 230 ceReqClass0, ceReqCallSetSPID, data->channel, 231 strlen(spid), spid, rcvmsg, SAR_TIMEOUT); 232 if(!status && !(rcvmsg->rsp_status)) { 233 pr_debug("%s: SCIOCSETSPID: command successful\n", 234 sc_adapter[card]->devicename); 235 kfree(rcvmsg); 236 kfree(spid); 237 return 0; 238 } 239 else { 240 pr_debug("%s: SCIOCSETSPID: command failed (status = %d)\n", 241 sc_adapter[card]->devicename, status); 242 kfree(rcvmsg); 243 kfree(spid); 244 return status; 245 } 246 } 247 248 case SCIOCGETDN: 249 { 250 pr_debug("%s: SCIOGETDN: ioctl received\n", 251 sc_adapter[card]->devicename); 252 253 /* 254 * Get the dn from the board 255 */ 256 status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, ceReqCallGetMyNumber, 257 data->channel, 0, NULL, rcvmsg, SAR_TIMEOUT); 258 if (!status) { 259 pr_debug("%s: SCIOCGETDN: command successful\n", 260 sc_adapter[card]->devicename); 261 } 262 else { 263 pr_debug("%s: SCIOCGETDN: command failed (status = %d)\n", 264 sc_adapter[card]->devicename, status); 265 kfree(rcvmsg); 266 return status; 267 } 268 269 dn = kzalloc(SCIOC_DNSIZE, GFP_KERNEL); 270 if (!dn) { 271 kfree(rcvmsg); 272 return -ENOMEM; 273 } 274 strlcpy(dn, rcvmsg->msg_data.byte_array, SCIOC_DNSIZE); 275 kfree(rcvmsg); 276 277 /* 278 * Package the dn and send to user space 279 */ 280 if (copy_to_user(data->dataptr, dn, SCIOC_DNSIZE)) { 281 kfree(dn); 282 return -EFAULT; 283 } 284 kfree(dn); 285 return 0; 286 } 287 288 case SCIOCSETDN: 289 { 290 pr_debug("%s: SCIOSETDN: ioctl received\n", 291 sc_adapter[card]->devicename); 292 293 /* 294 * Get the spid from user space 295 */ 296 dn = memdup_user(data->dataptr, SCIOC_DNSIZE); 297 if (IS_ERR(dn)) { 298 kfree(rcvmsg); 299 return PTR_ERR(dn); 300 } 301 302 pr_debug("%s: SCIOCSETDN: setting channel %d dn to %s\n", 303 sc_adapter[card]->devicename, data->channel, dn); 304 status = send_and_receive(card, CEPID, ceReqTypeCall, 305 ceReqClass0, ceReqCallSetMyNumber, data->channel, 306 strlen(dn),dn,rcvmsg, SAR_TIMEOUT); 307 if(!status && !(rcvmsg->rsp_status)) { 308 pr_debug("%s: SCIOCSETDN: command successful\n", 309 sc_adapter[card]->devicename); 310 kfree(rcvmsg); 311 kfree(dn); 312 return 0; 313 } 314 else { 315 pr_debug("%s: SCIOCSETDN: command failed (status = %d)\n", 316 sc_adapter[card]->devicename, status); 317 kfree(rcvmsg); 318 kfree(dn); 319 return status; 320 } 321 } 322 323 case SCIOCTRACE: 324 325 pr_debug("%s: SCIOTRACE: ioctl received\n", 326 sc_adapter[card]->devicename); 327/* sc_adapter[card]->trace = !sc_adapter[card]->trace; 328 pr_debug("%s: SCIOCTRACE: tracing turned %s\n", 329 sc_adapter[card]->devicename, 330 sc_adapter[card]->trace ? "ON" : "OFF"); */ 331 break; 332 333 case SCIOCSTAT: 334 { 335 boardInfo *bi; 336 337 pr_debug("%s: SCIOSTAT: ioctl received\n", 338 sc_adapter[card]->devicename); 339 340 bi = kzalloc(sizeof(boardInfo), GFP_KERNEL); 341 if (!bi) { 342 kfree(rcvmsg); 343 return -ENOMEM; 344 } 345 346 kfree(rcvmsg); 347 GetStatus(card, bi); 348 349 if (copy_to_user(data->dataptr, bi, sizeof(boardInfo))) { 350 kfree(bi); 351 return -EFAULT; 352 } 353 354 kfree(bi); 355 return 0; 356 } 357 358 case SCIOCGETSPEED: 359 { 360 pr_debug("%s: SCIOGETSPEED: ioctl received\n", 361 sc_adapter[card]->devicename); 362 363 /* 364 * Get the speed from the board 365 */ 366 status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, 367 ceReqCallGetCallType, data->channel, 0, NULL, rcvmsg, SAR_TIMEOUT); 368 if (!status && !(rcvmsg->rsp_status)) { 369 pr_debug("%s: SCIOCGETSPEED: command successful\n", 370 sc_adapter[card]->devicename); 371 } 372 else { 373 pr_debug("%s: SCIOCGETSPEED: command failed (status = %d)\n", 374 sc_adapter[card]->devicename, status); 375 kfree(rcvmsg); 376 return status; 377 } 378 379 speed = rcvmsg->msg_data.byte_array[0]; 380 381 kfree(rcvmsg); 382 383 /* 384 * Package the switch type and send to user space 385 */ 386 387 if (copy_to_user(data->dataptr, &speed, sizeof(char))) 388 return -EFAULT; 389 390 return 0; 391 } 392 393 case SCIOCSETSPEED: 394 pr_debug("%s: SCIOCSETSPEED: ioctl received\n", 395 sc_adapter[card]->devicename); 396 break; 397 398 case SCIOCLOOPTST: 399 pr_debug("%s: SCIOCLOOPTST: ioctl received\n", 400 sc_adapter[card]->devicename); 401 break; 402 403 default: 404 kfree(rcvmsg); 405 return -1; 406 } 407 408 kfree(rcvmsg); 409 return 0; 410} 411 412static int GetStatus(int card, boardInfo *bi) 413{ 414 RspMessage rcvmsg; 415 int i, status; 416 417 /* 418 * Fill in some of the basic info about the board 419 */ 420 bi->modelid = sc_adapter[card]->model; 421 strcpy(bi->serial_no, sc_adapter[card]->hwconfig.serial_no); 422 strcpy(bi->part_no, sc_adapter[card]->hwconfig.part_no); 423 bi->iobase = sc_adapter[card]->iobase; 424 bi->rambase = sc_adapter[card]->rambase; 425 bi->irq = sc_adapter[card]->interrupt; 426 bi->ramsize = sc_adapter[card]->hwconfig.ram_size; 427 bi->interface = sc_adapter[card]->hwconfig.st_u_sense; 428 strcpy(bi->load_ver, sc_adapter[card]->load_ver); 429 strcpy(bi->proc_ver, sc_adapter[card]->proc_ver); 430 431 /* 432 * Get the current PhyStats and LnkStats 433 */ 434 status = send_and_receive(card, CEPID, ceReqTypePhy, ceReqClass2, 435 ceReqPhyStatus, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT); 436 if(!status) { 437 if(sc_adapter[card]->model < PRI_BOARD) { 438 bi->l1_status = rcvmsg.msg_data.byte_array[2]; 439 for(i = 0 ; i < BRI_CHANNELS ; i++) 440 bi->status.bristats[i].phy_stat = 441 rcvmsg.msg_data.byte_array[i]; 442 } 443 else { 444 bi->l1_status = rcvmsg.msg_data.byte_array[0]; 445 bi->l2_status = rcvmsg.msg_data.byte_array[1]; 446 for(i = 0 ; i < PRI_CHANNELS ; i++) 447 bi->status.pristats[i].phy_stat = 448 rcvmsg.msg_data.byte_array[i+2]; 449 } 450 } 451 452 /* 453 * Get the call types for each channel 454 */ 455 for (i = 0 ; i < sc_adapter[card]->nChannels ; i++) { 456 status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, 457 ceReqCallGetCallType, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT); 458 if(!status) { 459 if (sc_adapter[card]->model == PRI_BOARD) { 460 bi->status.pristats[i].call_type = 461 rcvmsg.msg_data.byte_array[0]; 462 } 463 else { 464 bi->status.bristats[i].call_type = 465 rcvmsg.msg_data.byte_array[0]; 466 } 467 } 468 } 469 470 /* 471 * If PRI, get the call states and service states for each channel 472 */ 473 if (sc_adapter[card]->model == PRI_BOARD) { 474 /* 475 * Get the call states 476 */ 477 status = send_and_receive(card, CEPID, ceReqTypeStat, ceReqClass2, 478 ceReqPhyChCallState, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT); 479 if(!status) { 480 for( i = 0 ; i < PRI_CHANNELS ; i++ ) 481 bi->status.pristats[i].call_state = 482 rcvmsg.msg_data.byte_array[i]; 483 } 484 485 /* 486 * Get the service states 487 */ 488 status = send_and_receive(card, CEPID, ceReqTypeStat, ceReqClass2, 489 ceReqPhyChServState, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT); 490 if(!status) { 491 for( i = 0 ; i < PRI_CHANNELS ; i++ ) 492 bi->status.pristats[i].serv_state = 493 rcvmsg.msg_data.byte_array[i]; 494 } 495 496 /* 497 * Get the link stats for the channels 498 */ 499 for (i = 1 ; i <= PRI_CHANNELS ; i++) { 500 status = send_and_receive(card, CEPID, ceReqTypeLnk, ceReqClass0, 501 ceReqLnkGetStats, i, 0, NULL, &rcvmsg, SAR_TIMEOUT); 502 if (!status) { 503 bi->status.pristats[i-1].link_stats.tx_good = 504 (unsigned long)rcvmsg.msg_data.byte_array[0]; 505 bi->status.pristats[i-1].link_stats.tx_bad = 506 (unsigned long)rcvmsg.msg_data.byte_array[4]; 507 bi->status.pristats[i-1].link_stats.rx_good = 508 (unsigned long)rcvmsg.msg_data.byte_array[8]; 509 bi->status.pristats[i-1].link_stats.rx_bad = 510 (unsigned long)rcvmsg.msg_data.byte_array[12]; 511 } 512 } 513 514 /* 515 * Link stats for the D channel 516 */ 517 status = send_and_receive(card, CEPID, ceReqTypeLnk, ceReqClass0, 518 ceReqLnkGetStats, 0, 0, NULL, &rcvmsg, SAR_TIMEOUT); 519 if (!status) { 520 bi->dch_stats.tx_good = (unsigned long)rcvmsg.msg_data.byte_array[0]; 521 bi->dch_stats.tx_bad = (unsigned long)rcvmsg.msg_data.byte_array[4]; 522 bi->dch_stats.rx_good = (unsigned long)rcvmsg.msg_data.byte_array[8]; 523 bi->dch_stats.rx_bad = (unsigned long)rcvmsg.msg_data.byte_array[12]; 524 } 525 526 return 0; 527 } 528 529 /* 530 * If BRI or POTS, Get SPID, DN and call types for each channel 531 */ 532 533 /* 534 * Get the link stats for the channels 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 bi->status.bristats[0].link_stats.tx_good = 544 (unsigned long)rcvmsg.msg_data.byte_array[16]; 545 bi->status.bristats[0].link_stats.tx_bad = 546 (unsigned long)rcvmsg.msg_data.byte_array[20]; 547 bi->status.bristats[0].link_stats.rx_good = 548 (unsigned long)rcvmsg.msg_data.byte_array[24]; 549 bi->status.bristats[0].link_stats.rx_bad = 550 (unsigned long)rcvmsg.msg_data.byte_array[28]; 551 bi->status.bristats[1].link_stats.tx_good = 552 (unsigned long)rcvmsg.msg_data.byte_array[32]; 553 bi->status.bristats[1].link_stats.tx_bad = 554 (unsigned long)rcvmsg.msg_data.byte_array[36]; 555 bi->status.bristats[1].link_stats.rx_good = 556 (unsigned long)rcvmsg.msg_data.byte_array[40]; 557 bi->status.bristats[1].link_stats.rx_bad = 558 (unsigned long)rcvmsg.msg_data.byte_array[44]; 559 } 560 561 /* 562 * Get the SPIDs 563 */ 564 for (i = 0 ; i < BRI_CHANNELS ; i++) { 565 status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, 566 ceReqCallGetSPID, i+1, 0, NULL, &rcvmsg, SAR_TIMEOUT); 567 if (!status) 568 strcpy(bi->status.bristats[i].spid, rcvmsg.msg_data.byte_array); 569 } 570 571 /* 572 * Get the DNs 573 */ 574 for (i = 0 ; i < BRI_CHANNELS ; i++) { 575 status = send_and_receive(card, CEPID, ceReqTypeCall, ceReqClass0, 576 ceReqCallGetMyNumber, i+1, 0, NULL, &rcvmsg, SAR_TIMEOUT); 577 if (!status) 578 strcpy(bi->status.bristats[i].dn, rcvmsg.msg_data.byte_array); 579 } 580 581 return 0; 582} 583