command.c revision 1da177e4c3f41524e886b7f1b8a0c1fc7321cac2
1/* $Id: command.c,v 1.4.10.1 2001/09/23 22:24:59 kai Exp $ 2 * 3 * Copyright (C) 1996 SpellCaster Telecommunications Inc. 4 * 5 * This software may be used and distributed according to the terms 6 * of the GNU General Public License, incorporated herein by reference. 7 * 8 * For more information, please contact gpl-info@spellcast.com or write: 9 * 10 * SpellCaster Telecommunications Inc. 11 * 5621 Finch Avenue East, Unit #3 12 * Scarborough, Ontario Canada 13 * M1B 2T9 14 * +1 (416) 297-8565 15 * +1 (416) 297-6433 Facsimile 16 */ 17 18#include <linux/module.h> 19#include "includes.h" /* This must be first */ 20#include "hardware.h" 21#include "message.h" 22#include "card.h" 23#include "scioc.h" 24 25int dial(int card, unsigned long channel, setup_parm setup); 26int hangup(int card, unsigned long channel); 27int answer(int card, unsigned long channel); 28int clreaz(int card, unsigned long channel); 29int seteaz(int card, unsigned long channel, char *); 30int setl2(int card, unsigned long arg); 31int setl3(int card, unsigned long arg); 32int acceptb(int card, unsigned long channel); 33 34extern int cinst; 35extern board *sc_adapter[]; 36 37extern int sc_ioctl(int, scs_ioctl *); 38extern int setup_buffers(int, int, unsigned int); 39extern int indicate_status(int, int,ulong,char*); 40extern void check_reset(unsigned long); 41extern int send_and_receive(int, unsigned int, unsigned char, unsigned char, 42 unsigned char, unsigned char, unsigned char, unsigned char *, 43 RspMessage *, int); 44extern int sendmessage(int, unsigned int, unsigned int, unsigned int, 45 unsigned int, unsigned int, unsigned int, unsigned int *); 46extern inline void pullphone(char *, char *); 47 48#ifdef DEBUG 49/* 50 * Translate command codes to strings 51 */ 52static char *commands[] = { "ISDN_CMD_IOCTL", 53 "ISDN_CMD_DIAL", 54 "ISDN_CMD_ACCEPTB", 55 "ISDN_CMD_ACCEPTB", 56 "ISDN_CMD_HANGUP", 57 "ISDN_CMD_CLREAZ", 58 "ISDN_CMD_SETEAZ", 59 NULL, 60 NULL, 61 NULL, 62 "ISDN_CMD_SETL2", 63 NULL, 64 "ISDN_CMD_SETL3", 65 NULL, 66 NULL, 67 NULL, 68 NULL, 69 NULL, }; 70 71/* 72 * Translates ISDN4Linux protocol codes to strings for debug messages 73 */ 74static char *l3protos[] = { "ISDN_PROTO_L3_TRANS" }; 75static char *l2protos[] = { "ISDN_PROTO_L2_X75I", 76 "ISDN_PROTO_L2_X75UI", 77 "ISDN_PROTO_L2_X75BUI", 78 "ISDN_PROTO_L2_HDLC", 79 "ISDN_PROTO_L2_TRANS" }; 80#endif 81 82int get_card_from_id(int driver) 83{ 84 int i; 85 86 for(i = 0 ; i < cinst ; i++) { 87 if(sc_adapter[i]->driverId == driver) 88 return i; 89 } 90 return -ENODEV; 91} 92 93/* 94 * command 95 */ 96 97int command(isdn_ctrl *cmd) 98{ 99 int card; 100 101 card = get_card_from_id(cmd->driver); 102 if(!IS_VALID_CARD(card)) { 103 pr_debug("Invalid param: %d is not a valid card id\n", card); 104 return -ENODEV; 105 } 106 107 pr_debug("%s: Received %s command from Link Layer\n", 108 sc_adapter[card]->devicename, commands[cmd->command]); 109 110 /* 111 * Dispatch the command 112 */ 113 switch(cmd->command) { 114 case ISDN_CMD_IOCTL: 115 { 116 unsigned long cmdptr; 117 scs_ioctl ioc; 118 119 memcpy(&cmdptr, cmd->parm.num, sizeof(unsigned long)); 120 if (copy_from_user(&ioc, (scs_ioctl __user *)cmdptr, 121 sizeof(scs_ioctl))) { 122 pr_debug("%s: Failed to verify user space 0x%x\n", 123 sc_adapter[card]->devicename, cmdptr); 124 return -EFAULT; 125 } 126 return sc_ioctl(card, &ioc); 127 } 128 case ISDN_CMD_DIAL: 129 return dial(card, cmd->arg, cmd->parm.setup); 130 case ISDN_CMD_HANGUP: 131 return hangup(card, cmd->arg); 132 case ISDN_CMD_ACCEPTD: 133 return answer(card, cmd->arg); 134 case ISDN_CMD_ACCEPTB: 135 return acceptb(card, cmd->arg); 136 case ISDN_CMD_CLREAZ: 137 return clreaz(card, cmd->arg); 138 case ISDN_CMD_SETEAZ: 139 return seteaz(card, cmd->arg, cmd->parm.num); 140 case ISDN_CMD_SETL2: 141 return setl2(card, cmd->arg); 142 case ISDN_CMD_SETL3: 143 return setl3(card, cmd->arg); 144 default: 145 return -EINVAL; 146 } 147 return 0; 148} 149 150/* 151 * Confirm our ability to communicate with the board. This test assumes no 152 * other message activity is present 153 */ 154int loopback(int card) 155{ 156 157 int status; 158 static char testmsg[] = "Test Message"; 159 RspMessage rspmsg; 160 161 if(!IS_VALID_CARD(card)) { 162 pr_debug("Invalid param: %d is not a valid card id\n", card); 163 return -ENODEV; 164 } 165 166 pr_debug("%s: Sending loopback message\n", 167 sc_adapter[card]->devicename); 168 169 /* 170 * Send the loopback message to confirm that memory transfer is 171 * operational 172 */ 173 status = send_and_receive(card, CMPID, cmReqType1, 174 cmReqClass0, 175 cmReqMsgLpbk, 176 0, 177 (unsigned char) strlen(testmsg), 178 (unsigned char *)testmsg, 179 &rspmsg, SAR_TIMEOUT); 180 181 182 if (!status) { 183 pr_debug("%s: Loopback message successfully sent\n", 184 sc_adapter[card]->devicename); 185 if(strcmp(rspmsg.msg_data.byte_array, testmsg)) { 186 pr_debug("%s: Loopback return != sent\n", 187 sc_adapter[card]->devicename); 188 return -EIO; 189 } 190 return 0; 191 } 192 else { 193 pr_debug("%s: Send loopback message failed\n", 194 sc_adapter[card]->devicename); 195 return -EIO; 196 } 197 198} 199 200/* 201 * start the onboard firmware 202 */ 203int startproc(int card) 204{ 205 int status; 206 207 if(!IS_VALID_CARD(card)) { 208 pr_debug("Invalid param: %d is not a valid card id\n", card); 209 return -ENODEV; 210 } 211 212 /* 213 * send start msg 214 */ 215 status = sendmessage(card, CMPID,cmReqType2, 216 cmReqClass0, 217 cmReqStartProc, 218 0,0,NULL); 219 pr_debug("%s: Sent startProc\n", sc_adapter[card]->devicename); 220 221 return status; 222} 223 224 225int loadproc(int card, char *data) 226{ 227 return -1; 228} 229 230 231/* 232 * Dials the number passed in 233 */ 234int dial(int card, unsigned long channel, setup_parm setup) 235{ 236 int status; 237 char Phone[48]; 238 239 if(!IS_VALID_CARD(card)) { 240 pr_debug("Invalid param: %d is not a valid card id\n", card); 241 return -ENODEV; 242 } 243 244 /*extract ISDN number to dial from eaz/msn string*/ 245 strcpy(Phone,setup.phone); 246 247 /*send the connection message*/ 248 status = sendmessage(card, CEPID,ceReqTypePhy, 249 ceReqClass1, 250 ceReqPhyConnect, 251 (unsigned char) channel+1, 252 strlen(Phone), 253 (unsigned int *) Phone); 254 255 pr_debug("%s: Dialing %s on channel %d\n", 256 sc_adapter[card]->devicename, Phone, channel+1); 257 258 return status; 259} 260 261/* 262 * Answer an incoming call 263 */ 264int answer(int card, unsigned long channel) 265{ 266 if(!IS_VALID_CARD(card)) { 267 pr_debug("Invalid param: %d is not a valid card id\n", card); 268 return -ENODEV; 269 } 270 271 if(setup_buffers(card, channel+1, BUFFER_SIZE)) { 272 hangup(card, channel+1); 273 return -ENOBUFS; 274 } 275 276 indicate_status(card, ISDN_STAT_BCONN,channel,NULL); 277 pr_debug("%s: Answered incoming call on channel %s\n", 278 sc_adapter[card]->devicename, channel+1); 279 return 0; 280} 281 282/* 283 * Hangup up the call on specified channel 284 */ 285int hangup(int card, unsigned long channel) 286{ 287 int status; 288 289 if(!IS_VALID_CARD(card)) { 290 pr_debug("Invalid param: %d is not a valid card id\n", card); 291 return -ENODEV; 292 } 293 294 status = sendmessage(card, CEPID, ceReqTypePhy, 295 ceReqClass1, 296 ceReqPhyDisconnect, 297 (unsigned char) channel+1, 298 0, 299 NULL); 300 pr_debug("%s: Sent HANGUP message to channel %d\n", 301 sc_adapter[card]->devicename, channel+1); 302 return status; 303} 304 305/* 306 * Set the layer 2 protocol (X.25, HDLC, Raw) 307 */ 308int setl2(int card, unsigned long arg) 309{ 310 int status =0; 311 int protocol,channel; 312 313 if(!IS_VALID_CARD(card)) { 314 pr_debug("Invalid param: %d is not a valid card id\n", card); 315 return -ENODEV; 316 } 317 protocol = arg >> 8; 318 channel = arg & 0xff; 319 sc_adapter[card]->channel[channel].l2_proto = protocol; 320 pr_debug("%s: Level 2 protocol for channel %d set to %s from %d\n", 321 sc_adapter[card]->devicename, channel+1, 322 l2protos[sc_adapter[card]->channel[channel].l2_proto],protocol); 323 324 /* 325 * check that the adapter is also set to the correct protocol 326 */ 327 pr_debug("%s: Sending GetFrameFormat for channel %d\n", 328 sc_adapter[card]->devicename, channel+1); 329 status = sendmessage(card, CEPID, ceReqTypeCall, 330 ceReqClass0, 331 ceReqCallGetFrameFormat, 332 (unsigned char)channel+1, 333 1, 334 (unsigned int *) protocol); 335 if(status) 336 return status; 337 return 0; 338} 339 340/* 341 * Set the layer 3 protocol 342 */ 343int setl3(int card, unsigned long channel) 344{ 345 int protocol = channel >> 8; 346 347 if(!IS_VALID_CARD(card)) { 348 pr_debug("Invalid param: %d is not a valid card id\n", card); 349 return -ENODEV; 350 } 351 352 sc_adapter[card]->channel[channel].l3_proto = protocol; 353 pr_debug("%s: Level 3 protocol for channel %d set to %s\n", 354 sc_adapter[card]->devicename, channel+1, l3protos[protocol]); 355 return 0; 356} 357 358int acceptb(int card, unsigned long channel) 359{ 360 if(!IS_VALID_CARD(card)) { 361 pr_debug("Invalid param: %d is not a valid card id\n", card); 362 return -ENODEV; 363 } 364 365 if(setup_buffers(card, channel+1, BUFFER_SIZE)) 366 { 367 hangup(card, channel+1); 368 return -ENOBUFS; 369 } 370 371 pr_debug("%s: B-Channel connection accepted on channel %d\n", 372 sc_adapter[card]->devicename, channel+1); 373 indicate_status(card, ISDN_STAT_BCONN, channel, NULL); 374 return 0; 375} 376 377int clreaz(int card, unsigned long arg) 378{ 379 if(!IS_VALID_CARD(card)) { 380 pr_debug("Invalid param: %d is not a valid card id\n", card); 381 return -ENODEV; 382 } 383 384 strcpy(sc_adapter[card]->channel[arg].eazlist, ""); 385 sc_adapter[card]->channel[arg].eazclear = 1; 386 pr_debug("%s: EAZ List cleared for channel %d\n", 387 sc_adapter[card]->devicename, arg+1); 388 return 0; 389} 390 391int seteaz(int card, unsigned long arg, char *num) 392{ 393 if(!IS_VALID_CARD(card)) { 394 pr_debug("Invalid param: %d is not a valid card id\n", card); 395 return -ENODEV; 396 } 397 398 strcpy(sc_adapter[card]->channel[arg].eazlist, num); 399 sc_adapter[card]->channel[arg].eazclear = 0; 400 pr_debug("%s: EAZ list for channel %d set to: %s\n", 401 sc_adapter[card]->devicename, arg+1, 402 sc_adapter[card]->channel[arg].eazlist); 403 return 0; 404} 405 406int reset(int card) 407{ 408 unsigned long flags; 409 410 if(!IS_VALID_CARD(card)) { 411 pr_debug("Invalid param: %d is not a valid card id\n", card); 412 return -ENODEV; 413 } 414 415 indicate_status(card, ISDN_STAT_STOP, 0, NULL); 416 417 if(sc_adapter[card]->EngineUp) { 418 del_timer(&sc_adapter[card]->stat_timer); 419 } 420 421 sc_adapter[card]->EngineUp = 0; 422 423 spin_lock_irqsave(&sc_adapter[card]->lock, flags); 424 init_timer(&sc_adapter[card]->reset_timer); 425 sc_adapter[card]->reset_timer.function = check_reset; 426 sc_adapter[card]->reset_timer.data = card; 427 sc_adapter[card]->reset_timer.expires = jiffies + CHECKRESET_TIME; 428 add_timer(&sc_adapter[card]->reset_timer); 429 spin_unlock_irqrestore(&sc_adapter[card]->lock, flags); 430 431 outb(0x1,sc_adapter[card]->ioport[SFT_RESET]); 432 433 pr_debug("%s: Adapter Reset\n", sc_adapter[card]->devicename); 434 return 0; 435} 436 437void flushreadfifo (int card) 438{ 439 while(inb(sc_adapter[card]->ioport[FIFO_STATUS]) & RF_HAS_DATA) 440 inb(sc_adapter[card]->ioport[FIFO_READ]); 441} 442