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