command.c revision e3ca5e762c2aca373f1762cbc622ebe20fd20869
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 25static int dial(int card, unsigned long channel, setup_parm setup); 26static int hangup(int card, unsigned long channel); 27static int answer(int card, unsigned long channel); 28static int clreaz(int card, unsigned long channel); 29static int seteaz(int card, unsigned long channel, char *); 30static int setl2(int card, unsigned long arg); 31static int setl3(int card, unsigned long arg); 32static int 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 * start the onboard firmware 152 */ 153int startproc(int card) 154{ 155 int status; 156 157 if(!IS_VALID_CARD(card)) { 158 pr_debug("Invalid param: %d is not a valid card id\n", card); 159 return -ENODEV; 160 } 161 162 /* 163 * send start msg 164 */ 165 status = sendmessage(card, CMPID,cmReqType2, 166 cmReqClass0, 167 cmReqStartProc, 168 0,0,NULL); 169 pr_debug("%s: Sent startProc\n", sc_adapter[card]->devicename); 170 171 return status; 172} 173 174 175/* 176 * Dials the number passed in 177 */ 178static int dial(int card, unsigned long channel, setup_parm setup) 179{ 180 int status; 181 char Phone[48]; 182 183 if(!IS_VALID_CARD(card)) { 184 pr_debug("Invalid param: %d is not a valid card id\n", card); 185 return -ENODEV; 186 } 187 188 /*extract ISDN number to dial from eaz/msn string*/ 189 strcpy(Phone,setup.phone); 190 191 /*send the connection message*/ 192 status = sendmessage(card, CEPID,ceReqTypePhy, 193 ceReqClass1, 194 ceReqPhyConnect, 195 (unsigned char) channel+1, 196 strlen(Phone), 197 (unsigned int *) Phone); 198 199 pr_debug("%s: Dialing %s on channel %d\n", 200 sc_adapter[card]->devicename, Phone, channel+1); 201 202 return status; 203} 204 205/* 206 * Answer an incoming call 207 */ 208static int answer(int card, unsigned long channel) 209{ 210 if(!IS_VALID_CARD(card)) { 211 pr_debug("Invalid param: %d is not a valid card id\n", card); 212 return -ENODEV; 213 } 214 215 if(setup_buffers(card, channel+1, BUFFER_SIZE)) { 216 hangup(card, channel+1); 217 return -ENOBUFS; 218 } 219 220 indicate_status(card, ISDN_STAT_BCONN,channel,NULL); 221 pr_debug("%s: Answered incoming call on channel %s\n", 222 sc_adapter[card]->devicename, channel+1); 223 return 0; 224} 225 226/* 227 * Hangup up the call on specified channel 228 */ 229static int hangup(int card, unsigned long channel) 230{ 231 int status; 232 233 if(!IS_VALID_CARD(card)) { 234 pr_debug("Invalid param: %d is not a valid card id\n", card); 235 return -ENODEV; 236 } 237 238 status = sendmessage(card, CEPID, ceReqTypePhy, 239 ceReqClass1, 240 ceReqPhyDisconnect, 241 (unsigned char) channel+1, 242 0, 243 NULL); 244 pr_debug("%s: Sent HANGUP message to channel %d\n", 245 sc_adapter[card]->devicename, channel+1); 246 return status; 247} 248 249/* 250 * Set the layer 2 protocol (X.25, HDLC, Raw) 251 */ 252static int setl2(int card, unsigned long arg) 253{ 254 int status =0; 255 int protocol,channel; 256 257 if(!IS_VALID_CARD(card)) { 258 pr_debug("Invalid param: %d is not a valid card id\n", card); 259 return -ENODEV; 260 } 261 protocol = arg >> 8; 262 channel = arg & 0xff; 263 sc_adapter[card]->channel[channel].l2_proto = protocol; 264 pr_debug("%s: Level 2 protocol for channel %d set to %s from %d\n", 265 sc_adapter[card]->devicename, channel+1, 266 l2protos[sc_adapter[card]->channel[channel].l2_proto],protocol); 267 268 /* 269 * check that the adapter is also set to the correct protocol 270 */ 271 pr_debug("%s: Sending GetFrameFormat for channel %d\n", 272 sc_adapter[card]->devicename, channel+1); 273 status = sendmessage(card, CEPID, ceReqTypeCall, 274 ceReqClass0, 275 ceReqCallGetFrameFormat, 276 (unsigned char)channel+1, 277 1, 278 (unsigned int *) protocol); 279 if(status) 280 return status; 281 return 0; 282} 283 284/* 285 * Set the layer 3 protocol 286 */ 287static int setl3(int card, unsigned long channel) 288{ 289 int protocol = channel >> 8; 290 291 if(!IS_VALID_CARD(card)) { 292 pr_debug("Invalid param: %d is not a valid card id\n", card); 293 return -ENODEV; 294 } 295 296 sc_adapter[card]->channel[channel].l3_proto = protocol; 297 pr_debug("%s: Level 3 protocol for channel %d set to %s\n", 298 sc_adapter[card]->devicename, channel+1, l3protos[protocol]); 299 return 0; 300} 301 302static int acceptb(int card, unsigned long channel) 303{ 304 if(!IS_VALID_CARD(card)) { 305 pr_debug("Invalid param: %d is not a valid card id\n", card); 306 return -ENODEV; 307 } 308 309 if(setup_buffers(card, channel+1, BUFFER_SIZE)) 310 { 311 hangup(card, channel+1); 312 return -ENOBUFS; 313 } 314 315 pr_debug("%s: B-Channel connection accepted on channel %d\n", 316 sc_adapter[card]->devicename, channel+1); 317 indicate_status(card, ISDN_STAT_BCONN, channel, NULL); 318 return 0; 319} 320 321static int clreaz(int card, unsigned long arg) 322{ 323 if(!IS_VALID_CARD(card)) { 324 pr_debug("Invalid param: %d is not a valid card id\n", card); 325 return -ENODEV; 326 } 327 328 strcpy(sc_adapter[card]->channel[arg].eazlist, ""); 329 sc_adapter[card]->channel[arg].eazclear = 1; 330 pr_debug("%s: EAZ List cleared for channel %d\n", 331 sc_adapter[card]->devicename, arg+1); 332 return 0; 333} 334 335static int seteaz(int card, unsigned long arg, char *num) 336{ 337 if(!IS_VALID_CARD(card)) { 338 pr_debug("Invalid param: %d is not a valid card id\n", card); 339 return -ENODEV; 340 } 341 342 strcpy(sc_adapter[card]->channel[arg].eazlist, num); 343 sc_adapter[card]->channel[arg].eazclear = 0; 344 pr_debug("%s: EAZ list for channel %d set to: %s\n", 345 sc_adapter[card]->devicename, arg+1, 346 sc_adapter[card]->channel[arg].eazlist); 347 return 0; 348} 349 350int reset(int card) 351{ 352 unsigned long flags; 353 354 if(!IS_VALID_CARD(card)) { 355 pr_debug("Invalid param: %d is not a valid card id\n", card); 356 return -ENODEV; 357 } 358 359 indicate_status(card, ISDN_STAT_STOP, 0, NULL); 360 361 if(sc_adapter[card]->EngineUp) { 362 del_timer(&sc_adapter[card]->stat_timer); 363 } 364 365 sc_adapter[card]->EngineUp = 0; 366 367 spin_lock_irqsave(&sc_adapter[card]->lock, flags); 368 init_timer(&sc_adapter[card]->reset_timer); 369 sc_adapter[card]->reset_timer.function = check_reset; 370 sc_adapter[card]->reset_timer.data = card; 371 sc_adapter[card]->reset_timer.expires = jiffies + CHECKRESET_TIME; 372 add_timer(&sc_adapter[card]->reset_timer); 373 spin_unlock_irqrestore(&sc_adapter[card]->lock, flags); 374 375 outb(0x1,sc_adapter[card]->ioport[SFT_RESET]); 376 377 pr_debug("%s: Adapter Reset\n", sc_adapter[card]->devicename); 378 return 0; 379} 380 381void flushreadfifo (int card) 382{ 383 while(inb(sc_adapter[card]->ioport[FIFO_STATUS]) & RF_HAS_DATA) 384 inb(sc_adapter[card]->ioport[FIFO_READ]); 385} 386