1/* $Id: hycapi.c,v 1.1.1.1 2007/08/03 18:52:36 Exp $ 2 * 3 * Linux driver for HYSDN cards, CAPI2.0-Interface. 4 * 5 * Author Ulrich Albrecht <u.albrecht@hypercope.de> for Hypercope GmbH 6 * Copyright 2000 by Hypercope GmbH 7 * 8 * This software may be used and distributed according to the terms 9 * of the GNU General Public License, incorporated herein by reference. 10 * 11 */ 12 13#include <linux/module.h> 14#include <linux/signal.h> 15#include <linux/kernel.h> 16#include <linux/skbuff.h> 17#include <linux/netdevice.h> 18 19#define VER_DRIVER 0 20#define VER_CARDTYPE 1 21#define VER_HWID 2 22#define VER_SERIAL 3 23#define VER_OPTION 4 24#define VER_PROTO 5 25#define VER_PROFILE 6 26#define VER_CAPI 7 27 28#include "hysdn_defs.h" 29#include <linux/kernelcapi.h> 30 31static char hycapi_revision[]="$Revision: 1.1.1.1 $"; 32 33unsigned int hycapi_enable = 0xffffffff; 34module_param(hycapi_enable, uint, 0); 35 36typedef struct _hycapi_appl { 37 unsigned int ctrl_mask; 38 capi_register_params rp; 39 struct sk_buff *listen_req[CAPI_MAXCONTR]; 40} hycapi_appl; 41 42static hycapi_appl hycapi_applications[CAPI_MAXAPPL]; 43 44static u16 hycapi_send_message(struct capi_ctr *ctrl, struct sk_buff *skb); 45 46static inline int _hycapi_appCheck(int app_id, int ctrl_no) 47{ 48 if((ctrl_no <= 0) || (ctrl_no > CAPI_MAXCONTR) || (app_id <= 0) || 49 (app_id > CAPI_MAXAPPL)) 50 { 51 printk(KERN_ERR "HYCAPI: Invalid request app_id %d for controller %d", app_id, ctrl_no); 52 return -1; 53 } 54 return ((hycapi_applications[app_id-1].ctrl_mask & (1 << (ctrl_no-1))) != 0); 55} 56 57/****************************** 58Kernel-Capi callback reset_ctr 59******************************/ 60 61static void 62hycapi_reset_ctr(struct capi_ctr *ctrl) 63{ 64 hycapictrl_info *cinfo = ctrl->driverdata; 65 66#ifdef HYCAPI_PRINTFNAMES 67 printk(KERN_NOTICE "HYCAPI hycapi_reset_ctr\n"); 68#endif 69 capilib_release(&cinfo->ncci_head); 70 capi_ctr_reseted(ctrl); 71} 72 73/****************************** 74Kernel-Capi callback remove_ctr 75******************************/ 76 77static void 78hycapi_remove_ctr(struct capi_ctr *ctrl) 79{ 80 int i; 81 hycapictrl_info *cinfo = NULL; 82 hysdn_card *card = NULL; 83#ifdef HYCAPI_PRINTFNAMES 84 printk(KERN_NOTICE "HYCAPI hycapi_remove_ctr\n"); 85#endif 86 cinfo = (hycapictrl_info *)(ctrl->driverdata); 87 if(!cinfo) { 88 printk(KERN_ERR "No hycapictrl_info set!"); 89 return; 90 } 91 card = cinfo->card; 92 capi_ctr_suspend_output(ctrl); 93 for(i=0; i<CAPI_MAXAPPL;i++) { 94 if(hycapi_applications[i].listen_req[ctrl->cnr-1]) { 95 kfree_skb(hycapi_applications[i].listen_req[ctrl->cnr-1]); 96 hycapi_applications[i].listen_req[ctrl->cnr-1] = NULL; 97 } 98 } 99 detach_capi_ctr(ctrl); 100 ctrl->driverdata = NULL; 101 kfree(card->hyctrlinfo); 102 103 104 card->hyctrlinfo = NULL; 105} 106 107/*********************************************************** 108 109Queue a CAPI-message to the controller. 110 111***********************************************************/ 112 113static void 114hycapi_sendmsg_internal(struct capi_ctr *ctrl, struct sk_buff *skb) 115{ 116 hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata); 117 hysdn_card *card = cinfo->card; 118 119 spin_lock_irq(&cinfo->lock); 120#ifdef HYCAPI_PRINTFNAMES 121 printk(KERN_NOTICE "hycapi_send_message\n"); 122#endif 123 cinfo->skbs[cinfo->in_idx++] = skb; /* add to buffer list */ 124 if (cinfo->in_idx >= HYSDN_MAX_CAPI_SKB) 125 cinfo->in_idx = 0; /* wrap around */ 126 cinfo->sk_count++; /* adjust counter */ 127 if (cinfo->sk_count >= HYSDN_MAX_CAPI_SKB) { 128 /* inform upper layers we're full */ 129 printk(KERN_ERR "HYSDN Card%d: CAPI-buffer overrun!\n", 130 card->myid); 131 capi_ctr_suspend_output(ctrl); 132 } 133 cinfo->tx_skb = skb; 134 spin_unlock_irq(&cinfo->lock); 135 schedule_work(&card->irq_queue); 136} 137 138/*********************************************************** 139hycapi_register_internal 140 141Send down the CAPI_REGISTER-Command to the controller. 142This functions will also be used if the adapter has been rebooted to 143re-register any applications in the private list. 144 145************************************************************/ 146 147static void 148hycapi_register_internal(struct capi_ctr *ctrl, __u16 appl, 149 capi_register_params *rp) 150{ 151 char ExtFeatureDefaults[] = "49 /0/0/0/0,*/1,*/2,*/3,*/4,*/5,*/6,*/7,*/8,*/9,*"; 152 hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata); 153 hysdn_card *card = cinfo->card; 154 struct sk_buff *skb; 155 __u16 len; 156 __u8 _command = 0xa0, _subcommand = 0x80; 157 __u16 MessageNumber = 0x0000; 158 __u16 MessageBufferSize = 0; 159 int slen = strlen(ExtFeatureDefaults); 160#ifdef HYCAPI_PRINTFNAMES 161 printk(KERN_NOTICE "hycapi_register_appl\n"); 162#endif 163 MessageBufferSize = rp->level3cnt * rp->datablkcnt * rp->datablklen; 164 165 len = CAPI_MSG_BASELEN + 8 + slen + 1; 166 if (!(skb = alloc_skb(len, GFP_ATOMIC))) { 167 printk(KERN_ERR "HYSDN card%d: memory squeeze in hycapi_register_appl\n", 168 card->myid); 169 return; 170 } 171 memcpy(skb_put(skb,sizeof(__u16)), &len, sizeof(__u16)); 172 memcpy(skb_put(skb,sizeof(__u16)), &appl, sizeof(__u16)); 173 memcpy(skb_put(skb,sizeof(__u8)), &_command, sizeof(_command)); 174 memcpy(skb_put(skb,sizeof(__u8)), &_subcommand, sizeof(_subcommand)); 175 memcpy(skb_put(skb,sizeof(__u16)), &MessageNumber, sizeof(__u16)); 176 memcpy(skb_put(skb,sizeof(__u16)), &MessageBufferSize, sizeof(__u16)); 177 memcpy(skb_put(skb,sizeof(__u16)), &(rp->level3cnt), sizeof(__u16)); 178 memcpy(skb_put(skb,sizeof(__u16)), &(rp->datablkcnt), sizeof(__u16)); 179 memcpy(skb_put(skb,sizeof(__u16)), &(rp->datablklen), sizeof(__u16)); 180 memcpy(skb_put(skb,slen), ExtFeatureDefaults, slen); 181 hycapi_applications[appl-1].ctrl_mask |= (1 << (ctrl->cnr-1)); 182 hycapi_send_message(ctrl, skb); 183} 184 185/************************************************************ 186hycapi_restart_internal 187 188After an adapter has been rebootet, re-register all applications and 189send a LISTEN_REQ (if there has been such a thing ) 190 191*************************************************************/ 192 193static void hycapi_restart_internal(struct capi_ctr *ctrl) 194{ 195 int i; 196 struct sk_buff *skb; 197#ifdef HYCAPI_PRINTFNAMES 198 printk(KERN_WARNING "HYSDN: hycapi_restart_internal"); 199#endif 200 for(i=0; i<CAPI_MAXAPPL; i++) { 201 if(_hycapi_appCheck(i+1, ctrl->cnr) == 1) { 202 hycapi_register_internal(ctrl, i+1, 203 &hycapi_applications[i].rp); 204 if(hycapi_applications[i].listen_req[ctrl->cnr-1]) { 205 skb = skb_copy(hycapi_applications[i].listen_req[ctrl->cnr-1], GFP_ATOMIC); 206 hycapi_sendmsg_internal(ctrl, skb); 207 } 208 } 209 } 210} 211 212/************************************************************* 213Register an application. 214Error-checking is done for CAPI-compliance. 215 216The application is recorded in the internal list. 217*************************************************************/ 218 219static void 220hycapi_register_appl(struct capi_ctr *ctrl, __u16 appl, 221 capi_register_params *rp) 222{ 223 int MaxLogicalConnections = 0, MaxBDataBlocks = 0, MaxBDataLen = 0; 224 hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata); 225 hysdn_card *card = cinfo->card; 226 int chk = _hycapi_appCheck(appl, ctrl->cnr); 227 if(chk < 0) { 228 return; 229 } 230 if(chk == 1) { 231 printk(KERN_INFO "HYSDN: apl %d already registered\n", appl); 232 return; 233 } 234 MaxBDataBlocks = rp->datablkcnt > CAPI_MAXDATAWINDOW ? CAPI_MAXDATAWINDOW : rp->datablkcnt; 235 rp->datablkcnt = MaxBDataBlocks; 236 MaxBDataLen = rp->datablklen < 1024 ? 1024 : rp->datablklen ; 237 rp->datablklen = MaxBDataLen; 238 239 MaxLogicalConnections = rp->level3cnt; 240 if (MaxLogicalConnections < 0) { 241 MaxLogicalConnections = card->bchans * -MaxLogicalConnections; 242 } 243 if (MaxLogicalConnections == 0) { 244 MaxLogicalConnections = card->bchans; 245 } 246 247 rp->level3cnt = MaxLogicalConnections; 248 memcpy(&hycapi_applications[appl-1].rp, 249 rp, sizeof(capi_register_params)); 250} 251 252/********************************************************************* 253 254hycapi_release_internal 255 256Send down a CAPI_RELEASE to the controller. 257*********************************************************************/ 258 259static void hycapi_release_internal(struct capi_ctr *ctrl, __u16 appl) 260{ 261 hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata); 262 hysdn_card *card = cinfo->card; 263 struct sk_buff *skb; 264 __u16 len; 265 __u8 _command = 0xa1, _subcommand = 0x80; 266 __u16 MessageNumber = 0x0000; 267 268 capilib_release_appl(&cinfo->ncci_head, appl); 269 270#ifdef HYCAPI_PRINTFNAMES 271 printk(KERN_NOTICE "hycapi_release_appl\n"); 272#endif 273 len = CAPI_MSG_BASELEN; 274 if (!(skb = alloc_skb(len, GFP_ATOMIC))) { 275 printk(KERN_ERR "HYSDN card%d: memory squeeze in hycapi_register_appl\n", 276 card->myid); 277 return; 278 } 279 memcpy(skb_put(skb,sizeof(__u16)), &len, sizeof(__u16)); 280 memcpy(skb_put(skb,sizeof(__u16)), &appl, sizeof(__u16)); 281 memcpy(skb_put(skb,sizeof(__u8)), &_command, sizeof(_command)); 282 memcpy(skb_put(skb,sizeof(__u8)), &_subcommand, sizeof(_subcommand)); 283 memcpy(skb_put(skb,sizeof(__u16)), &MessageNumber, sizeof(__u16)); 284 hycapi_send_message(ctrl, skb); 285 hycapi_applications[appl-1].ctrl_mask &= ~(1 << (ctrl->cnr-1)); 286} 287 288/****************************************************************** 289hycapi_release_appl 290 291Release the application from the internal list an remove it's 292registration at controller-level 293******************************************************************/ 294 295static void 296hycapi_release_appl(struct capi_ctr *ctrl, __u16 appl) 297{ 298 int chk; 299 300 chk = _hycapi_appCheck(appl, ctrl->cnr); 301 if(chk<0) { 302 printk(KERN_ERR "HYCAPI: Releasing invalid appl %d on controller %d\n", appl, ctrl->cnr); 303 return; 304 } 305 if(hycapi_applications[appl-1].listen_req[ctrl->cnr-1]) { 306 kfree_skb(hycapi_applications[appl-1].listen_req[ctrl->cnr-1]); 307 hycapi_applications[appl-1].listen_req[ctrl->cnr-1] = NULL; 308 } 309 if(chk == 1) 310 { 311 hycapi_release_internal(ctrl, appl); 312 } 313} 314 315 316/************************************************************** 317Kill a single controller. 318**************************************************************/ 319 320int hycapi_capi_release(hysdn_card *card) 321{ 322 hycapictrl_info *cinfo = card->hyctrlinfo; 323 struct capi_ctr *ctrl; 324#ifdef HYCAPI_PRINTFNAMES 325 printk(KERN_NOTICE "hycapi_capi_release\n"); 326#endif 327 if(cinfo) { 328 ctrl = &cinfo->capi_ctrl; 329 hycapi_remove_ctr(ctrl); 330 } 331 return 0; 332} 333 334/************************************************************** 335hycapi_capi_stop 336 337Stop CAPI-Output on a card. (e.g. during reboot) 338***************************************************************/ 339 340int hycapi_capi_stop(hysdn_card *card) 341{ 342 hycapictrl_info *cinfo = card->hyctrlinfo; 343 struct capi_ctr *ctrl; 344#ifdef HYCAPI_PRINTFNAMES 345 printk(KERN_NOTICE "hycapi_capi_stop\n"); 346#endif 347 if(cinfo) { 348 ctrl = &cinfo->capi_ctrl; 349/* ctrl->suspend_output(ctrl); */ 350 capi_ctr_reseted(ctrl); 351 } 352 return 0; 353} 354 355/*************************************************************** 356hycapi_send_message 357 358Send a message to the controller. 359 360Messages are parsed for their Command/Subcommand-type, and appropriate 361action's are performed. 362 363Note that we have to muck around with a 64Bit-DATA_REQ as there are 364firmware-releases that do not check the MsgLen-Indication! 365 366***************************************************************/ 367 368static u16 hycapi_send_message(struct capi_ctr *ctrl, struct sk_buff *skb) 369{ 370 __u16 appl_id; 371 int _len, _len2; 372 __u8 msghead[64]; 373 hycapictrl_info *cinfo = ctrl->driverdata; 374 u16 retval = CAPI_NOERROR; 375 376 appl_id = CAPIMSG_APPID(skb->data); 377 switch(_hycapi_appCheck(appl_id, ctrl->cnr)) 378 { 379 case 0: 380/* printk(KERN_INFO "Need to register\n"); */ 381 hycapi_register_internal(ctrl, 382 appl_id, 383 &(hycapi_applications[appl_id-1].rp)); 384 break; 385 case 1: 386 break; 387 default: 388 printk(KERN_ERR "HYCAPI: Controller mixup!\n"); 389 retval = CAPI_ILLAPPNR; 390 goto out; 391 } 392 switch(CAPIMSG_CMD(skb->data)) { 393 case CAPI_DISCONNECT_B3_RESP: 394 capilib_free_ncci(&cinfo->ncci_head, appl_id, 395 CAPIMSG_NCCI(skb->data)); 396 break; 397 case CAPI_DATA_B3_REQ: 398 _len = CAPIMSG_LEN(skb->data); 399 if (_len > 22) { 400 _len2 = _len - 22; 401 skb_copy_from_linear_data(skb, msghead, 22); 402 skb_copy_to_linear_data_offset(skb, _len2, 403 msghead, 22); 404 skb_pull(skb, _len2); 405 CAPIMSG_SETLEN(skb->data, 22); 406 retval = capilib_data_b3_req(&cinfo->ncci_head, 407 CAPIMSG_APPID(skb->data), 408 CAPIMSG_NCCI(skb->data), 409 CAPIMSG_MSGID(skb->data)); 410 } 411 break; 412 case CAPI_LISTEN_REQ: 413 if(hycapi_applications[appl_id-1].listen_req[ctrl->cnr-1]) 414 { 415 kfree_skb(hycapi_applications[appl_id-1].listen_req[ctrl->cnr-1]); 416 hycapi_applications[appl_id-1].listen_req[ctrl->cnr-1] = NULL; 417 } 418 if (!(hycapi_applications[appl_id-1].listen_req[ctrl->cnr-1] = skb_copy(skb, GFP_ATOMIC))) 419 { 420 printk(KERN_ERR "HYSDN: memory squeeze in private_listen\n"); 421 } 422 break; 423 default: 424 break; 425 } 426 out: 427 if (retval == CAPI_NOERROR) 428 hycapi_sendmsg_internal(ctrl, skb); 429 else 430 dev_kfree_skb_any(skb); 431 432 return retval; 433} 434 435/********************************************************************* 436hycapi_read_proc 437 438Informations provided in the /proc/capi-entries. 439 440*********************************************************************/ 441 442static int hycapi_read_proc(char *page, char **start, off_t off, 443 int count, int *eof, struct capi_ctr *ctrl) 444{ 445 hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata); 446 hysdn_card *card = cinfo->card; 447 int len = 0; 448 char *s; 449#ifdef HYCAPI_PRINTFNAMES 450 printk(KERN_NOTICE "hycapi_read_proc\n"); 451#endif 452 len += sprintf(page+len, "%-16s %s\n", "name", cinfo->cardname); 453 len += sprintf(page+len, "%-16s 0x%x\n", "io", card->iobase); 454 len += sprintf(page+len, "%-16s %d\n", "irq", card->irq); 455 456 switch (card->brdtype) { 457 case BD_PCCARD: s = "HYSDN Hycard"; break; 458 case BD_ERGO: s = "HYSDN Ergo2"; break; 459 case BD_METRO: s = "HYSDN Metro4"; break; 460 case BD_CHAMP2: s = "HYSDN Champ2"; break; 461 case BD_PLEXUS: s = "HYSDN Plexus30"; break; 462 default: s = "???"; break; 463 } 464 len += sprintf(page+len, "%-16s %s\n", "type", s); 465 if ((s = cinfo->version[VER_DRIVER]) != 0) 466 len += sprintf(page+len, "%-16s %s\n", "ver_driver", s); 467 if ((s = cinfo->version[VER_CARDTYPE]) != 0) 468 len += sprintf(page+len, "%-16s %s\n", "ver_cardtype", s); 469 if ((s = cinfo->version[VER_SERIAL]) != 0) 470 len += sprintf(page+len, "%-16s %s\n", "ver_serial", s); 471 472 len += sprintf(page+len, "%-16s %s\n", "cardname", cinfo->cardname); 473 474 if (off+count >= len) 475 *eof = 1; 476 if (len < off) 477 return 0; 478 *start = page + off; 479 return ((count < len-off) ? count : len-off); 480} 481 482/************************************************************** 483hycapi_load_firmware 484 485This does NOT load any firmware, but the callback somehow is needed 486on capi-interface registration. 487 488**************************************************************/ 489 490static int hycapi_load_firmware(struct capi_ctr *ctrl, capiloaddata *data) 491{ 492#ifdef HYCAPI_PRINTFNAMES 493 printk(KERN_NOTICE "hycapi_load_firmware\n"); 494#endif 495 return 0; 496} 497 498 499static char *hycapi_procinfo(struct capi_ctr *ctrl) 500{ 501 hycapictrl_info *cinfo = (hycapictrl_info *)(ctrl->driverdata); 502#ifdef HYCAPI_PRINTFNAMES 503 printk(KERN_NOTICE "hycapi_proc_info\n"); 504#endif 505 if (!cinfo) 506 return ""; 507 sprintf(cinfo->infobuf, "%s %s 0x%x %d %s", 508 cinfo->cardname[0] ? cinfo->cardname : "-", 509 cinfo->version[VER_DRIVER] ? cinfo->version[VER_DRIVER] : "-", 510 cinfo->card ? cinfo->card->iobase : 0x0, 511 cinfo->card ? cinfo->card->irq : 0, 512 hycapi_revision 513 ); 514 return cinfo->infobuf; 515} 516 517/****************************************************************** 518hycapi_rx_capipkt 519 520Receive a capi-message. 521 522All B3_DATA_IND are converted to 64K-extension compatible format. 523New nccis are created if necessary. 524*******************************************************************/ 525 526void 527hycapi_rx_capipkt(hysdn_card * card, unsigned char *buf, unsigned short len) 528{ 529 struct sk_buff *skb; 530 hycapictrl_info *cinfo = card->hyctrlinfo; 531 struct capi_ctr *ctrl; 532 __u16 ApplId; 533 __u16 MsgLen, info; 534 __u16 len2, CapiCmd; 535 __u32 CP64[2] = {0,0}; 536#ifdef HYCAPI_PRINTFNAMES 537 printk(KERN_NOTICE "hycapi_rx_capipkt\n"); 538#endif 539 if(!cinfo) { 540 return; 541 } 542 ctrl = &cinfo->capi_ctrl; 543 if(len < CAPI_MSG_BASELEN) { 544 printk(KERN_ERR "HYSDN Card%d: invalid CAPI-message, lenght %d!\n", 545 card->myid, len); 546 return; 547 } 548 MsgLen = CAPIMSG_LEN(buf); 549 ApplId = CAPIMSG_APPID(buf); 550 CapiCmd = CAPIMSG_CMD(buf); 551 552 if((CapiCmd == CAPI_DATA_B3_IND) && (MsgLen < 30)) { 553 len2 = len + (30 - MsgLen); 554 if (!(skb = alloc_skb(len2, GFP_ATOMIC))) { 555 printk(KERN_ERR "HYSDN Card%d: incoming packet dropped\n", 556 card->myid); 557 return; 558 } 559 memcpy(skb_put(skb, MsgLen), buf, MsgLen); 560 memcpy(skb_put(skb, 2*sizeof(__u32)), CP64, 2* sizeof(__u32)); 561 memcpy(skb_put(skb, len - MsgLen), buf + MsgLen, 562 len - MsgLen); 563 CAPIMSG_SETLEN(skb->data, 30); 564 } else { 565 if (!(skb = alloc_skb(len, GFP_ATOMIC))) { 566 printk(KERN_ERR "HYSDN Card%d: incoming packet dropped\n", 567 card->myid); 568 return; 569 } 570 memcpy(skb_put(skb, len), buf, len); 571 } 572 switch(CAPIMSG_CMD(skb->data)) 573 { 574 case CAPI_CONNECT_B3_CONF: 575/* Check info-field for error-indication: */ 576 info = CAPIMSG_U16(skb->data, 12); 577 switch(info) 578 { 579 case 0: 580 capilib_new_ncci(&cinfo->ncci_head, ApplId, CAPIMSG_NCCI(skb->data), 581 hycapi_applications[ApplId-1].rp.datablkcnt); 582 583 break; 584 case 0x0001: 585 printk(KERN_ERR "HYSDN Card%d: NCPI not supported by current " 586 "protocol. NCPI ignored.\n", card->myid); 587 break; 588 case 0x2001: 589 printk(KERN_ERR "HYSDN Card%d: Message not supported in" 590 " current state\n", card->myid); 591 break; 592 case 0x2002: 593 printk(KERN_ERR "HYSDN Card%d: invalid PLCI\n", card->myid); 594 break; 595 case 0x2004: 596 printk(KERN_ERR "HYSDN Card%d: out of NCCI\n", card->myid); 597 break; 598 case 0x3008: 599 printk(KERN_ERR "HYSDN Card%d: NCPI not supported\n", 600 card->myid); 601 break; 602 default: 603 printk(KERN_ERR "HYSDN Card%d: Info in CONNECT_B3_CONF: %d\n", 604 card->myid, info); 605 break; 606 } 607 break; 608 case CAPI_CONNECT_B3_IND: 609 capilib_new_ncci(&cinfo->ncci_head, ApplId, 610 CAPIMSG_NCCI(skb->data), 611 hycapi_applications[ApplId-1].rp.datablkcnt); 612 break; 613 case CAPI_DATA_B3_CONF: 614 capilib_data_b3_conf(&cinfo->ncci_head, ApplId, 615 CAPIMSG_NCCI(skb->data), 616 CAPIMSG_MSGID(skb->data)); 617 break; 618 default: 619 break; 620 } 621 capi_ctr_handle_message(ctrl, ApplId, skb); 622} 623 624/****************************************************************** 625hycapi_tx_capiack 626 627Internally acknowledge a msg sent. This will remove the msg from the 628internal queue. 629 630*******************************************************************/ 631 632void hycapi_tx_capiack(hysdn_card * card) 633{ 634 hycapictrl_info *cinfo = card->hyctrlinfo; 635#ifdef HYCAPI_PRINTFNAMES 636 printk(KERN_NOTICE "hycapi_tx_capiack\n"); 637#endif 638 if(!cinfo) { 639 return; 640 } 641 spin_lock_irq(&cinfo->lock); 642 kfree_skb(cinfo->skbs[cinfo->out_idx]); /* free skb */ 643 cinfo->skbs[cinfo->out_idx++] = NULL; 644 if (cinfo->out_idx >= HYSDN_MAX_CAPI_SKB) 645 cinfo->out_idx = 0; /* wrap around */ 646 647 if (cinfo->sk_count-- == HYSDN_MAX_CAPI_SKB) /* dec usage count */ 648 capi_ctr_resume_output(&cinfo->capi_ctrl); 649 spin_unlock_irq(&cinfo->lock); 650} 651 652/*************************************************************** 653hycapi_tx_capiget(hysdn_card *card) 654 655This is called when polling for messages to SEND. 656 657****************************************************************/ 658 659struct sk_buff * 660hycapi_tx_capiget(hysdn_card *card) 661{ 662 hycapictrl_info *cinfo = card->hyctrlinfo; 663 if(!cinfo) { 664 return (struct sk_buff *)NULL; 665 } 666 if (!cinfo->sk_count) 667 return (struct sk_buff *)NULL; /* nothing available */ 668 669 return (cinfo->skbs[cinfo->out_idx]); /* next packet to send */ 670} 671 672 673/********************************************************** 674int hycapi_init() 675 676attach the capi-driver to the kernel-capi. 677 678***********************************************************/ 679 680int hycapi_init(void) 681{ 682 int i; 683 for(i=0;i<CAPI_MAXAPPL;i++) { 684 memset(&(hycapi_applications[i]), 0, sizeof(hycapi_appl)); 685 } 686 return(0); 687} 688 689/************************************************************** 690hycapi_cleanup(void) 691 692detach the capi-driver to the kernel-capi. Actually this should 693free some more ressources. Do that later. 694**************************************************************/ 695 696void 697hycapi_cleanup(void) 698{ 699} 700 701/******************************************************************** 702hycapi_capi_create(hysdn_card *card) 703 704Attach the card with its capi-ctrl. 705*********************************************************************/ 706 707static void hycapi_fill_profile(hysdn_card *card) 708{ 709 hycapictrl_info *cinfo = NULL; 710 struct capi_ctr *ctrl = NULL; 711 cinfo = card->hyctrlinfo; 712 if(!cinfo) return; 713 ctrl = &cinfo->capi_ctrl; 714 strcpy(ctrl->manu, "Hypercope"); 715 ctrl->version.majorversion = 2; 716 ctrl->version.minorversion = 0; 717 ctrl->version.majormanuversion = 3; 718 ctrl->version.minormanuversion = 2; 719 ctrl->profile.ncontroller = card->myid; 720 ctrl->profile.nbchannel = card->bchans; 721 ctrl->profile.goptions = GLOBAL_OPTION_INTERNAL_CONTROLLER | 722 GLOBAL_OPTION_B_CHANNEL_OPERATION; 723 ctrl->profile.support1 = B1_PROT_64KBIT_HDLC | 724 (card->faxchans ? B1_PROT_T30 : 0) | 725 B1_PROT_64KBIT_TRANSPARENT; 726 ctrl->profile.support2 = B2_PROT_ISO7776 | 727 (card->faxchans ? B2_PROT_T30 : 0) | 728 B2_PROT_TRANSPARENT; 729 ctrl->profile.support3 = B3_PROT_TRANSPARENT | 730 B3_PROT_T90NL | 731 (card->faxchans ? B3_PROT_T30 : 0) | 732 (card->faxchans ? B3_PROT_T30EXT : 0) | 733 B3_PROT_ISO8208; 734} 735 736int 737hycapi_capi_create(hysdn_card *card) 738{ 739 hycapictrl_info *cinfo = NULL; 740 struct capi_ctr *ctrl = NULL; 741 int retval; 742#ifdef HYCAPI_PRINTFNAMES 743 printk(KERN_NOTICE "hycapi_capi_create\n"); 744#endif 745 if((hycapi_enable & (1 << card->myid)) == 0) { 746 return 1; 747 } 748 if (!card->hyctrlinfo) { 749 cinfo = kzalloc(sizeof(hycapictrl_info), GFP_ATOMIC); 750 if (!cinfo) { 751 printk(KERN_WARNING "HYSDN: no memory for capi-ctrl.\n"); 752 return -ENOMEM; 753 } 754 card->hyctrlinfo = cinfo; 755 cinfo->card = card; 756 spin_lock_init(&cinfo->lock); 757 INIT_LIST_HEAD(&cinfo->ncci_head); 758 759 switch (card->brdtype) { 760 case BD_PCCARD: strcpy(cinfo->cardname,"HYSDN Hycard"); break; 761 case BD_ERGO: strcpy(cinfo->cardname,"HYSDN Ergo2"); break; 762 case BD_METRO: strcpy(cinfo->cardname,"HYSDN Metro4"); break; 763 case BD_CHAMP2: strcpy(cinfo->cardname,"HYSDN Champ2"); break; 764 case BD_PLEXUS: strcpy(cinfo->cardname,"HYSDN Plexus30"); break; 765 default: strcpy(cinfo->cardname,"HYSDN ???"); break; 766 } 767 768 ctrl = &cinfo->capi_ctrl; 769 ctrl->driver_name = "hycapi"; 770 ctrl->driverdata = cinfo; 771 ctrl->register_appl = hycapi_register_appl; 772 ctrl->release_appl = hycapi_release_appl; 773 ctrl->send_message = hycapi_send_message; 774 ctrl->load_firmware = hycapi_load_firmware; 775 ctrl->reset_ctr = hycapi_reset_ctr; 776 ctrl->procinfo = hycapi_procinfo; 777 ctrl->ctr_read_proc = hycapi_read_proc; 778 strcpy(ctrl->name, cinfo->cardname); 779 ctrl->owner = THIS_MODULE; 780 781 retval = attach_capi_ctr(ctrl); 782 if (retval) { 783 printk(KERN_ERR "hycapi: attach controller failed.\n"); 784 return -EBUSY; 785 } 786 /* fill in the blanks: */ 787 hycapi_fill_profile(card); 788 capi_ctr_ready(ctrl); 789 } else { 790 /* resume output on stopped ctrl */ 791 ctrl = &card->hyctrlinfo->capi_ctrl; 792 hycapi_fill_profile(card); 793 capi_ctr_ready(ctrl); 794 hycapi_restart_internal(ctrl); 795/* ctrl->resume_output(ctrl); */ 796 } 797 return 0; 798} 799