linux/drivers/staging/dgap/dgap_parse.c
<<
>>
Prefs
   1/*
   2 * Copyright 2003 Digi International (www.digi.com)
   3 *      Scott H Kilau <Scott_Kilau at digi dot com>
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License as published by
   7 * the Free Software Foundation; either version 2, or (at your option)
   8 * any later version.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the
  12 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  13 * PURPOSE.  See the GNU General Public License for more details.
  14 *
  15 * You should have received a copy of the GNU General Public License
  16 * along with this program; if not, write to the Free Software
  17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  18 *
  19 *
  20 *      NOTE TO LINUX KERNEL HACKERS:  DO NOT REFORMAT THIS CODE! 
  21 *
  22 *      This is shared code between Digi's CVS archive and the
  23 *      Linux Kernel sources.
  24 *      Changing the source just for reformatting needlessly breaks
  25 *      our CVS diff history.
  26 *
  27 *      Send any bug fixes/changes to:  Eng.Linux at digi dot com. 
  28 *      Thank you.
  29 *
  30 *
  31 *****************************************************************************
  32 *
  33 * dgap_parse.c - Parses the configuration information from the input file.
  34 *
  35 * $Id: dgap_parse.c,v 1.1 2009/10/23 14:01:57 markh Exp $
  36 *
  37 */
  38#include <linux/kernel.h>
  39#include <linux/ctype.h>
  40#include <linux/slab.h>
  41
  42#include "dgap_types.h"
  43#include "dgap_fep5.h"
  44#include "dgap_driver.h"
  45#include "dgap_conf.h"
  46
  47
  48/*
  49 * Function prototypes.
  50 */
  51static int dgap_gettok(char **in, struct cnode *p);
  52static char *dgap_getword(char **in);
  53static char *dgap_savestring(char *s);
  54static struct cnode *dgap_newnode(int t);
  55static int dgap_checknode(struct cnode *p);
  56static void dgap_err(char *s);
  57
  58/*
  59 * Our needed internal static variables...
  60 */
  61static struct cnode dgap_head;
  62#define MAXCWORD 200
  63static char dgap_cword[MAXCWORD];
  64
  65struct toklist {
  66        int     token;
  67        char    *string;
  68};
  69
  70static struct toklist dgap_tlist[] = {
  71        {       BEGIN,          "config_begin"                  },
  72        {       END,            "config_end"                    },
  73        {       BOARD,          "board"                         },
  74        {       PCX,            "Digi_AccelePort_C/X_PCI"       },      /* C/X_PCI */
  75        {       PEPC,           "Digi_AccelePort_EPC/X_PCI"     },      /* EPC/X_PCI */
  76        {       PPCM,           "Digi_AccelePort_Xem_PCI"       },      /* PCI/Xem */
  77        {       APORT2_920P,    "Digi_AccelePort_2r_920_PCI"    },
  78        {       APORT4_920P,    "Digi_AccelePort_4r_920_PCI"    },
  79        {       APORT8_920P,    "Digi_AccelePort_8r_920_PCI"    },
  80        {       PAPORT4,        "Digi_AccelePort_4r_PCI(EIA-232/RS-422)" },
  81        {       PAPORT8,        "Digi_AccelePort_8r_PCI(EIA-232/RS-422)" },
  82        {       IO,             "io"                            },
  83        {       PCIINFO,        "pciinfo"                       },
  84        {       LINE,           "line"                          },
  85        {       CONC,           "conc"                          },
  86        {       CONC,           "concentrator"                  },
  87        {       CX,             "cx"                            },
  88        {       CX,             "ccon"                          },
  89        {       EPC,            "epccon"                        },
  90        {       EPC,            "epc"                           },
  91        {       MOD,            "module"                        },
  92        {       ID,             "id"                            },
  93        {       STARTO,         "start"                         },
  94        {       SPEED,          "speed"                         },
  95        {       CABLE,          "cable"                         },
  96        {       CONNECT,        "connect"                       },
  97        {       METHOD,         "method"                        },
  98        {       STATUS,         "status"                        },
  99        {       CUSTOM,         "Custom"                        },
 100        {       BASIC,          "Basic"                         },
 101        {       MEM,            "mem"                           },
 102        {       MEM,            "memory"                        },
 103        {       PORTS,          "ports"                         },
 104        {       MODEM,          "modem"                         },
 105        {       NPORTS,         "nports"                        },
 106        {       TTYN,           "ttyname"                       },
 107        {       CU,             "cuname"                        },
 108        {       PRINT,          "prname"                        },
 109        {       CMAJOR,         "major"                         },
 110        {       ALTPIN,         "altpin"                        },
 111        {       USEINTR,        "useintr"                       },
 112        {       TTSIZ,          "ttysize"                       },
 113        {       CHSIZ,          "chsize"                        },
 114        {       BSSIZ,          "boardsize"                     },
 115        {       UNTSIZ,         "schedsize"                     },
 116        {       F2SIZ,          "f2200size"                     },
 117        {       VPSIZ,          "vpixsize"                      },
 118        {       0,              NULL                            }
 119};
 120
 121
 122/*
 123 * Parse a configuration file read into memory as a string.
 124 */
 125int     dgap_parsefile(char **in, int Remove)
 126{
 127        struct cnode *p, *brd, *line, *conc;
 128        int     rc;
 129        char    *s = NULL, *s2 = NULL;
 130        int     linecnt = 0;
 131
 132        p = &dgap_head;
 133        brd = line = conc = NULL;
 134
 135        /* perhaps we are adding to an existing list? */
 136        while (p->next != NULL) {
 137                p = p->next;
 138        }
 139
 140        /* file must start with a BEGIN */
 141        while ( (rc = dgap_gettok(in,p)) != BEGIN ) {
 142                if (rc == 0) {
 143                        dgap_err("unexpected EOF");
 144                        return(-1);
 145                }
 146        }
 147
 148        for (; ; ) {
 149                rc = dgap_gettok(in,p);
 150                if (rc == 0) {
 151                        dgap_err("unexpected EOF");
 152                        return(-1);
 153                }
 154
 155                switch (rc) {
 156                case 0:
 157                        dgap_err("unexpected end of file");
 158                        return(-1);
 159
 160                case BEGIN:     /* should only be 1 begin */
 161                        dgap_err("unexpected config_begin\n");
 162                        return(-1);
 163
 164                case END:
 165                        return(0);
 166
 167                case BOARD:     /* board info */
 168                        if (dgap_checknode(p))
 169                                return(-1);
 170                        if ( (p->next = dgap_newnode(BNODE)) == NULL ) {
 171                                dgap_err("out of memory");
 172                                return(-1);
 173                        }
 174                        p = p->next;
 175
 176                        p->u.board.status = dgap_savestring("No");
 177                        line = conc = NULL;
 178                        brd = p;
 179                        linecnt = -1;
 180                        break;
 181
 182                case APORT2_920P:       /* AccelePort_4 */
 183                        if (p->type != BNODE) {
 184                                dgap_err("unexpected Digi_2r_920 string");
 185                                return(-1);
 186                        }
 187                        p->u.board.type = APORT2_920P;
 188                        p->u.board.v_type = 1;
 189                        DPR_INIT(("Adding Digi_2r_920 PCI to config...\n"));
 190                        break;
 191
 192                case APORT4_920P:       /* AccelePort_4 */
 193                        if (p->type != BNODE) {
 194                                dgap_err("unexpected Digi_4r_920 string");
 195                                return(-1);
 196                        }
 197                        p->u.board.type = APORT4_920P;
 198                        p->u.board.v_type = 1;
 199                        DPR_INIT(("Adding Digi_4r_920 PCI to config...\n"));
 200                        break;
 201
 202                case APORT8_920P:       /* AccelePort_8 */
 203                        if (p->type != BNODE) {
 204                                dgap_err("unexpected Digi_8r_920 string");
 205                                return(-1);
 206                        }
 207                        p->u.board.type = APORT8_920P;
 208                        p->u.board.v_type = 1;
 209                        DPR_INIT(("Adding Digi_8r_920 PCI to config...\n"));
 210                        break;
 211
 212                case PAPORT4:   /* AccelePort_4 PCI */
 213                        if (p->type != BNODE) {
 214                                dgap_err("unexpected Digi_4r(PCI) string");
 215                                return(-1);
 216                        }
 217                        p->u.board.type = PAPORT4;
 218                        p->u.board.v_type = 1;
 219                        DPR_INIT(("Adding Digi_4r PCI to config...\n"));
 220                        break;
 221
 222                case PAPORT8:   /* AccelePort_8 PCI */
 223                        if (p->type != BNODE) {
 224                                dgap_err("unexpected Digi_8r string");
 225                                return(-1);
 226                        }
 227                        p->u.board.type = PAPORT8;
 228                        p->u.board.v_type = 1;
 229                        DPR_INIT(("Adding Digi_8r PCI to config...\n"));
 230                        break;
 231
 232                case PCX:       /* PCI C/X */
 233                        if (p->type != BNODE) {
 234                                dgap_err("unexpected Digi_C/X_(PCI) string");
 235                                return(-1);
 236                        }
 237                        p->u.board.type = PCX;
 238                        p->u.board.v_type = 1;
 239                        p->u.board.conc1 = 0;
 240                        p->u.board.conc2 = 0;
 241                        p->u.board.module1 = 0;
 242                        p->u.board.module2 = 0;
 243                        DPR_INIT(("Adding PCI C/X to config...\n"));
 244                        break;
 245
 246                case PEPC:      /* PCI EPC/X */
 247                        if (p->type != BNODE) {
 248                                dgap_err("unexpected \"Digi_EPC/X_(PCI)\" string");
 249                                return(-1);
 250                        }
 251                        p->u.board.type = PEPC;
 252                        p->u.board.v_type = 1;
 253                        p->u.board.conc1 = 0;
 254                        p->u.board.conc2 = 0;
 255                        p->u.board.module1 = 0;
 256                        p->u.board.module2 = 0;
 257                        DPR_INIT(("Adding PCI EPC/X to config...\n"));
 258                        break;
 259
 260                case PPCM:      /* PCI/Xem */
 261                        if (p->type != BNODE) {
 262                                dgap_err("unexpected PCI/Xem string");
 263                                return(-1);
 264                        }
 265                        p->u.board.type = PPCM;
 266                        p->u.board.v_type = 1;
 267                        p->u.board.conc1 = 0;
 268                        p->u.board.conc2 = 0;
 269                        DPR_INIT(("Adding PCI XEM to config...\n"));
 270                        break;
 271
 272                case IO:        /* i/o port */
 273                        if (p->type != BNODE) {
 274                                dgap_err("IO port only vaild for boards");
 275                                return(-1);
 276                        }
 277                        s = dgap_getword(in);
 278                        if (s == NULL) {
 279                                dgap_err("unexpected end of file");
 280                                return(-1);
 281                        }
 282                        p->u.board.portstr = dgap_savestring(s);
 283                        p->u.board.port = (short)simple_strtol(s, &s2, 0);
 284                        if ((short)strlen(s) > (short)(s2 - s)) {
 285                                dgap_err("bad number for IO port");
 286                                return(-1);
 287                        }
 288                        p->u.board.v_port = 1;
 289                        DPR_INIT(("Adding IO (%s) to config...\n", s));
 290                        break;
 291
 292                case MEM:       /* memory address */
 293                        if (p->type != BNODE) {
 294                                dgap_err("memory address only vaild for boards");
 295                                return(-1);
 296                        }
 297                        s = dgap_getword(in);
 298                        if (s == NULL) {
 299                                dgap_err("unexpected end of file");
 300                                return(-1);
 301                        }
 302                        p->u.board.addrstr = dgap_savestring(s);
 303                        p->u.board.addr = simple_strtoul(s, &s2, 0);
 304                        if ((int)strlen(s) > (int)(s2 - s)) {
 305                                dgap_err("bad number for memory address");
 306                                return(-1);
 307                        }
 308                        p->u.board.v_addr = 1;
 309                        DPR_INIT(("Adding MEM (%s) to config...\n", s));
 310                        break;
 311
 312                case PCIINFO:   /* pci information */
 313                        if (p->type != BNODE) {
 314                                dgap_err("memory address only vaild for boards");
 315                                return(-1);
 316                        }
 317                        s = dgap_getword(in);
 318                        if (s == NULL) {
 319                                dgap_err("unexpected end of file");
 320                                return(-1);
 321                        }
 322                        p->u.board.pcibusstr = dgap_savestring(s);
 323                        p->u.board.pcibus = simple_strtoul(s, &s2, 0);
 324                        if ((int)strlen(s) > (int)(s2 - s)) {
 325                                dgap_err("bad number for pci bus");
 326                                return(-1);
 327                        }
 328                        p->u.board.v_pcibus = 1;
 329                        s = dgap_getword(in);
 330                        if (s == NULL) {
 331                                dgap_err("unexpected end of file");
 332                                return(-1);
 333                        }
 334                        p->u.board.pcislotstr = dgap_savestring(s);
 335                        p->u.board.pcislot = simple_strtoul(s, &s2, 0);
 336                        if ((int)strlen(s) > (int)(s2 - s)) {
 337                                dgap_err("bad number for pci slot");
 338                                return(-1);
 339                        }
 340                        p->u.board.v_pcislot = 1;
 341
 342                        DPR_INIT(("Adding PCIINFO (%s %s) to config...\n", p->u.board.pcibusstr, 
 343                                p->u.board.pcislotstr));
 344                        break;
 345
 346                case METHOD:
 347                        if (p->type != BNODE) {
 348                                dgap_err("install method only vaild for boards");
 349                                return(-1);
 350                        }
 351                        s = dgap_getword(in);
 352                        if (s == NULL) {
 353                                dgap_err("unexpected end of file");
 354                                return(-1);
 355                        }
 356                        p->u.board.method = dgap_savestring(s);
 357                        p->u.board.v_method = 1;
 358                        DPR_INIT(("Adding METHOD (%s) to config...\n", s));
 359                        break;
 360
 361                case STATUS:
 362                        if (p->type != BNODE) {
 363                                dgap_err("config status only vaild for boards");
 364                                return(-1);
 365                        }
 366                        s = dgap_getword(in);
 367                        if (s == NULL) {
 368                                dgap_err("unexpected end of file");
 369                                return(-1);
 370                        }
 371                        p->u.board.status = dgap_savestring(s);
 372                        DPR_INIT(("Adding STATUS (%s) to config...\n", s));
 373                        break;
 374
 375                case NPORTS:    /* number of ports */
 376                        if (p->type == BNODE) {
 377                                s = dgap_getword(in);
 378                                if (s == NULL) {
 379                                        dgap_err("unexpected end of file");
 380                                        return(-1);
 381                                }
 382                                p->u.board.nport = (char)simple_strtol(s, &s2, 0);
 383                                if ((int)strlen(s) > (int)(s2 - s)) {
 384                                        dgap_err("bad number for number of ports");
 385                                        return(-1);
 386                                }
 387                                p->u.board.v_nport = 1;
 388                        } else if (p->type == CNODE) {
 389                                s = dgap_getword(in);
 390                                if (s == NULL) {
 391                                        dgap_err("unexpected end of file");
 392                                        return(-1);
 393                                }
 394                                p->u.conc.nport = (char)simple_strtol(s, &s2, 0);
 395                                if ((int)strlen(s) > (int)(s2 - s)) {
 396                                        dgap_err("bad number for number of ports");
 397                                        return(-1);
 398                                }
 399                                p->u.conc.v_nport = 1;
 400                        } else if (p->type == MNODE) {
 401                                s = dgap_getword(in);
 402                                if (s == NULL) {
 403                                        dgap_err("unexpected end of file");
 404                                        return(-1);
 405                                }
 406                                p->u.module.nport = (char)simple_strtol(s, &s2, 0);
 407                                if ((int)strlen(s) > (int)(s2 - s)) {
 408                                        dgap_err("bad number for number of ports");
 409                                        return(-1);
 410                                }
 411                                p->u.module.v_nport = 1;
 412                        } else {
 413                                dgap_err("nports only valid for concentrators or modules");
 414                                return(-1);
 415                        }
 416                        DPR_INIT(("Adding NPORTS (%s) to config...\n", s));
 417                        break;
 418
 419                case ID:        /* letter ID used in tty name */
 420                        s = dgap_getword(in);
 421                        if (s == NULL) {
 422                                dgap_err("unexpected end of file");
 423                                return(-1);
 424                        }
 425
 426                        p->u.board.status = dgap_savestring(s);
 427
 428                        if (p->type == CNODE) {
 429                                p->u.conc.id = dgap_savestring(s);
 430                                p->u.conc.v_id = 1;
 431                        } else if (p->type == MNODE) {
 432                                p->u.module.id = dgap_savestring(s);
 433                                p->u.module.v_id = 1;
 434                        } else {
 435                                dgap_err("id only valid for concentrators or modules");
 436                                return(-1);
 437                        }
 438                        DPR_INIT(("Adding ID (%s) to config...\n", s));
 439                        break;
 440
 441                case STARTO:    /* start offset of ID */
 442                        if (p->type == BNODE) {
 443                                s = dgap_getword(in);
 444                                if (s == NULL) {
 445                                        dgap_err("unexpected end of file");
 446                                        return(-1);
 447                                }
 448                                p->u.board.start = simple_strtol(s, &s2, 0);
 449                                if ((int)strlen(s) > (int)(s2 - s)) {
 450                                        dgap_err("bad number for start of tty count");
 451                                        return(-1);
 452                                }
 453                                p->u.board.v_start = 1;
 454                        } else if (p->type == CNODE) {
 455                                s = dgap_getword(in);
 456                                if (s == NULL) {
 457                                        dgap_err("unexpected end of file");
 458                                        return(-1);
 459                                }
 460                                p->u.conc.start = simple_strtol(s, &s2, 0);
 461                                if ((int)strlen(s) > (int)(s2 - s)) {
 462                                        dgap_err("bad number for start of tty count");
 463                                        return(-1);
 464                                }
 465                                p->u.conc.v_start = 1;
 466                        } else if (p->type == MNODE) {
 467                                s = dgap_getword(in);
 468                                if (s == NULL) {
 469                                        dgap_err("unexpected end of file");
 470                                        return(-1);
 471                                }
 472                                p->u.module.start = simple_strtol(s, &s2, 0);
 473                                if ((int)strlen(s) > (int)(s2 - s)) {
 474                                        dgap_err("bad number for start of tty count");
 475                                        return(-1);
 476                                }
 477                                p->u.module.v_start = 1;
 478                        } else {
 479                                dgap_err("start only valid for concentrators or modules");
 480                                return(-1);
 481                        }
 482                        DPR_INIT(("Adding START (%s) to config...\n", s));
 483                        break;
 484
 485                case TTYN:      /* tty name prefix */
 486                        if (dgap_checknode(p))
 487                                return(-1);
 488                        if ( (p->next = dgap_newnode(TNODE)) == NULL ) {
 489                                dgap_err("out of memory");
 490                                return(-1);
 491                        }
 492                        p = p->next;
 493                        if ( (s = dgap_getword(in)) == NULL ) {
 494                                dgap_err("unexpeced end of file");
 495                                return(-1);
 496                        }
 497                        if ( (p->u.ttyname = dgap_savestring(s)) == NULL ) {
 498                                dgap_err("out of memory");
 499                                return(-1);
 500                        }
 501                        DPR_INIT(("Adding TTY (%s) to config...\n", s));
 502                        break;
 503
 504                case CU:        /* cu name prefix */
 505                        if (dgap_checknode(p))
 506                                return(-1);
 507                        if ( (p->next = dgap_newnode(CUNODE)) == NULL ) {
 508                                dgap_err("out of memory");
 509                                return(-1);
 510                        }
 511                        p = p->next;
 512                        if ( (s = dgap_getword(in)) == NULL ) {
 513                                dgap_err("unexpeced end of file");
 514                                return(-1);
 515                        }
 516                        if ( (p->u.cuname = dgap_savestring(s)) == NULL ) {
 517                                dgap_err("out of memory");
 518                                return(-1);
 519                        }
 520                        DPR_INIT(("Adding CU (%s) to config...\n", s));
 521                        break;
 522
 523                case LINE:      /* line information */
 524                        if (dgap_checknode(p))
 525                                return(-1);
 526                        if (brd == NULL) {
 527                                dgap_err("must specify board before line info");
 528                                return(-1);
 529                        }
 530                        switch (brd->u.board.type) {
 531                        case PPCM:
 532                                dgap_err("line not vaild for PC/em");
 533                                return(-1);
 534                        }
 535                        if ( (p->next = dgap_newnode(LNODE)) == NULL ) {
 536                                dgap_err("out of memory");
 537                                return(-1);
 538                        }
 539                        p = p->next;
 540                        conc = NULL;
 541                        line = p;
 542                        linecnt++;
 543                        DPR_INIT(("Adding LINE to config...\n"));
 544                        break;
 545
 546                case CONC:      /* concentrator information */
 547                        if (dgap_checknode(p))
 548                                return(-1);
 549                        if (line == NULL) {
 550                                dgap_err("must specify line info before concentrator");
 551                                return(-1);
 552                        }
 553                        if ( (p->next = dgap_newnode(CNODE)) == NULL ) {
 554                                dgap_err("out of memory");
 555                                return(-1);
 556                        }
 557                        p = p->next;
 558                        conc = p;
 559                        if (linecnt)
 560                                brd->u.board.conc2++;
 561                        else
 562                                brd->u.board.conc1++;
 563
 564                        DPR_INIT(("Adding CONC to config...\n"));
 565                        break;
 566
 567                case CX:        /* c/x type concentrator */
 568                        if (p->type != CNODE) {
 569                                dgap_err("cx only valid for concentrators");
 570                                return(-1);
 571                        }
 572                        p->u.conc.type = CX;
 573                        p->u.conc.v_type = 1;
 574                        DPR_INIT(("Adding CX to config...\n"));
 575                        break;
 576
 577                case EPC:       /* epc type concentrator */
 578                        if (p->type != CNODE) {
 579                                dgap_err("cx only valid for concentrators");
 580                                return(-1);
 581                        }
 582                        p->u.conc.type = EPC;
 583                        p->u.conc.v_type = 1;
 584                        DPR_INIT(("Adding EPC to config...\n"));
 585                        break;
 586
 587                case MOD:       /* EBI module */
 588                        if (dgap_checknode(p))
 589                                return(-1);
 590                        if (brd == NULL) {
 591                                dgap_err("must specify board info before EBI modules");
 592                                return(-1);
 593                        }
 594                        switch (brd->u.board.type) {
 595                        case PPCM:
 596                                linecnt = 0;
 597                                break;
 598                        default:
 599                                if (conc == NULL) {
 600                                        dgap_err("must specify concentrator info before EBI module");
 601                                        return(-1);
 602                                }
 603                        }
 604                        if ( (p->next = dgap_newnode(MNODE)) == NULL ) {
 605                                dgap_err("out of memory");
 606                                return(-1);
 607                        }
 608                        p = p->next;
 609                        if (linecnt)
 610                                brd->u.board.module2++;
 611                        else
 612                                brd->u.board.module1++;
 613
 614                        DPR_INIT(("Adding MOD to config...\n"));
 615                        break;
 616
 617                case PORTS:     /* ports type EBI module */
 618                        if (p->type != MNODE) {
 619                                dgap_err("ports only valid for EBI modules");
 620                                return(-1);
 621                        }
 622                        p->u.module.type = PORTS;
 623                        p->u.module.v_type = 1;
 624                        DPR_INIT(("Adding PORTS to config...\n"));
 625                        break;
 626
 627                case MODEM:     /* ports type EBI module */
 628                        if (p->type != MNODE) {
 629                                dgap_err("modem only valid for modem modules");
 630                                return(-1);
 631                        }
 632                        p->u.module.type = MODEM;
 633                        p->u.module.v_type = 1;
 634                        DPR_INIT(("Adding MODEM to config...\n"));
 635                        break;
 636
 637                case CABLE:
 638                        if (p->type == LNODE) {
 639                                if ((s = dgap_getword(in)) == NULL) {
 640                                        dgap_err("unexpected end of file");
 641                                        return(-1);
 642                                }
 643                                p->u.line.cable = dgap_savestring(s);
 644                                p->u.line.v_cable = 1;
 645                        }
 646                        DPR_INIT(("Adding CABLE (%s) to config...\n", s));
 647                        break;
 648
 649                case SPEED:     /* sync line speed indication */
 650                        if (p->type == LNODE) {
 651                                s = dgap_getword(in);
 652                                if (s == NULL) {
 653                                        dgap_err("unexpected end of file");
 654                                        return(-1);
 655                                }
 656                                p->u.line.speed = (char)simple_strtol(s, &s2, 0);
 657                                if ((short)strlen(s) > (short)(s2 - s)) {
 658                                        dgap_err("bad number for line speed");
 659                                        return(-1);
 660                                }
 661                                p->u.line.v_speed = 1;
 662                        } else if (p->type == CNODE) {
 663                                s = dgap_getword(in);
 664                                if (s == NULL) {
 665                                        dgap_err("unexpected end of file");
 666                                        return(-1);
 667                                }
 668                                p->u.conc.speed = (char)simple_strtol(s, &s2, 0);
 669                                if ((short)strlen(s) > (short)(s2 - s)) {
 670                                        dgap_err("bad number for line speed");
 671                                        return(-1);
 672                                }
 673                                p->u.conc.v_speed = 1;
 674                        } else {
 675                                dgap_err("speed valid only for lines or concentrators.");
 676                                return(-1);
 677                        }
 678                        DPR_INIT(("Adding SPEED (%s) to config...\n", s));
 679                        break;
 680
 681                case CONNECT:
 682                        if (p->type == CNODE) {
 683                                if ((s = dgap_getword(in)) == NULL) {
 684                                        dgap_err("unexpected end of file");
 685                                        return(-1);
 686                                }
 687                                p->u.conc.connect = dgap_savestring(s);
 688                                p->u.conc.v_connect = 1;
 689                        }
 690                        DPR_INIT(("Adding CONNECT (%s) to config...\n", s));
 691                        break;
 692                case PRINT:     /* transparent print name prefix */
 693                        if (dgap_checknode(p))
 694                                return(-1);
 695                        if ( (p->next = dgap_newnode(PNODE)) == NULL ) {
 696                                dgap_err("out of memory");
 697                                return(-1);
 698                        }
 699                        p = p->next;
 700                        if ( (s = dgap_getword(in)) == NULL ) {
 701                                dgap_err("unexpeced end of file");
 702                                return(-1);
 703                        }
 704                        if ( (p->u.printname = dgap_savestring(s)) == NULL ) {
 705                                dgap_err("out of memory");
 706                                return(-1);
 707                        }
 708                        DPR_INIT(("Adding PRINT (%s) to config...\n", s));
 709                        break;
 710
 711                case CMAJOR:    /* major number */
 712                        if (dgap_checknode(p))
 713                                return(-1);
 714                        if ( (p->next = dgap_newnode(JNODE)) == NULL ) {
 715                                dgap_err("out of memory");
 716                                return(-1);
 717                        }
 718                        p = p->next;
 719                        s = dgap_getword(in);
 720                        if (s == NULL) {
 721                                dgap_err("unexpected end of file");
 722                                return(-1);
 723                        }
 724                        p->u.majornumber = simple_strtol(s, &s2, 0);
 725                        if ((int)strlen(s) > (int)(s2 - s)) {
 726                                dgap_err("bad number for major number");
 727                                return(-1);
 728                        }
 729                        DPR_INIT(("Adding CMAJOR (%s) to config...\n", s));
 730                        break;
 731
 732                case ALTPIN:    /* altpin setting */
 733                        if (dgap_checknode(p))
 734                                return(-1);
 735                        if ( (p->next = dgap_newnode(ANODE)) == NULL ) {
 736                                dgap_err("out of memory");
 737                                return(-1);
 738                        }
 739                        p = p->next;
 740                        s = dgap_getword(in);
 741                        if (s == NULL) {
 742                                dgap_err("unexpected end of file");
 743                                return(-1);
 744                        }
 745                        p->u.altpin = simple_strtol(s, &s2, 0);
 746                        if ((int)strlen(s) > (int)(s2 - s)) {
 747                                dgap_err("bad number for altpin");
 748                                return(-1);
 749                        }
 750                        DPR_INIT(("Adding ALTPIN (%s) to config...\n", s));
 751                        break;
 752
 753                case USEINTR:           /* enable interrupt setting */
 754                        if (dgap_checknode(p))
 755                                return(-1);
 756                        if ( (p->next = dgap_newnode(INTRNODE)) == NULL ) {
 757                                dgap_err("out of memory");
 758                                return(-1);
 759                        }
 760                        p = p->next;
 761                        s = dgap_getword(in);
 762                        if (s == NULL) {
 763                                dgap_err("unexpected end of file");
 764                                return(-1);
 765                        }
 766                        p->u.useintr = simple_strtol(s, &s2, 0);
 767                        if ((int)strlen(s) > (int)(s2 - s)) {
 768                                dgap_err("bad number for useintr");
 769                                return(-1);
 770                        }
 771                        DPR_INIT(("Adding USEINTR (%s) to config...\n", s));
 772                        break;
 773
 774                case TTSIZ:     /* size of tty structure */
 775                        if (dgap_checknode(p))
 776                                return(-1);
 777                        if ( (p->next = dgap_newnode(TSNODE)) == NULL ) {
 778                                dgap_err("out of memory");
 779                                return(-1);
 780                        }
 781                        p = p->next;
 782                        s = dgap_getword(in);
 783                        if (s == NULL) {
 784                                dgap_err("unexpected end of file");
 785                                return(-1);
 786                        }
 787                        p->u.ttysize = simple_strtol(s, &s2, 0);
 788                        if ((int)strlen(s) > (int)(s2 - s)) {
 789                                dgap_err("bad number for ttysize");
 790                                return(-1);
 791                        }
 792                        DPR_INIT(("Adding TTSIZ (%s) to config...\n", s));
 793                        break;
 794
 795                case CHSIZ:     /* channel structure size */
 796                        if (dgap_checknode(p))
 797                                return(-1);
 798                        if ( (p->next = dgap_newnode(CSNODE)) == NULL ) {
 799                                dgap_err("out of memory");
 800                                return(-1);
 801                        }
 802                        p = p->next;
 803                        s = dgap_getword(in);
 804                        if (s == NULL) {
 805                                dgap_err("unexpected end of file");
 806                                return(-1);
 807                        }
 808                        p->u.chsize = simple_strtol(s, &s2, 0);
 809                        if ((int)strlen(s) > (int)(s2 - s)) {
 810                                dgap_err("bad number for chsize");
 811                                return(-1);
 812                        }
 813                        DPR_INIT(("Adding CHSIZE (%s) to config...\n", s));
 814                        break;
 815
 816                case BSSIZ:     /* board structure size */
 817                        if (dgap_checknode(p))
 818                                return(-1);
 819                        if ( (p->next = dgap_newnode(BSNODE)) == NULL ) {
 820                                dgap_err("out of memory");
 821                                return(-1);
 822                        }
 823                        p = p->next;
 824                        s = dgap_getword(in);
 825                        if (s == NULL) {
 826                                dgap_err("unexpected end of file");
 827                                return(-1);
 828                        }
 829                        p->u.bssize = simple_strtol(s, &s2, 0);
 830                        if ((int)strlen(s) > (int)(s2 - s)) {
 831                                dgap_err("bad number for bssize");
 832                                return(-1);
 833                        }
 834                        DPR_INIT(("Adding BSSIZ (%s) to config...\n", s));
 835                        break;
 836
 837                case UNTSIZ:    /* sched structure size */
 838                        if (dgap_checknode(p))
 839                                return(-1);
 840                        if ( (p->next = dgap_newnode(USNODE)) == NULL ) {
 841                                dgap_err("out of memory");
 842                                return(-1);
 843                        }
 844                        p = p->next;
 845                        s = dgap_getword(in);
 846                        if (s == NULL) {
 847                                dgap_err("unexpected end of file");
 848                                return(-1);
 849                        }
 850                        p->u.unsize = simple_strtol(s, &s2, 0);
 851                        if ((int)strlen(s) > (int)(s2 - s)) {
 852                                dgap_err("bad number for schedsize");
 853                                return(-1);
 854                        }
 855                        DPR_INIT(("Adding UNTSIZ (%s) to config...\n", s));
 856                        break;
 857
 858                case F2SIZ:     /* f2200 structure size */
 859                        if (dgap_checknode(p))
 860                                return(-1);
 861                        if ( (p->next = dgap_newnode(FSNODE)) == NULL ) {
 862                                dgap_err("out of memory");
 863                                return(-1);
 864                        }
 865                        p = p->next;
 866                        s = dgap_getword(in);
 867                        if (s == NULL) {
 868                                dgap_err("unexpected end of file");
 869                                return(-1);
 870                        }
 871                        p->u.f2size = simple_strtol(s, &s2, 0);
 872                        if ((int)strlen(s) > (int)(s2 - s)) {
 873                                dgap_err("bad number for f2200size");
 874                                return(-1);
 875                        }
 876                        DPR_INIT(("Adding F2SIZ (%s) to config...\n", s));
 877                        break;
 878
 879                case VPSIZ:     /* vpix structure size */
 880                        if (dgap_checknode(p))
 881                                return(-1);
 882                        if ( (p->next = dgap_newnode(VSNODE)) == NULL ) {
 883                                dgap_err("out of memory");
 884                                return(-1);
 885                        }
 886                        p = p->next;
 887                        s = dgap_getword(in);
 888                        if (s == NULL) {
 889                                dgap_err("unexpected end of file");
 890                                return(-1);
 891                        }
 892                        p->u.vpixsize = simple_strtol(s, &s2, 0);
 893                        if ((int)strlen(s) > (int)(s2 - s)) {
 894                                dgap_err("bad number for vpixsize");
 895                                return(-1);
 896                        }
 897                        DPR_INIT(("Adding VPSIZ (%s) to config...\n", s));
 898                        break;
 899                }
 900        }
 901}
 902
 903
 904/*
 905 * dgap_sindex: much like index(), but it looks for a match of any character in
 906 * the group, and returns that position.  If the first character is a ^, then
 907 * this will match the first occurrence not in that group.
 908 */
 909static char *dgap_sindex (char *string, char *group)
 910{
 911        char    *ptr;
 912
 913        if (!string || !group)
 914                return (char *) NULL;
 915
 916        if (*group == '^') {   
 917                group++;
 918                for (; *string; string++) {
 919                        for (ptr = group; *ptr; ptr++) {
 920                                if (*ptr == *string)
 921                                        break;
 922                        }
 923                        if (*ptr == '\0')
 924                                return string;
 925                }
 926        }   
 927        else {
 928                for (; *string; string++) {
 929                        for (ptr = group; *ptr; ptr++) {
 930                                if (*ptr == *string)
 931                                        return string;
 932                        }
 933                }
 934        }
 935
 936        return (char *) NULL;
 937}
 938
 939
 940/*
 941 * Get a token from the input file; return 0 if end of file is reached
 942 */
 943static int dgap_gettok(char **in, struct cnode *p)
 944{
 945        char    *w;
 946        struct toklist *t;
 947        
 948        if (strstr(dgap_cword, "boar")) {
 949                w = dgap_getword(in);
 950                snprintf(dgap_cword, MAXCWORD, "%s", w);
 951                for (t = dgap_tlist; t->token != 0; t++) {
 952                        if ( !strcmp(w, t->string)) {
 953                                return(t->token);
 954                        } 
 955                }
 956                dgap_err("board !!type not specified");
 957                return(1);
 958        }
 959        else {
 960                while ( (w = dgap_getword(in)) != NULL ) {
 961                        snprintf(dgap_cword, MAXCWORD, "%s", w);
 962                        for (t = dgap_tlist; t->token != 0; t++) {
 963                                if ( !strcmp(w, t->string) )
 964                                        return(t->token);
 965                        }
 966                }
 967                return(0);
 968        }
 969}
 970
 971
 972/*
 973 * get a word from the input stream, also keep track of current line number.
 974 * words are separated by whitespace.
 975 */
 976static char *dgap_getword(char **in)
 977{
 978        char *ret_ptr = *in;
 979
 980        char *ptr = dgap_sindex(*in, " \t\n");
 981
 982        /* If no word found, return null */
 983        if (!ptr)
 984                return NULL;
 985
 986        /* Mark new location for our buffer */
 987        *ptr = '\0';
 988        *in = ptr + 1;
 989
 990        /* Eat any extra spaces/tabs/newlines that might be present */
 991        while (*in && **in && ((**in == ' ') || (**in == '\t') || (**in == '\n'))) {
 992                **in = '\0';
 993                *in = *in + 1;
 994        }
 995
 996        return ret_ptr;
 997}
 998
 999
