root/drivers/isdn/icn/icn.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. icn_new_buf
  2. icn_free_queue
  3. icn_shiftout
  4. icn_map_channel
  5. icn_lock_channel
  6. icn_release_channel
  7. icn_trymaplock_channel
  8. icn_maprelease_channel
  9. icn_pollbchan_receive
  10. icn_pollbchan_send
  11. icn_pollbchan
  12. icn_pollit
  13. icn_pollcard
  14. icn_sendbuf
  15. icn_check_loader
  16. icn_loadboot
  17. icn_loadproto
  18. icn_readstatus
  19. icn_writecmd
  20. icn_stopdriver
  21. my_atoi
  22. icn_command
  23. if_command1
  24. if_command2
  25. if_writecmd1
  26. if_writecmd2
  27. if_readstatus1
  28. if_readstatus2
  29. if_sendbuf1
  30. if_sendbuf2
  31. icn_setup
  32. icn_init
  33. cleanup_module

   1 /* $Id icn.c,v 1.15 1996/01/10 20:57:39 fritz Exp fritz $
   2  *
   3  * ISDN low-level module for the ICN active ISDN-Card.
   4  *
   5  * Copyright 1994,95,96 by Fritz Elfert (fritz@wuemaus.franken.de)
   6  *
   7  * This program is free software; you can redistribute it and/or modify
   8  * it under the terms of the GNU General Public License as published by
   9  * the Free Software Foundation; either version 2, or (at your option)
  10  * any later version.
  11  *
  12  * This program is distributed in the hope that it will be useful,
  13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15  * GNU General Public License for more details.
  16  *
  17  * You should have received a copy of the GNU General Public License
  18  * along with this program; if not, write to the Free Software
  19  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  20  *
  21  * $Log: icn.c,v $
  22  * Revision 1.18  1996/04/20 16:50:26  fritz
  23  * Fixed status-buffer overrun.
  24  * Misc. typos
  25  *
  26  * Revision 1.17  1996/02/11 02:39:04  fritz
  27  * Increased Buffer for status-messages.
  28  * Removed conditionals for HDLC-firmware.
  29  *
  30  * Revision 1.16  1996/01/22 05:01:55  fritz
  31  * Revert to GPL.
  32  *
  33  * Revision 1.15  1996/01/10 20:57:39  fritz
  34  * Bugfix: Loading firmware twice caused the device stop working.
  35  *
  36  * Revision 1.14  1995/12/18  18:23:37  fritz
  37  * Support for ICN-2B Cards.
  38  * Change for supporting user-settable service-octet.
  39  *
  40  * Revision 1.13  1995/10/29  21:41:07  fritz
  41  * Added support for DriverId's, added Jan's patches for Kernel versions.
  42  *
  43  * Revision 1.12  1995/04/29  13:07:35  fritz
  44  * Added support for new Euro-ISDN-firmware
  45  *
  46  * Revision 1.11  1995/04/23  13:40:45  fritz
  47  * Added support for SPV's.
  48  * Changed Dial-Command to support MSN's on DSS1-Lines.
  49  *
  50  * Revision 1.10  1995/03/25  23:23:24  fritz
  51  * Changed configurable Ports, to allow settings for DIP-Switch Cardversions.
  52  *
  53  * Revision 1.9  1995/03/25  23:17:30  fritz
  54  * Fixed race-condition in pollbchan_send
  55  *
  56  * Revision 1.8  1995/03/15  12:49:44  fritz
  57  * Added support for SPV's
  58  * Split pollbchan_work for calling send-routine directly
  59  *
  60  * Revision 1.7  1995/02/20  03:48:03  fritz
  61  * Added support of new request_region-function.
  62  * Minor bugfixes.
  63  *
  64  * Revision 1.6  1995/01/31  15:48:45  fritz
  65  * Added Cause-Messages to be signaled to upper layers.
  66  * Added Revision-Info on load.
  67  *
  68  * Revision 1.5  1995/01/29  23:34:59  fritz
  69  * Added stopdriver() and appropriate calls.
  70  * Changed printk-statements to support loglevels.
  71  *
  72  * Revision 1.4  1995/01/09  07:40:46  fritz
  73  * Added GPL-Notice
  74  *
  75  * Revision 1.3  1995/01/04  05:15:18  fritz
  76  * Added undocumented "bootload-finished"-command in download-code
  77  * to satisfy some brain-damaged icn card-versions.
  78  *
  79  * Revision 1.2  1995/01/02  02:14:45  fritz
  80  * Misc Bugfixes
  81  *
  82  * Revision 1.1  1994/12/14  17:56:06  fritz
  83  * Initial revision
  84  *
  85  */
  86 
  87 #include "icn.h"
  88 
  89 
  90 
  91 /*
  92  * Verbose bootcode- and protocol-downloading.
  93  */
  94 #undef BOOT_DEBUG
  95 
  96 /*
  97  * Verbose Shmem-Mapping.
  98  */
  99 #undef MAP_DEBUG
 100 
 101 /* If defined, no bootcode- and protocol-downloading is supported and
 102  * you must use an external loader
 103  */
 104 #undef LOADEXTERN
 105 
 106 static char
 107 *revision = "$Revision: 1.18 $";
 108 
 109 static void icn_pollcard(unsigned long dummy);
 110 
 111 /* Try to allocate a new buffer, link it into queue. */
 112 static u_char *
 113  icn_new_buf(pqueue ** queue, int length)
     /* [previous][next][first][last][top][bottom][index][help] */
 114 {
 115         pqueue *p;
 116         pqueue *q;
 117 
 118         if ((p = *queue)) {
 119                 while (p) {
 120                         q = p;
 121                         p = (pqueue *) p->next;
 122                 }
 123                 p = (pqueue *) kmalloc(sizeof(pqueue) + length, GFP_ATOMIC);
 124                 q->next = (u_char *) p;
 125         } else
 126                 p = *queue = (pqueue *) kmalloc(sizeof(pqueue) + length, GFP_ATOMIC);
 127         if (p) {
 128                 p->size = sizeof(pqueue) + length;
 129                 p->length = length;
 130                 p->next = NULL;
 131                 p->rptr = p->buffer;
 132                 return p->buffer;
 133         } else {
 134                 return (u_char *) NULL;
 135         }
 136 }
 137 
 138 #ifdef MODULE
 139 static void icn_free_queue(pqueue ** queue)
     /* [previous][next][first][last][top][bottom][index][help] */
 140 {
 141         pqueue *p;
 142         pqueue *q;
 143 
 144         p = *queue;
 145         while (p) {
 146                 q = p;
 147                 p = (pqueue *) p->next;
 148                 kfree_s(q, q->size);
 149         }
 150         *queue = (pqueue *) 0;
 151 }
 152 #endif
 153 
 154 /* Put a value into a shift-register, highest bit first.
 155  * Parameters:
 156  *            port     = port for output (bit 0 is significant)
 157  *            val      = value to be output
 158  *            firstbit = Bit-Number of highest bit
 159  *            bitcount = Number of bits to output
 160  */
 161 static inline void icn_shiftout(unsigned short port,
     /* [previous][next][first][last][top][bottom][index][help] */
 162                      unsigned long val,
 163                      int firstbit,
 164                      int bitcount)
 165 {
 166 
 167         register u_char s;
 168         register u_char c;
 169 
 170         for (s = firstbit, c = bitcount; c > 0; s--, c--)
 171                 OUTB_P((u_char) ((val >> s) & 1) ? 0xff : 0, port);
 172 }
 173 
 174 /*
 175  * Map Cannel0 (Bank0/Bank8) or Channel1 (Bank4/Bank12)
 176  */
 177 static inline void icn_map_channel(int channel)
     /* [previous][next][first][last][top][bottom][index][help] */
 178 {
 179         static u_char chan2bank[] =
 180         {0, 4, 8, 12};
 181 
 182 #ifdef MAP_DEBUG
 183         printk(KERN_DEBUG "icn_map_channel %d %d\n", dev->channel, channel);
 184 #endif
 185         if (channel == dev->channel)
 186                 return;
 187         OUTB_P(0, ICN_MAPRAM);  /* Disable RAM          */
 188         icn_shiftout(ICN_BANK, chan2bank[channel], 3, 4);       /* Select Bank          */
 189         OUTB_P(0xff, ICN_MAPRAM);       /* Enable RAM           */
 190         dev->channel = channel;
 191 #ifdef MAP_DEBUG
 192         printk(KERN_DEBUG "icn_map_channel done\n");
 193 #endif
 194 }
 195 
 196 static inline int icn_lock_channel(int channel)
     /* [previous][next][first][last][top][bottom][index][help] */
 197 {
 198         register int retval;
 199         ulong flags;
 200 
 201 #ifdef MAP_DEBUG
 202         printk(KERN_DEBUG "icn_lock_channel %d\n", channel);
 203 #endif
 204         save_flags(flags);
 205         cli();
 206         if (dev->channel == channel) {
 207                 dev->chanlock++;
 208                 retval = 1;
 209 #ifdef MAP_DEBUG
 210                 printk(KERN_DEBUG "icn_lock_channel %d OK\n", channel);
 211 #endif
 212         } else {
 213                 retval = 0;
 214 #ifdef MAP_DEBUG
 215                 printk(KERN_DEBUG "icn_lock_channel %d FAILED, dc=%d\n", channel, dev->channel);
 216 #endif
 217         }
 218         restore_flags(flags);
 219         return retval;
 220 }
 221 
 222 static inline void icn_release_channel(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 223 {
 224         ulong flags;
 225 
 226 #ifdef MAP_DEBUG
 227         printk(KERN_DEBUG "icn_release_channel l=%d\n", dev->chanlock);
 228 #endif
 229         save_flags(flags);
 230         cli();
 231         if (dev->chanlock)
 232                 dev->chanlock--;
 233         restore_flags(flags);
 234 }
 235 
 236 static inline int icn_trymaplock_channel(int channel)
     /* [previous][next][first][last][top][bottom][index][help] */
 237 {
 238         ulong flags;
 239 
 240         save_flags(flags);
 241         cli();
 242 #ifdef MAP_DEBUG
 243         printk(KERN_DEBUG "trymaplock c=%d dc=%d l=%d\n", channel, dev->channel,
 244                dev->chanlock);
 245 #endif
 246         if ((!dev->chanlock) || (dev->channel == channel)) {
 247                 dev->chanlock++;
 248                 icn_map_channel(channel);
 249                 restore_flags(flags);
 250 #ifdef MAP_DEBUG
 251                 printk(KERN_DEBUG "trymaplock %d OK\n", channel);
 252 #endif
 253                 return 1;
 254         }
 255         restore_flags(flags);
 256 #ifdef MAP_DEBUG
 257         printk(KERN_DEBUG "trymaplock %d FAILED\n", channel);
 258 #endif
 259         return 0;
 260 }
 261 
 262 static inline void icn_maprelease_channel(int channel)
     /* [previous][next][first][last][top][bottom][index][help] */
 263 {
 264         ulong flags;
 265 
 266         save_flags(flags);
 267         cli();
 268 #ifdef MAP_DEBUG
 269         printk(KERN_DEBUG "map_release c=%d l=%d\n", channel, dev->chanlock);
 270 #endif
 271         if (dev->chanlock)
 272                 dev->chanlock--;
 273         if (!dev->chanlock)
 274                 icn_map_channel(channel);
 275         restore_flags(flags);
 276 }
 277 
 278 /* Get Data from the B-Channel, assemble fragmented packets and put them
 279  * into receive-queue. Wake up any B-Channel-reading processes.
 280  * This routine is called via timer-callback from pollbchan().
 281  * It schedules itself while any B-Channel is open.
 282  */
 283 
 284 #ifdef DEBUG_RCVCALLBACK
 285 static int max_pending[2] =
 286 {0, 0};
 287 #endif
 288 
 289 static void icn_pollbchan_receive(int channel, icn_dev * dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 290 {
 291         int mch = channel + ((dev->secondhalf) ? 2 : 0);
 292         int eflag;
 293         int cnt;
 294         int flags;
 295 #ifdef DEBUG_RCVCALLBACK
 296         int rcv_pending1;
 297         int rcv_pending2;
 298         int akt_pending;
 299 #endif
 300 
 301         if (icn_trymaplock_channel(mch)) {
 302                 while (rbavl) {
 303                         cnt = rbuf_l;
 304                         if ((dev->rcvidx[channel] + cnt) > 4000) {
 305                                 printk(KERN_WARNING "icn: bogus packet on ch%d, dropping.\n",
 306                                        channel + 1);
 307                                 dev->rcvidx[channel] = 0;
 308                                 eflag = 0;
 309                         } else {
 310                                 memcpy(&dev->rcvbuf[channel][dev->rcvidx[channel]], rbuf_d, cnt);
 311                                 dev->rcvidx[channel] += cnt;
 312                                 eflag = rbuf_f;
 313                         }
 314                         rbnext;
 315                         icn_maprelease_channel(mch & 2);
 316                         if (!eflag) {
 317                                 save_flags(flags);
 318                                 cli();
 319 #ifdef DEBUG_RCVCALLBACK
 320                                 rcv_pending1 =
 321                                     (dev->shmem->data_control.ecnr > dev->shmem->data_control.ecns) ?
 322                                     0xf - dev->shmem->data_control.ecnr + dev->shmem->data_control.ecns :
 323                                     dev->shmem->data_control.ecns - dev->shmem->data_control.ecnr;
 324 #endif
 325                                 dev->interface.rcvcallb(dev->myid, channel, dev->rcvbuf[channel],
 326                                                    dev->rcvidx[channel]);
 327                                 dev->rcvidx[channel] = 0;
 328 #ifdef DEBUG_RCVCALLBACK
 329                                 rcv_pending2 =
 330                                     (dev->shmem->data_control.ecnr > dev->shmem->data_control.ecns) ?
 331                                     0xf - dev->shmem->data_control.ecnr + dev->shmem->data_control.ecns :
 332                                     dev->shmem->data_control.ecns - dev->shmem->data_control.ecnr;
 333                                 akt_pending = rcv_pending2 - rcv_pending1;
 334                                 if (akt_pending > max_pending[channel]) {
 335                                         max_pending[channel] = akt_pending;
 336                                         printk(KERN_DEBUG "ICN_DEBUG: pend: %d %d\n", max_pending[0], max_pending[1]);
 337                                 }
 338 #endif
 339                                 restore_flags(flags);
 340                         }
 341                         if (!icn_trymaplock_channel(mch))
 342                                 break;
 343                 }
 344                 icn_maprelease_channel(mch & 2);
 345         }
 346 }
 347 
 348 /* Send data-packet to B-Channel, split it up into fragments of
 349  * ICN_FRAGSIZE length. If last fragment is sent out, signal
 350  * success to upper layers via statcallb with ISDN_STAT_BSENT argument.
 351  * This routine is called via timer-callback from pollbchan() or
 352  * directly from sendbuf().
 353  */
 354 
 355 static void icn_pollbchan_send(int channel, icn_dev * dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 356 {
 357         int mch = channel + ((dev->secondhalf) ? 2 : 0);
 358         int eflag = 0;
 359         int cnt;
 360         int left;
 361         int flags;
 362         pqueue *p;
 363         isdn_ctrl cmd;
 364 
 365         if (!dev->sndcount[channel])
 366                 return;
 367         if (icn_trymaplock_channel(mch)) {
 368                 while (sbfree && dev->sndcount[channel]) {
 369                         left = dev->spqueue[channel]->length;
 370                         cnt =
 371                             (sbuf_l =
 372                              (left > ICN_FRAGSIZE) ? ((sbuf_f = 0xff), ICN_FRAGSIZE) : ((sbuf_f = 0), left));
 373                         memcpy(sbuf_d, dev->spqueue[channel]->rptr, cnt);
 374                         sbnext; /* switch to next buffer        */
 375                         icn_maprelease_channel(mch & 2);
 376                         dev->spqueue[channel]->rptr += cnt;
 377                         eflag = ((dev->spqueue[channel]->length -= cnt) == 0);
 378                         save_flags(flags);
 379                         cli();
 380                         p = dev->spqueue[channel];
 381                         dev->sndcount[channel] -= cnt;
 382                         if (eflag)
 383                                 dev->spqueue[channel] = (pqueue *) dev->spqueue[channel]->next;
 384                         restore_flags(flags);
 385                         if (eflag) {
 386                                 kfree_s(p, p->size);
 387                                 cmd.command = ISDN_STAT_BSENT;
 388                                 cmd.driver = dev->myid;
 389                                 cmd.arg = channel;
 390                                 dev->interface.statcallb(&cmd);
 391                         }
 392                         if (!icn_trymaplock_channel(mch))
 393                                 break;
 394                 }
 395                 icn_maprelease_channel(mch & 2);
 396         }
 397 }
 398 
 399 /* Send/Receive Data to/from the B-Channel.
 400  * This routine is called via timer-callback.
 401  * It schedules itself while any B-Channel is open.
 402  */
 403 
 404 static void icn_pollbchan(unsigned long dummy)
     /* [previous][next][first][last][top][bottom][index][help] */
 405 {
 406         unsigned long flags;
 407 
 408         dev->flags |= ICN_FLAGS_RBTIMER;
 409         if (dev->flags & ICN_FLAGS_B1ACTIVE) {
 410                 icn_pollbchan_receive(0, dev);
 411                 icn_pollbchan_send(0, dev);
 412         }
 413         if (dev->flags & ICN_FLAGS_B2ACTIVE) {
 414                 icn_pollbchan_receive(1, dev);
 415                 icn_pollbchan_send(1, dev);
 416         }
 417         if (dev->doubleS0) {
 418                 if (dev2->flags & ICN_FLAGS_B1ACTIVE) {
 419                         icn_pollbchan_receive(0, dev2);
 420                         icn_pollbchan_send(0, dev2);
 421                 }
 422                 if (dev2->flags & ICN_FLAGS_B2ACTIVE) {
 423                         icn_pollbchan_receive(1, dev2);
 424                         icn_pollbchan_send(1, dev2);
 425                 }
 426         }
 427         if (dev->flags & (ICN_FLAGS_B1ACTIVE | ICN_FLAGS_B2ACTIVE)) {
 428                 /* schedule b-channel polling again */
 429                 save_flags(flags);
 430                 cli();
 431                 del_timer(&dev->rb_timer);
 432                 dev->rb_timer.function = icn_pollbchan;
 433                 dev->rb_timer.expires = jiffies + ICN_TIMER_BCREAD;
 434                 add_timer(&dev->rb_timer);
 435                 restore_flags(flags);
 436         } else
 437                 dev->flags &= ~ICN_FLAGS_RBTIMER;
 438         if (dev->doubleS0) {
 439                 if (dev2->flags & (ICN_FLAGS_B1ACTIVE | ICN_FLAGS_B2ACTIVE)) {
 440                         /* schedule b-channel polling again */
 441                         save_flags(flags);
 442                         cli();
 443                         del_timer(&dev2->rb_timer);
 444                         dev2->rb_timer.function = icn_pollbchan;
 445                         dev2->rb_timer.expires = jiffies + ICN_TIMER_BCREAD;
 446                         add_timer(&dev2->rb_timer);
 447                         restore_flags(flags);
 448                 } else
 449                         dev2->flags &= ~ICN_FLAGS_RBTIMER;
 450         }
 451 }
 452 
 453 static void icn_pollit(icn_dev * dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 454 {
 455         int mch = dev->secondhalf ? 2 : 0;
 456         int avail = 0;
 457         int dflag = 0;
 458         int left;
 459         u_char c;
 460         int ch;
 461         int flags;
 462         int i;
 463         u_char *p;
 464         isdn_ctrl cmd;
 465 
 466         if (icn_trymaplock_channel(mch)) {
 467                 avail = msg_avail;
 468                 for (left = avail, i = msg_o; left > 0; i++, left--) {
 469                         c = dev->shmem->comm_buffers.iopc_buf[i & 0xff];
 470                         save_flags(flags);
 471                         cli();
 472                         *dev->msg_buf_write++ = (c == 0xff) ? '\n' : c;
 473                         if (dev->msg_buf_write == dev->msg_buf_read) {
 474                                 if (++dev->msg_buf_read > dev->msg_buf_end)
 475                                         dev->msg_buf_read = dev->msg_buf;
 476                         }
 477                         if (dev->msg_buf_write > dev->msg_buf_end)
 478                                 dev->msg_buf_write = dev->msg_buf;
 479                         restore_flags(flags);
 480                         if (c == 0xff) {
 481                                 dev->imsg[dev->iptr] = 0;
 482                                 dev->iptr = 0;
 483                                 if (dev->imsg[0] == '0' && dev->imsg[1] >= '0' &&
 484                                     dev->imsg[1] <= '2' && dev->imsg[2] == ';') {
 485                                         ch = dev->imsg[1] - '0';
 486                                         p = &dev->imsg[3];
 487                                         if (!strncmp(p, "BCON_", 5)) {
 488                                                 switch (ch) {
 489                                                 case 1:
 490                                                         dev->flags |= ICN_FLAGS_B1ACTIVE;
 491                                                         break;
 492                                                 case 2:
 493                                                         dev->flags |= ICN_FLAGS_B2ACTIVE;
 494                                                         break;
 495                                                 }
 496                                                 cmd.command = ISDN_STAT_BCONN;
 497                                                 cmd.driver = dev->myid;
 498                                                 cmd.arg = ch - 1;
 499                                                 dev->interface.statcallb(&cmd);
 500                                                 continue;
 501                                         }
 502                                         if (!strncmp(p, "TEI OK", 6)) {
 503                                                 cmd.command = ISDN_STAT_RUN;
 504                                                 cmd.driver = dev->myid;
 505                                                 cmd.arg = ch - 1;
 506                                                 dev->interface.statcallb(&cmd);
 507                                                 continue;
 508                                         }
 509                                         if (!strncmp(p, "BDIS_", 5)) {
 510                                                 switch (ch) {
 511                                                 case 1:
 512                                                         dev->flags &= ~ICN_FLAGS_B1ACTIVE;
 513                                                         dflag |= 1;
 514                                                         break;
 515                                                 case 2:
 516                                                         dev->flags &= ~ICN_FLAGS_B2ACTIVE;
 517                                                         dflag |= 2;
 518                                                         break;
 519                                                 }
 520                                                 cmd.command = ISDN_STAT_BHUP;
 521                                                 cmd.arg = ch - 1;
 522                                                 cmd.driver = dev->myid;
 523                                                 dev->interface.statcallb(&cmd);
 524                                                 continue;
 525                                         }
 526                                         if (!strncmp(p, "DCON_", 5)) {
 527                                                 cmd.command = ISDN_STAT_DCONN;
 528                                                 cmd.arg = ch - 1;
 529                                                 cmd.driver = dev->myid;
 530                                                 dev->interface.statcallb(&cmd);
 531                                                 continue;
 532                                         }
 533                                         if (!strncmp(p, "DDIS_", 5)) {
 534                                                 cmd.command = ISDN_STAT_DHUP;
 535                                                 cmd.arg = ch - 1;
 536                                                 cmd.driver = dev->myid;
 537                                                 dev->interface.statcallb(&cmd);
 538                                                 continue;
 539                                         }
 540                                         if (!strncmp(p, "E_L1: ACT FAIL", 14)) {
 541                                                 cmd.command = ISDN_STAT_BHUP;
 542                                                 cmd.arg = 0;
 543                                                 cmd.driver = dev->myid;
 544                                                 dev->interface.statcallb(&cmd);
 545                                                 cmd.command = ISDN_STAT_DHUP;
 546                                                 cmd.arg = 0;
 547                                                 cmd.driver = dev->myid;
 548                                                 dev->interface.statcallb(&cmd);
 549                                                 continue;
 550                                         }
 551                                         if (!strncmp(p, "CIF", 3)) {
 552                                                 cmd.command = ISDN_STAT_CINF;
 553                                                 cmd.arg = ch - 1;
 554                                                 strncpy(cmd.num, p + 3, sizeof(cmd.num) - 1);
 555                                                 cmd.driver = dev->myid;
 556                                                 dev->interface.statcallb(&cmd);
 557                                                 continue;
 558                                         }
 559                                         if (!strncmp(p, "CAU", 3)) {
 560                                                 cmd.command = ISDN_STAT_CAUSE;
 561                                                 cmd.arg = ch - 1;
 562                                                 strncpy(cmd.num, p + 3, sizeof(cmd.num) - 1);
 563                                                 cmd.driver = dev->myid;
 564                                                 dev->interface.statcallb(&cmd);
 565                                                 continue;
 566                                         }
 567                                         if (!strncmp(p, "DCAL_I", 6)) {
 568                                                 cmd.command = ISDN_STAT_ICALL;
 569                                                 cmd.driver = dev->myid;
 570                                                 cmd.arg = ch - 1;
 571                                                 strncpy(cmd.num, p + 6, sizeof(cmd.num) - 1);
 572                                                 dev->interface.statcallb(&cmd);
 573                                                 continue;
 574                                         }
 575                                         if (!strncmp(p, "FCALL", 5)) {
 576                                                 cmd.command = ISDN_STAT_ICALL;
 577                                                 cmd.driver = dev->myid;
 578                                                 cmd.arg = ch - 1;
 579                                                 strcpy(cmd.num, "LEASED,07,00,1");
 580                                                 dev->interface.statcallb(&cmd);
 581                                                 continue;
 582                                         }
 583                                         if (!strncmp(p, "DSCA_I", 6)) {
 584                                                 cmd.command = ISDN_STAT_ICALL;
 585                                                 cmd.driver = dev->myid;
 586                                                 cmd.arg = ch - 1;
 587                                                 strncpy(cmd.num, p + 6, sizeof(cmd.num) - 1);
 588                                                 dev->interface.statcallb(&cmd);
 589                                                 continue;
 590                                         }
 591                                         if (!strncmp(p, "NO D-CHAN", 9)) {
 592                                                 cmd.command = ISDN_STAT_NODCH;
 593                                                 cmd.driver = dev->myid;
 594                                                 cmd.arg = ch - 1;
 595                                                 strncpy(cmd.num, p + 6, sizeof(cmd.num) - 1);
 596                                                 dev->interface.statcallb(&cmd);
 597                                                 continue;
 598                                         }
 599                                 } else {
 600                                         p = dev->imsg;
 601                                         if (!strncmp(p, "DRV1.", 5)) {
 602                                                 printk(KERN_INFO "icn: %s\n",p);
 603                                                 if (!strncmp(p + 7, "TC", 2)) {
 604                                                         dev->ptype = ISDN_PTYPE_1TR6;
 605                                                         dev->interface.features |= ISDN_FEATURE_P_1TR6;
 606                                                         printk(KERN_INFO "icn: 1TR6-Protocol loaded and running\n");
 607                                                 }
 608                                                 if (!strncmp(p + 7, "EC", 2)) {
 609                                                         dev->ptype = ISDN_PTYPE_EURO;
 610                                                         dev->interface.features |= ISDN_FEATURE_P_EURO;
 611                                                         printk(KERN_INFO "icn: Euro-Protocol loaded and running\n");
 612                                                 }
 613                                                 continue;
 614                                         }
 615                                 }
 616                         } else {
 617                                 dev->imsg[dev->iptr] = c;
 618                                 if (dev->iptr < 59)
 619                                         dev->iptr++;
 620                         }
 621                 }
 622                 msg_o = (msg_o + avail) & 0xff;
 623                 icn_release_channel();
 624         }
 625         if (avail) {
 626                 cmd.command = ISDN_STAT_STAVAIL;
 627                 cmd.driver = dev->myid;
 628                 cmd.arg = avail;
 629                 dev->interface.statcallb(&cmd);
 630         }
 631         if (dflag & 1)
 632                 dev->interface.rcvcallb(dev->myid, 0, dev->rcvbuf[0], 0);
 633         if (dflag & 2)
 634                 dev->interface.rcvcallb(dev->myid, 1, dev->rcvbuf[1], 0);
 635         if (dev->flags & (ICN_FLAGS_B1ACTIVE | ICN_FLAGS_B2ACTIVE))
 636                 if (!(dev->flags & ICN_FLAGS_RBTIMER)) {
 637                         /* schedule b-channel polling */
 638                         dev->flags |= ICN_FLAGS_RBTIMER;
 639                         save_flags(flags);
 640                         cli();
 641                         del_timer(&dev->rb_timer);
 642                         dev->rb_timer.function = icn_pollbchan;
 643                         dev->rb_timer.expires = jiffies + ICN_TIMER_BCREAD;
 644                         add_timer(&dev->rb_timer);
 645                         restore_flags(flags);
 646                 }
 647 }
 648 
 649 /*
 650  * Check Statusqueue-Pointer from isdn-card.
 651  * If there are new status-replies from the interface, check
 652  * them against B-Channel-connects/disconnects and set flags accordingly.
 653  * Wake-Up any processes, who are reading the status-device.
 654  * If there are B-Channels open, initiate a timer-callback to
 655  * icn_pollbchan().
 656  * This routine is called periodically via timer.
 657  */
 658 
 659 static void icn_pollcard(unsigned long dummy)
     /* [previous][next][first][last][top][bottom][index][help] */
 660 {
 661         ulong flags;
 662 
 663         icn_pollit(dev);
 664         if (dev->doubleS0)
 665                 icn_pollit(dev2);
 666         /* schedule again */
 667         save_flags(flags);
 668         cli();
 669         del_timer(&dev->st_timer);
 670         dev->st_timer.function = icn_pollcard;
 671         dev->st_timer.expires = jiffies + ICN_TIMER_DCREAD;
 672         add_timer(&dev->st_timer);
 673         restore_flags(flags);
 674 }
 675 
 676 /* Send a packet to the transmit-buffers, handle fragmentation if necessary.
 677  * Parameters:
 678  *            channel = Number of B-channel
 679  *            buffer  = pointer to packet
 680  *            len     = size of packet (max 4000)
 681  *            dev     = pointer to device-struct
 682  *            user    = 1 = call from userproc, 0 = call from kernel
 683  * Return:
 684  *        Number of bytes transferred, -E??? on error
 685  */
 686 
 687 static int icn_sendbuf(int channel, const u_char * buffer, int len, int user, icn_dev * dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 688 {
 689         register u_char *p;
 690         int flags;
 691 
 692         if (len > 4000)
 693                 return -EINVAL;
 694         if (len) {
 695                 if (dev->sndcount[channel] > ICN_MAX_SQUEUE)
 696                         return 0;
 697                 save_flags(flags);
 698                 cli();
 699                 p = icn_new_buf(&dev->spqueue[channel], len);
 700                 if (!p) {
 701                         restore_flags(flags);
 702                         return 0;
 703                 }
 704                 if (user) {
 705                         memcpy_fromfs(p, buffer, len);
 706                 } else {
 707                         memcpy(p, buffer, len);
 708                 }
 709                 dev->sndcount[channel] += len;
 710                 icn_pollbchan_send(channel, dev);
 711                 restore_flags(flags);
 712         }
 713         return len;
 714 }
 715 
 716 #ifndef LOADEXTERN
 717 static int icn_check_loader(int cardnumber)
     /* [previous][next][first][last][top][bottom][index][help] */
 718 {
 719         int timer = 0;
 720 
 721         while (1) {
 722 #ifdef BOOT_DEBUG
 723                 printk(KERN_DEBUG "Loader %d ?\n", cardnumber);
 724 #endif
 725                 if (dev->shmem->data_control.scns ||
 726                     dev->shmem->data_control.scnr) {
 727                         if (timer++ > 5) {
 728                                 printk(KERN_WARNING "icn: Boot-Loader %d timed out.\n", cardnumber);
 729                                 icn_release_channel();
 730                                 return -EIO;
 731                         }
 732 #ifdef BOOT_DEBUG
 733                         printk(KERN_DEBUG "Loader %d TO?\n", cardnumber);
 734 #endif
 735                         current->state = TASK_INTERRUPTIBLE;
 736                         current->timeout = jiffies + ICN_BOOT_TIMEOUT1;
 737                         schedule();
 738                 } else {
 739 #ifdef BOOT_DEBUG
 740                         printk(KERN_DEBUG "Loader %d OK\n", cardnumber);
 741 #endif
 742                         icn_release_channel();
 743                         return 0;
 744                 }
 745         }
 746 }
 747 
 748 /* Load the boot-code into the interface-card's memory and start it.
 749  * Always called from user-process.
 750  * 
 751  * Parameters:
 752  *            buffer = pointer to packet
 753  * Return:
 754  *        0 if successfully loaded
 755  */
 756 
 757 #ifdef BOOT_DEBUG
 758 #define SLEEP(sec) { \
 759 int slsec = sec; \
 760   printk(KERN_DEBUG "SLEEP(%d)\n",slsec); \
 761   while (slsec) { \
 762     current->state = TASK_INTERRUPTIBLE; \
 763     current->timeout = jiffies + HZ; \
 764     schedule(); \
 765     slsec--; \
 766   } \
 767 }
 768 #else
 769 #define SLEEP(sec)
 770 #endif
 771 
 772 static int icn_loadboot(u_char * buffer, icn_dev * dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 773 {
 774         int ret;
 775         ulong flags;
 776 
 777 #ifdef BOOT_DEBUG
 778         printk(KERN_DEBUG "icn_loadboot called, buffaddr=%08lx\n", (ulong) buffer);
 779 #endif
 780         if ((ret = verify_area(VERIFY_READ, (void *) buffer, ICN_CODE_STAGE1)))
 781                 return ret;
 782         save_flags(flags);
 783         cli();
 784         if (!dev->rvalid) {
 785                 if (check_region(dev->port, ICN_PORTLEN)) {
 786                         printk(KERN_WARNING "icn: ports 0x%03x-0x%03x in use.\n", dev->port,
 787                                dev->port + ICN_PORTLEN);
 788                         restore_flags(flags);
 789                         return -EBUSY;
 790                 }
 791                 request_region(dev->port, ICN_PORTLEN, regname);
 792                 dev->rvalid = 1;
 793         }
 794         if (!dev->mvalid) {
 795                 if (check_shmem((ulong) dev->shmem, 0x4000)) {
 796                         printk(KERN_WARNING "icn: memory at 0x%08lx in use.\n", (ulong) dev->shmem);
 797                         restore_flags(flags);
 798                         return -EBUSY;
 799                 }
 800                 request_shmem((ulong) dev->shmem, 0x4000, regname);
 801                 dev->mvalid = 1;
 802         }
 803         restore_flags(flags);
 804         OUTB_P(0, ICN_RUN);     /* Reset Controller */
 805         OUTB_P(0, ICN_MAPRAM);  /* Disable RAM      */
 806         icn_shiftout(ICN_CFG, 0x0f, 3, 4);      /* Windowsize= 16k */
 807         icn_shiftout(ICN_CFG, (unsigned long) dev->shmem, 23, 10);      /* Set RAM-Addr.   */
 808 #ifdef BOOT_DEBUG
 809         printk(KERN_DEBUG "shmem=%08lx\n", (ulong) dev->shmem);
 810 #endif
 811         SLEEP(1);
 812         save_flags(flags);
 813         cli();
 814         dev->channel = 1;       /* Force Mapping   */
 815 #ifdef BOOT_DEBUG
 816         printk(KERN_DEBUG "Map Bank 0\n");
 817 #endif
 818         icn_map_channel(0);             /* Select Bank 0   */
 819         icn_lock_channel(0);    /* Lock Bank 0     */
 820         restore_flags(flags);
 821         SLEEP(1);
 822         memcpy_fromfs(dev->shmem, buffer, ICN_CODE_STAGE1);     /* Copy code       */
 823 #ifdef BOOT_DEBUG
 824         printk(KERN_DEBUG "Bootloader transfered\n");
 825 #endif
 826         if (dev->doubleS0) {
 827                 SLEEP(1);
 828                 save_flags(flags);
 829                 cli();
 830                 icn_release_channel();
 831 #ifdef BOOT_DEBUG
 832                 printk(KERN_DEBUG "Map Bank 8\n");
 833 #endif
 834                 icn_map_channel(2);     /* Select Bank 8   */
 835                 icn_lock_channel(2);    /* Lock Bank 8     */
 836                 restore_flags(flags);
 837                 SLEEP(1);
 838                 memcpy_fromfs(dev->shmem, buffer, ICN_CODE_STAGE1);     /* Copy code       */
 839 #ifdef BOOT_DEBUG
 840                 printk(KERN_DEBUG "Bootloader transfered\n");
 841 #endif
 842         }
 843         SLEEP(1);
 844         OUTB_P(0xff, ICN_RUN);  /* Start Boot-Code */
 845         if ((ret = icn_check_loader(dev->doubleS0 ? 2 : 1)))
 846                 return ret;
 847         if (!dev->doubleS0)
 848                 return 0;
 849         /* reached only, if we have a Double-S0-Card */
 850         save_flags(flags);
 851         cli();
 852 #ifdef BOOT_DEBUG
 853         printk(KERN_DEBUG "Map Bank 0\n");
 854 #endif
 855         icn_map_channel(0);             /* Select Bank 0   */
 856         icn_lock_channel(0);    /* Lock Bank 0     */
 857         restore_flags(flags);
 858         SLEEP(1);
 859         return (icn_check_loader(1));
 860 }
 861 
 862 static int icn_loadproto(u_char * buffer, icn_dev * ldev)
     /* [previous][next][first][last][top][bottom][index][help] */
 863 {
 864         register u_char *p = buffer;
 865         uint left = ICN_CODE_STAGE2;
 866         uint cnt;
 867         int timer;
 868         int ret;
 869         unsigned long flags;
 870 
 871 #ifdef BOOT_DEBUG
 872         printk(KERN_DEBUG "icn_loadproto called\n");
 873 #endif
 874         if ((ret = verify_area(VERIFY_READ, (void *) buffer, ICN_CODE_STAGE2)))
 875                 return ret;
 876         timer = 0;
 877         save_flags(flags);
 878         cli();
 879         if (ldev->secondhalf) {
 880                 icn_map_channel(2);
 881                 icn_lock_channel(2);
 882         } else {
 883                 icn_map_channel(0);
 884                 icn_lock_channel(0);
 885         }
 886         restore_flags(flags);
 887         while (left) {
 888                 if (sbfree) {   /* If there is a free buffer...  */
 889                         cnt = MIN(256, left);
 890                         memcpy_fromfs(&sbuf_l, p, cnt);         /* copy data                     */
 891                         sbnext; /* switch to next buffer         */
 892                         p += cnt;
 893                         left -= cnt;
 894                         timer = 0;
 895                 } else {
 896 #ifdef BOOT_DEBUG
 897                         printk(KERN_DEBUG "boot 2 !sbfree\n");
 898 #endif
 899                         if (timer++ > 5) {
 900                                 icn_maprelease_channel(0);
 901                                 return -EIO;
 902                         }
 903                         current->state = TASK_INTERRUPTIBLE;
 904                         current->timeout = jiffies + 10;
 905                         schedule();
 906                 }
 907         }
 908         sbuf_n = 0x20;
 909         timer = 0;
 910         while (1) {
 911                 if (cmd_o || cmd_i) {
 912 #ifdef BOOT_DEBUG
 913                         printk(KERN_DEBUG "Proto?\n");
 914 #endif
 915                         if (timer++ > 5) {
 916                                 printk(KERN_WARNING "icn: Protocol timed out.\n");
 917 #ifdef BOOT_DEBUG
 918                                 printk(KERN_DEBUG "Proto TO!\n");
 919 #endif
 920                                 icn_maprelease_channel(0);
 921                                 return -EIO;
 922                         }
 923 #ifdef BOOT_DEBUG
 924                         printk(KERN_DEBUG "Proto TO?\n");
 925 #endif
 926                         current->state = TASK_INTERRUPTIBLE;
 927                         current->timeout = jiffies + ICN_BOOT_TIMEOUT1;
 928                         schedule();
 929                 } else {
 930                         if ((ldev->secondhalf) || (!dev->doubleS0)) {
 931                                 save_flags(flags);
 932                                 cli();
 933 #ifdef BOOT_DEBUG
 934                                 printk(KERN_DEBUG "Proto loaded, install poll-timer %d\n",
 935                                        ldev->secondhalf);
 936 #endif
 937                                 init_timer(&dev->st_timer);
 938                                 dev->st_timer.expires = jiffies + ICN_TIMER_DCREAD;
 939                                 dev->st_timer.function = icn_pollcard;
 940                                 add_timer(&dev->st_timer);
 941                                 restore_flags(flags);
 942                         }
 943                         icn_maprelease_channel(0);
 944                         return 0;
 945                 }
 946         }
 947 }
 948 #endif                          /* !LOADEXTERN */
 949 
 950 /* Read the Status-replies from the Interface */
 951 static int icn_readstatus(u_char * buf, int len, int user, icn_dev * dev)
     /* [previous][next][first][last][top][bottom][index][help] */
 952 {
 953         int count;
 954         u_char *p;
 955 
 956         for (p = buf, count = 0; count < len; p++, count++) {
 957                 if (dev->msg_buf_read == dev->msg_buf_write)
 958                         return count;
 959                 if (user)
 960                         put_fs_byte(*dev->msg_buf_read++, p);
 961                 else
 962                         *p = *dev->msg_buf_read++;
 963                 if (dev->msg_buf_read > dev->msg_buf_end)
 964                         dev->msg_buf_read = dev->msg_buf;
 965         }
 966         return count;
 967 }
 968 
 969 /* Put command-strings into the command-queue of the Interface */
 970 static int icn_writecmd(const u_char * buf, int len, int user, icn_dev * dev, int waitflg)
     /* [previous][next][first][last][top][bottom][index][help] */
 971 {
 972         int mch = dev->secondhalf ? 2 : 0;
 973         int avail;
 974         int pp;
 975         int i;
 976         int count;
 977         int ocount;
 978         unsigned long flags;
 979         u_char *p;
 980         isdn_ctrl cmd;
 981         u_char msg[0x100];
 982 
 983         while (1) {
 984                 if (icn_trymaplock_channel(mch)) {
 985                         avail = cmd_free;
 986                         count = MIN(avail, len);
 987                         if (user)
 988                                 memcpy_fromfs(msg, buf, count);
 989                         else
 990                                 memcpy(msg, buf, count);
 991                         save_flags(flags);
 992                         cli();
 993                         ocount = 1;
 994                         *dev->msg_buf_write++ = '>';
 995                         if (dev->msg_buf_write > dev->msg_buf_end)
 996                                 dev->msg_buf_write = dev->msg_buf;
 997                         for (p = msg, pp = cmd_i, i = count; i > 0; i--, p++, pp++) {
 998                                 dev->shmem->comm_buffers.pcio_buf[pp & 0xff] = (*p == '\n') ? 0xff : *p;
 999                                 *dev->msg_buf_write++ = *p;
1000                                 if ((*p == '\n') && (i > 1)) {
1001                                         *dev->msg_buf_write++ = '>';
1002                                         if (dev->msg_buf_write > dev->msg_buf_end)
1003                                                 dev->msg_buf_write = dev->msg_buf;
1004                                         ocount++;
1005                                 }
1006                                 /* No checks for buffer overflow of raw-status-device */
1007                                 if (dev->msg_buf_write > dev->msg_buf_end)
1008                                         dev->msg_buf_write = dev->msg_buf;
1009                                 ocount++;
1010                         }
1011                         restore_flags(flags);
1012                         cmd.command = ISDN_STAT_STAVAIL;
1013                         cmd.driver = dev->myid;
1014                         cmd.arg = ocount;
1015                         dev->interface.statcallb(&cmd);
1016                         cmd_i = (cmd_i + count) & 0xff;
1017                         icn_release_channel();
1018                         waitflg = 0;
1019                 } else
1020                         count = 0;
1021                 if (!waitflg)
1022                         break;
1023                 current->timeout = jiffies + 10;
1024                 schedule();
1025         }
1026         return count;
1027 }
1028 
1029 static void icn_stopdriver(icn_dev * ldev)
     /* [previous][next][first][last][top][bottom][index][help] */
1030 {
1031         unsigned long flags;
1032         isdn_ctrl cmd;
1033 
1034         save_flags(flags);
1035         cli();
1036         del_timer(&dev->st_timer);
1037         del_timer(&ldev->rb_timer);
1038         cmd.command = ISDN_STAT_STOP;
1039         cmd.driver = ldev->myid;
1040         ldev->interface.statcallb(&cmd);
1041         restore_flags(flags);
1042 }
1043 
1044 static int my_atoi(char *s)
     /* [previous][next][first][last][top][bottom][index][help] */
1045 {
1046         int i, n;
1047 
1048         n = 0;
1049         if (!s)
1050                 return -1;
1051         for (i = 0; *s >= '0' && *s <= '9'; i++, s++)
1052                 n = 10 * n + (*s - '0');
1053         return n;
1054 }
1055 
1056 static int icn_command(isdn_ctrl * c, icn_dev * ldev)
     /* [previous][next][first][last][top][bottom][index][help] */
1057 {
1058         ulong a;
1059         ulong flags;
1060         int i;
1061         char cbuf[60];
1062         isdn_ctrl cmd;
1063 
1064         switch (c->command) {
1065         case ISDN_CMD_IOCTL:
1066                 memcpy(&a, c->num, sizeof(ulong));
1067                 switch (c->arg) {
1068                 case ICN_IOCTL_SETMMIO:
1069                         if ((unsigned long) dev->shmem != (a & 0x0ffc000)) {
1070                                 if (check_shmem((ulong) (a & 0x0ffc000), 0x4000)) {
1071                                         printk(KERN_WARNING "icn: memory at 0x%08lx in use.\n",
1072                                                (ulong) (a & 0x0ffc000));
1073                                         return -EINVAL;
1074                                 }
1075                                 icn_stopdriver(dev);
1076                                 if (dev->doubleS0)
1077                                         icn_stopdriver(dev2);
1078                                 save_flags(flags);
1079                                 cli();
1080                                 if (dev->mvalid)
1081                                         release_shmem((ulong) dev->shmem, 0x4000);
1082                                 dev->mvalid = 0;
1083                                 dev->shmem = (icn_shmem *) (a & 0x0ffc000);
1084                                 if (dev->doubleS0)
1085                                         dev2->shmem = (icn_shmem *) (a & 0x0ffc000);
1086                                 restore_flags(flags);
1087                                 printk(KERN_INFO "icn: mmio set to 0x%08lx\n",
1088                                        (unsigned long) dev->shmem);
1089                         }
1090                         break;
1091                 case ICN_IOCTL_GETMMIO:
1092                         return (int) dev->shmem;
1093                 case ICN_IOCTL_SETPORT:
1094                         if (a == 0x300 || a == 0x310 || a == 0x320 || a == 0x330
1095                             || a == 0x340 || a == 0x350 || a == 0x360 ||
1096                             a == 0x308 || a == 0x318 || a == 0x328 || a == 0x338
1097                             || a == 0x348 || a == 0x358 || a == 0x368) {
1098                                 if (dev->port != (unsigned short) a) {
1099                                         if (check_region((unsigned short) a, ICN_PORTLEN)) {
1100                                                 printk(KERN_WARNING "icn: ports 0x%03x-0x%03x in use.\n",
1101                                                        (int) a, (int) a + ICN_PORTLEN);
1102                                                 return -EINVAL;
1103                                         }
1104                                         icn_stopdriver(dev);
1105                                         if (dev->doubleS0)
1106                                                 icn_stopdriver(dev2);
1107                                         save_flags(flags);
1108                                         cli();
1109                                         if (dev->rvalid)
1110                                                 release_region(dev->port, ICN_PORTLEN);
1111                                         dev->port = (unsigned short) a;
1112                                         dev->rvalid = 0;
1113                                         if (dev->doubleS0) {
1114                                                 dev2->port = (unsigned short) a;
1115                                                 dev2->rvalid = 0;
1116                                         }
1117                                         restore_flags(flags);
1118                                         printk(KERN_INFO "icn: port set to 0x%03x\n", dev->port);
1119                                 }
1120                         } else
1121                                 return -EINVAL;
1122                         break;
1123                 case ICN_IOCTL_GETPORT:
1124                         return (int) dev->port;
1125                 case ICN_IOCTL_GETDOUBLE:
1126                         return (int) dev->doubleS0;
1127                 case ICN_IOCTL_DEBUGVAR:
1128                         return (ulong) ldev;
1129 #ifndef LOADEXTERN
1130                 case ICN_IOCTL_LOADBOOT:
1131                         icn_stopdriver(dev);
1132                         if (dev->doubleS0)
1133                                 icn_stopdriver(dev2);
1134                         return (icn_loadboot((u_char *) a, dev));
1135                 case ICN_IOCTL_LOADPROTO:
1136                         icn_stopdriver(dev);
1137                         if (dev->doubleS0)
1138                                 icn_stopdriver(dev2);
1139                         if ((i = (icn_loadproto((u_char *) a, dev))))
1140                                 return i;
1141                         if (dev->doubleS0)
1142                                 i = icn_loadproto((u_char *) (a + ICN_CODE_STAGE2), dev2);
1143                         return i;
1144 #endif
1145                 case ICN_IOCTL_LEASEDCFG:
1146                         if (a) {
1147                                 if (!ldev->leased) {
1148                                         ldev->leased = 1;
1149                                         while (ldev->ptype == ISDN_PTYPE_UNKNOWN) {
1150                                                 current->timeout = jiffies + ICN_BOOT_TIMEOUT1;
1151                                                 schedule();
1152                                         }
1153                                         current->timeout = jiffies + ICN_BOOT_TIMEOUT1;
1154                                         schedule();
1155                                         sprintf(cbuf, "00;FV2ON\n01;EAZ1\n");
1156                                         i = icn_writecmd(cbuf, strlen(cbuf), 0, ldev, 1);
1157                                         printk(KERN_INFO "icn: Leased-line mode enabled\n");
1158                                         cmd.command = ISDN_STAT_RUN;
1159                                         cmd.driver = ldev->myid;
1160                                         cmd.arg = 0;
1161                                         ldev->interface.statcallb(&cmd);
1162                                 }
1163                         } else {
1164                                 if (ldev->leased) {
1165                                         ldev->leased = 0;
1166                                         sprintf(cbuf, "00;FV2OFF\n");
1167                                         i = icn_writecmd(cbuf, strlen(cbuf), 0, ldev, 1);
1168                                         printk(KERN_INFO "icn: Leased-line mode disabled\n");
1169                                         cmd.command = ISDN_STAT_RUN;
1170                                         cmd.driver = ldev->myid;
1171                                         cmd.arg = 0;
1172                                         ldev->interface.statcallb(&cmd);
1173                                 }
1174                         }
1175                         return 0;
1176                 default:
1177                         return -EINVAL;
1178                 }
1179                 break;
1180         case ISDN_CMD_DIAL:
1181                 if (ldev->leased)
1182                         break;
1183                 if ((c->arg & 255) < ICN_BCH) {
1184                         char *p;
1185                         char *p2;
1186                         char dial[50];
1187                         char sis[50];
1188                         char dcode[4];
1189                         int si1, si2;
1190 
1191                         a = c->arg;
1192                         strcpy(sis, c->num);
1193                         p = strrchr(sis, ',');
1194                         *p++ = '\0';
1195                         si2 = my_atoi(p);
1196                         p = strrchr(sis, ',') + 1;
1197                         si1 = my_atoi(p);
1198                         p = c->num;
1199                         if (*p == 's' || *p == 'S') {
1200                                 /* Dial for SPV */
1201                                 p++;
1202                                 strcpy(dcode, "SCA");
1203                         } else
1204                                 /* Normal Dial */
1205                                 strcpy(dcode, "CAL");
1206                         strcpy(dial, p);
1207                         p = strchr(dial, ',');
1208                         *p++ = '\0';
1209                         p2 = strchr(p, ',');
1210                         *p2 = '\0';
1211                         sprintf(cbuf, "%02d;D%s_R%s,%02d,%02d,%s\n", (int) (a + 1), dcode, dial, si1,
1212                                 si2, p);
1213                         i = icn_writecmd(cbuf, strlen(cbuf), 0, ldev, 1);
1214                 }
1215                 break;
1216         case ISDN_CMD_ACCEPTD:
1217                 if (c->arg < ICN_BCH) {
1218                         a = c->arg + 1;
1219                         sprintf(cbuf, "%02d;DCON_R\n", (int) a);
1220                         i = icn_writecmd(cbuf, strlen(cbuf), 0, ldev, 1);
1221                 }
1222                 break;
1223         case ISDN_CMD_ACCEPTB:
1224                 if (c->arg < ICN_BCH) {
1225                         a = c->arg + 1;
1226                         sprintf(cbuf, "%02d;BCON_R\n", (int) a);
1227                         i = icn_writecmd(cbuf, strlen(cbuf), 0, ldev, 1);
1228                 }
1229                 break;
1230         case ISDN_CMD_HANGUP:
1231                 if (c->arg < ICN_BCH) {
1232                         a = c->arg + 1;
1233                         sprintf(cbuf, "%02d;BDIS_R\n%02d;DDIS_R\n", (int) a, (int) a);
1234                         i = icn_writecmd(cbuf, strlen(cbuf), 0, ldev, 1);
1235                 }
1236                 break;
1237         case ISDN_CMD_SETEAZ:
1238                 if (ldev->leased)
1239                         break;
1240                 if (c->arg < ICN_BCH) {
1241                         a = c->arg + 1;
1242                         if (ldev->ptype == ISDN_PTYPE_EURO) {
1243                                 sprintf(cbuf, "%02d;MS%s%s\n", (int) a, c->num[0] ? "N" : "ALL", c->num);
1244                         } else
1245                                 sprintf(cbuf, "%02d;EAZ%s\n", (int) a, c->num[0] ? c->num : "0123456789");
1246                         i = icn_writecmd(cbuf, strlen(cbuf), 0, ldev, 1);
1247                 }
1248                 break;
1249         case ISDN_CMD_CLREAZ:
1250                 if (ldev->leased)
1251                         break;
1252                 if (c->arg < ICN_BCH) {
1253                         a = c->arg + 1;
1254                         if (ldev->ptype == ISDN_PTYPE_EURO)
1255                                 sprintf(cbuf, "%02d;MSNC\n", (int) a);
1256                         else
1257                                 sprintf(cbuf, "%02d;EAZC\n", (int) a);
1258                         i = icn_writecmd(cbuf, strlen(cbuf), 0, ldev, 1);
1259                 }
1260                 break;
1261         case ISDN_CMD_SETL2:
1262                 if ((c->arg & 255) < ICN_BCH) {
1263                         a = c->arg;
1264                         switch (a >> 8) {
1265                         case ISDN_PROTO_L2_X75I:
1266                                 sprintf(cbuf, "%02d;BX75\n", (int) (a & 255) + 1);
1267                                 break;
1268                         case ISDN_PROTO_L2_HDLC:
1269                                 sprintf(cbuf, "%02d;BTRA\n", (int) (a & 255) + 1);
1270                                 break;
1271                         default:
1272                                 return -EINVAL;
1273                         }
1274                         i = icn_writecmd(cbuf, strlen(cbuf), 0, ldev, 1);
1275                         ldev->l2_proto[a & 255] = (a >> 8);
1276                 }
1277                 break;
1278         case ISDN_CMD_GETL2:
1279                 if ((c->arg & 255) < ICN_BCH)
1280                         return ldev->l2_proto[c->arg & 255];
1281                 else
1282                         return -ENODEV;
1283         case ISDN_CMD_SETL3:
1284                 return 0;
1285         case ISDN_CMD_GETL3:
1286                 if ((c->arg & 255) < ICN_BCH)
1287                         return ISDN_PROTO_L3_TRANS;
1288                 else
1289                         return -ENODEV;
1290         case ISDN_CMD_GETEAZ:
1291                 break;
1292         case ISDN_CMD_SETSIL:
1293                 break;
1294         case ISDN_CMD_GETSIL:
1295                 break;
1296         case ISDN_CMD_LOCK:
1297                 MOD_INC_USE_COUNT;
1298                 break;
1299         case ISDN_CMD_UNLOCK:
1300                 MOD_DEC_USE_COUNT;
1301                 break;
1302         default:
1303                 return -EINVAL;
1304         }
1305         return 0;
1306 }
1307 
1308 /*
1309  * For second half of doubleS0-Card add channel-offset.
1310  */
1311 static int if_command1(isdn_ctrl * c)
     /* [previous][next][first][last][top][bottom][index][help] */
1312 {
1313         return (icn_command(c, dev));
1314 }
1315 
1316 static int if_command2(isdn_ctrl * c)
     /* [previous][next][first][last][top][bottom][index][help] */
1317 {
1318         return (icn_command(c, dev2));
1319 }
1320 
1321 static int if_writecmd1(const u_char * buf, int len, int user)
     /* [previous][next][first][last][top][bottom][index][help] */
1322 {
1323         return (icn_writecmd(buf, len, user, dev, 0));
1324 }
1325 
1326 static int if_writecmd2(const u_char * buf, int len, int user)
     /* [previous][next][first][last][top][bottom][index][help] */
1327 {
1328         return (icn_writecmd(buf, len, user, dev2, 0));
1329 }
1330 
1331 static int if_readstatus1(u_char * buf, int len, int user)
     /* [previous][next][first][last][top][bottom][index][help] */
1332 {
1333         return (icn_readstatus(buf, len, user, dev));
1334 }
1335 
1336 static int if_readstatus2(u_char * buf, int len, int user)
     /* [previous][next][first][last][top][bottom][index][help] */
1337 {
1338         return (icn_readstatus(buf, len, user, dev2));
1339 }
1340 
1341 static int if_sendbuf1(int id, int channel, const u_char * buffer, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
1342                        int user)
1343 {
1344         return (icn_sendbuf(channel, buffer, len, user, dev));
1345 }
1346 
1347 static int if_sendbuf2(int id, int channel, const u_char * buffer, int len,
     /* [previous][next][first][last][top][bottom][index][help] */
1348                        int user)
1349 {
1350         return (icn_sendbuf(channel, buffer, len, user, dev2));
1351 }
1352 
1353 #ifdef MODULE
1354 #define icn_init init_module
1355 #else
1356 void icn_setup(char *str, int *ints)
     /* [previous][next][first][last][top][bottom][index][help] */
1357 {
1358         char *p;
1359         static char sid[20];
1360         static char sid2[20];
1361 
1362         if (ints[0])
1363                 portbase = ints[1];
1364         if (ints[0]>1)
1365                 membase  = ints[2];
1366         if (strlen(str)) {
1367                 strcpy(sid,str);
1368                 icn_id = sid;
1369                 if ((p = strchr(sid,','))) {
1370                         *p++ = 0;
1371                         strcpy(sid2,p);
1372                         icn_id2 = sid2;
1373                 }
1374         }
1375 }
1376 #endif
1377 
1378 int icn_init(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1379 {
1380 #ifdef LOADEXTERN
1381         unsigned long flags;
1382 #endif
1383         char *p;
1384         isdn_ctrl cmd;
1385         char rev[10];
1386 
1387         if (!(dev = (icn_devptr) kmalloc(sizeof(icn_dev), GFP_KERNEL))) {
1388                 printk(KERN_WARNING "icn: Could not allocate device-struct.\n");
1389                 return -EIO;
1390         }
1391         memset((char *) dev, 0, sizeof(icn_dev));
1392         dev->port = portbase;
1393         dev->shmem = (icn_shmem *) (membase & 0x0ffc000);
1394         if (strlen(icn_id2))
1395                 dev->doubleS0 = 1;
1396         dev->interface.channels = ICN_BCH;
1397         dev->interface.maxbufsize = 4000;
1398         dev->interface.command = if_command1;
1399         dev->interface.writebuf = if_sendbuf1;
1400         dev->interface.writecmd = if_writecmd1;
1401         dev->interface.readstat = if_readstatus1;
1402         dev->interface.features = ISDN_FEATURE_L2_X75I |
1403                 ISDN_FEATURE_L2_HDLC |
1404                 ISDN_FEATURE_L3_TRANS |
1405                 ISDN_FEATURE_P_UNKNOWN;
1406         dev->ptype = ISDN_PTYPE_UNKNOWN;
1407         strncpy(dev->interface.id, icn_id, sizeof(dev->interface.id) - 1);
1408         dev->msg_buf_write = dev->msg_buf;
1409         dev->msg_buf_read = dev->msg_buf;
1410         dev->msg_buf_end = &dev->msg_buf[sizeof(dev->msg_buf) - 1];
1411         memset((char *) dev->l2_proto, ISDN_PROTO_L2_X75I, sizeof(dev->l2_proto));
1412         if (strlen(icn_id2)) {
1413                 if (!(dev2 = (icn_devptr) kmalloc(sizeof(icn_dev), GFP_KERNEL))) {
1414                         printk(KERN_WARNING "icn: Could not allocate device-struct.\n");
1415                         kfree(dev);
1416                         kfree(dev2);
1417                         return -EIO;
1418                 }
1419                 memcpy((char *) dev2, (char *) dev, sizeof(icn_dev));
1420                 dev2->interface.command = if_command2;
1421                 dev2->interface.writebuf = if_sendbuf2;
1422                 dev2->interface.writecmd = if_writecmd2;
1423                 dev2->interface.readstat = if_readstatus2;
1424                 strncpy(dev2->interface.id, icn_id2,
1425                         sizeof(dev->interface.id) - 1);
1426                 dev2->msg_buf_write = dev2->msg_buf;
1427                 dev2->msg_buf_read = dev2->msg_buf;
1428                 dev2->msg_buf_end = &dev2->msg_buf[sizeof(dev2->msg_buf) - 1];
1429                 dev2->secondhalf = 1;
1430         }
1431         if (!register_isdn(&dev->interface)) {
1432                 printk(KERN_WARNING "icn: Unable to register\n");
1433                 kfree(dev);
1434                 if (dev->doubleS0)
1435                         kfree(dev2);
1436                 return -EIO;
1437         }
1438         dev->myid = dev->interface.channels;
1439         sprintf(regname, "icn-isdn (%s)", dev->interface.id);
1440         if (dev->doubleS0) {
1441                 if (!register_isdn(&dev2->interface)) {
1442                         printk(KERN_WARNING "icn: Unable to register\n");
1443                         kfree(dev2);
1444                         if (dev->doubleS0) {
1445                                 icn_stopdriver(dev);
1446                                 cmd.command = ISDN_STAT_UNLOAD;
1447                                 cmd.driver = dev->myid;
1448                                 dev->interface.statcallb(&cmd);
1449                                 kfree(dev);
1450                         }
1451                         return -EIO;
1452                 }
1453                 dev2->myid = dev2->interface.channels;
1454         }
1455         
1456         /* No symbols to export, hide all symbols */
1457         register_symtab(NULL);
1458 
1459         if ((p = strchr(revision, ':'))) {
1460                 strcpy(rev, p + 1);
1461                 p = strchr(rev, '$');
1462                 *p = 0;
1463         } else
1464                 strcpy(rev, " ??? ");
1465         printk(KERN_NOTICE "ICN-ISDN-driver Rev%sport=0x%03x mmio=0x%08x id='%s'\n",
1466                rev, dev->port, (uint) dev->shmem, dev->interface.id);
1467 #ifdef LOADEXTERN
1468         save_flags(flags);
1469         cli();
1470         init_timer(&dev->st_timer);
1471         dev->st_timer.expires = jiffies + ICN_TIMER_DCREAD;
1472         dev->st_timer.function = icn_pollcard;
1473         add_timer(&dev->st_timer);
1474         restore_flags(flags);
1475 #endif
1476         return 0;
1477 }
1478 
1479 #ifdef MODULE
1480 void cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
1481 {
1482         isdn_ctrl cmd;
1483         int i;
1484 
1485         icn_stopdriver(dev);
1486         cmd.command = ISDN_STAT_UNLOAD;
1487         cmd.driver = dev->myid;
1488         dev->interface.statcallb(&cmd);
1489         if (dev->doubleS0) {
1490                 icn_stopdriver(dev2);
1491                 cmd.command = ISDN_STAT_UNLOAD;
1492                 cmd.driver = dev2->myid;
1493                 dev2->interface.statcallb(&cmd);
1494         }
1495         if (dev->rvalid) {
1496                 OUTB_P(0, ICN_RUN);     /* Reset Controller     */
1497                 OUTB_P(0, ICN_MAPRAM);  /* Disable RAM          */
1498                 release_region(dev->port, ICN_PORTLEN);
1499         }
1500         if (dev->mvalid)
1501                 release_shmem((ulong) dev->shmem, 0x4000);
1502         if (dev->doubleS0) {
1503                 for (i = 0; i < ICN_BCH; i++)
1504                         icn_free_queue(&dev2->spqueue[1]);
1505                 kfree(dev2);
1506         }
1507         for (i = 0; i < ICN_BCH; i++)
1508                 icn_free_queue(&dev->spqueue[1]);
1509         kfree(dev);
1510         printk(KERN_NOTICE "ICN-ISDN-driver unloaded\n");
1511 }
1512 #endif

/* [previous][next][first][last][top][bottom][index][help] */