linux/drivers/isdn/sc/ioctl.c
<<
>>
Prefs
   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