1000/*
1001 * print an error message, giving the line number in the file where
1002 * the error occurred.
1003 */
1004static void dgap_err(char *s)
1005{
1006        printk("DGAP: parse: %s\n", s);
1007}
1008
1009
1010/*
1011 * allocate a new configuration node of type t
1012 */
1013static struct cnode *dgap_newnode(int t)
1014{
1015        struct cnode *n;
1016
1017        n = kmalloc(sizeof(struct cnode), GFP_ATOMIC);
1018        if (n != NULL) {
1019                memset((char *)n, 0, sizeof(struct cnode));
1020                n->type = t;
1021        }
1022        return(n);
1023}
1024
1025
1026/*
1027 * dgap_checknode: see if all the necessary info has been supplied for a node
1028 * before creating the next node.
1029 */
1030static int dgap_checknode(struct cnode *p)
1031{
1032        switch (p->type) {
1033        case BNODE:
1034                if (p->u.board.v_type == 0) {
1035                        dgap_err("board type !not specified");
1036                        return(1);
1037                }
1038
1039                return(0);
1040
1041        case LNODE:
1042                if (p->u.line.v_speed == 0) {
1043                        dgap_err("line speed not specified");
1044                        return(1);
1045                }
1046                return(0);
1047
1048        case CNODE:
1049                if (p->u.conc.v_type == 0) {
1050                        dgap_err("concentrator type not specified");
1051                        return(1);
1052                }
1053                if (p->u.conc.v_speed == 0) {
1054                        dgap_err("concentrator line speed not specified");
1055                        return(1);
1056                }
1057                if (p->u.conc.v_nport == 0) {
1058                        dgap_err("number of ports on concentrator not specified");
1059                        return(1);
1060                }
1061                if (p->u.conc.v_id == 0) {
1062                        dgap_err("concentrator id letter not specified");
1063                        return(1);
1064                }
1065                return(0);
1066
1067        case MNODE:
1068                if (p->u.module.v_type == 0) {
1069                        dgap_err("EBI module type not specified");
1070                        return(1);
1071                }
1072                if (p->u.module.v_nport == 0) {
1073                        dgap_err("number of ports on EBI module not specified");
1074                        return(1);
1075                }
1076                if (p->u.module.v_id == 0) {
1077                        dgap_err("EBI module id letter not specified");
1078                        return(1);
1079                }
1080                return(0);
1081        }
1082        return(0);
1083}
1084
1085/*
1086 * save a string somewhere
1087 */
1088static char     *dgap_savestring(char *s)
1089{
1090        char    *p;
1091        if ( (p = kmalloc(strlen(s) + 1, GFP_ATOMIC) ) != NULL) {
1092                strcpy(p, s);
1093        }
1094        return(p);
1095}
1096
1097
1098/*
1099 * Given a board pointer, returns whether we should use interrupts or not.
1100 */
1101uint dgap_config_get_useintr(struct board_t *bd)
1102{
1103        struct cnode *p = NULL;
1104
1105        if (!bd)
1106                return(0);
1107
1108        for (p = bd->bd_config; p; p = p->next) {
1109                switch (p->type) {
1110                case INTRNODE:
1111                        /*
1112                         * check for pcxr types.
1113                         */
1114                        return p->u.useintr;
1115                default:
1116                        break;
1117                }
1118        }
1119
1120        /* If not found, then don't turn on interrupts. */
1121        return 0;
1122}
1123
1124
1125/*
1126 * Given a board pointer, returns whether we turn on altpin or not.
1127 */
1128uint dgap_config_get_altpin(struct board_t *bd)
1129{
1130        struct cnode *p = NULL;
1131
1132        if (!bd)
1133                return(0);
1134
1135        for (p = bd->bd_config; p; p = p->next) {
1136                switch (p->type) {
1137                case ANODE:
1138                        /*
1139                         * check for pcxr types.
1140                         */
1141                        return p->u.altpin;
1142                default:
1143                        break;
1144                }
1145        }
1146
1147        /* If not found, then don't turn on interrupts. */
1148        return 0;
1149}
1150
1151
1152
1153/*
1154 * Given a specific type of board, if found, detached link and 
1155 * returns the first occurrence in the list.
1156 */
1157struct cnode *dgap_find_config(int type, int bus, int slot)
1158{
1159        struct cnode *p, *prev = NULL, *prev2 = NULL, *found = NULL;
1160
1161        p = &dgap_head;
1162
1163        while (p->next != NULL) {
1164                prev = p;
1165                p = p->next;
1166
1167                if (p->type == BNODE) {
1168
1169                        if (p->u.board.type == type) {
1170
1171                                if (p->u.board.v_pcibus && p->u.board.pcibus != bus) {
1172                                        DPR(("Found matching board, but wrong bus position. System says bus %d, we want bus %ld\n",
1173                                                bus, p->u.board.pcibus));
1174                                        continue;
1175                                }
1176                                if (p->u.board.v_pcislot && p->u.board.pcislot != slot) {
1177                                        DPR_INIT(("Found matching board, but wrong slot position. System says slot %d, we want slot %ld\n",
1178                                                slot, p->u.board.pcislot));
1179                                        continue;
1180                                }
1181
1182                                DPR_INIT(("Matched type in config file\n"));
1183
1184                                found = p;
1185                                /*
1186                                 * Keep walking thru the list till we find the next board.
1187                                 */
1188                                while (p->next != NULL) {
1189                                        prev2 = p;
1190                                        p = p->next;
1191                                        if (p->type == BNODE) {
1192
1193                                                /*
1194                                                 * Mark the end of our 1 board chain of configs.
1195                                                 */
1196                                                prev2->next = NULL;
1197
1198                                                /*
1199                                                 * Link the "next" board to the previous board,
1200                                                 * effectively "unlinking" our board from the main config.
1201                                                 */
1202                                                prev->next = p;
1203
1204                                                return found;
1205                                        }
1206                                }
1207                                /*
1208                                 * It must be the last board in the list.
1209                                 */
1210                                prev->next = NULL;
1211                                return found;
1212                        }
1213                }
1214        }
1215        return NULL;
1216}
1217
1218/*
1219 * Given a board pointer, walks the config link, counting up
1220 * all ports user specified should be on the board.
1221 * (This does NOT mean they are all actually present right now tho)
1222 */
1223uint dgap_config_get_number_of_ports(struct board_t *bd)
1224{
1225        int count = 0;
1226        struct cnode *p = NULL;
1227
1228        if (!bd)
1229                return(0);
1230
1231        for (p = bd->bd_config; p; p = p->next) {
1232
1233                switch (p->type) {
1234                case BNODE:
1235                        /*
1236                         * check for pcxr types.
1237                         */
1238                        if (p->u.board.type > EPCFE)
1239                                count += p->u.board.nport;
1240                        break;
1241                case CNODE:
1242                        count += p->u.conc.nport;
1243                        break;
1244                case MNODE:
1245                        count += p->u.module.nport;
1246                        break;
1247                }
1248        }
1249        return (count);
1250}
1251
1252char *dgap_create_config_string(struct board_t *bd, char *string)
1253{
1254        char *ptr = string;
1255        struct cnode *p = NULL;
1256        struct cnode *q = NULL;
1257        int speed;
1258
1259        if (!bd) {
1260                *ptr = 0xff;
1261                return string;
1262        }
1263
1264        for (p = bd->bd_config; p; p = p->next) {
1265
1266                switch (p->type) {
1267                case LNODE:
1268                        *ptr = '\0';
1269                        ptr++;
1270                        *ptr = p->u.line.speed;
1271                        ptr++;
1272                        break;
1273                case CNODE:
1274                        /*
1275                         * Because the EPC/con concentrators can have EM modules
1276                         * hanging off of them, we have to walk ahead in the list
1277                         * and keep adding the number of ports on each EM to the config.
1278                         * UGH!
1279                         */
1280                        speed = p->u.conc.speed;
1281                        q = p->next;
1282                        if ((q != NULL) && (q->type == MNODE) ) {
1283                                *ptr = (p->u.conc.nport + 0x80);
1284                                ptr++;
1285                                p = q;
1286                                while ((q->next != NULL) && (q->next->type) == MNODE) {
1287                                        *ptr = (q->u.module.nport + 0x80);
1288                                        ptr++;
1289                                        p = q;
1290                                        q = q->next;
1291                                }
1292                                *ptr = q->u.module.nport;
1293                                ptr++;
1294                        } else {
1295                                *ptr = p->u.conc.nport;
1296                                ptr++;
1297                        }
1298
1299                        *ptr = speed;
1300                        ptr++;
1301                        break;
1302                }
1303        }
1304
1305        *ptr = 0xff;
1306        return string;
1307}
1308
1309
1310
1311char *dgap_get_config_letters(struct board_t *bd, char *string)
1312{
1313        int found = FALSE;
1314        char *ptr = string;
1315        struct cnode *cptr = NULL;
1316        int len = 0;
1317        int left = MAXTTYNAMELEN;
1318
1319        if (!bd) {
1320                return "<NULL>";
1321        }
1322
1323        for (cptr = bd->bd_config; cptr; cptr = cptr->next) {
1324
1325                if ((cptr->type == BNODE) &&
1326                     ((cptr->u.board.type == APORT2_920P) || (cptr->u.board.type == APORT4_920P) ||
1327                     (cptr->u.board.type == APORT8_920P) || (cptr->u.board.type == PAPORT4) ||
1328                     (cptr->u.board.type == PAPORT8))) {
1329
1330                        found = TRUE;
1331                }
1332
1333                if (cptr->type == TNODE && found == TRUE) {
1334                        char *ptr1;
1335                        if (strstr(cptr->u.ttyname, "tty")) {
1336                                ptr1 = cptr->u.ttyname;
1337                                ptr1 += 3;
1338                        }
1339                        else {
1340                                ptr1 = cptr->u.ttyname;
1341                        }
1342                        if (ptr1) {
1343                                len = snprintf(ptr, left, "%s", ptr1);
1344                                left -= len;
1345                                ptr  += len;
1346                                if (left <= 0)
1347                                        break;
1348                        }
1349                }
1350
1351                if (cptr->type == CNODE) {
1352                        if (cptr->u.conc.id) {
1353                                len = snprintf(ptr, left, "%s", cptr->u.conc.id);
1354                                left -= len;
1355                                ptr  += len;
1356                                if (left <= 0)
1357                                        break;
1358                        }
1359                }
1360
1361                if (cptr->type == MNODE) {
1362                        if (cptr->u.module.id) {
1363                                len = snprintf(ptr, left, "%s", cptr->u.module.id);
1364                                left -= len;
1365                                ptr  += len;
1366                                if (left <= 0)
1367                                        break;
1368                        }
1369                }
1370        }
1371
1372        return string;
1373}
1374