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

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