]> Pileus Git - ~andy/linux/blob - drivers/staging/dgap/dgap_parse.c
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[~andy/linux] / 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/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  */
51 static int dgap_gettok(char **in, struct cnode *p);
52 static char *dgap_getword(char **in);
53 static char *dgap_savestring(char *s);
54 static struct cnode *dgap_newnode(int t);
55 static int dgap_checknode(struct cnode *p);
56 static void dgap_err(char *s);
57
58 /*
59  * Our needed internal static variables...
60  */
61 static struct cnode dgap_head;
62 #define MAXCWORD 200
63 static char dgap_cword[MAXCWORD];
64
65 struct toklist {
66         int     token;
67         char    *string;
68 };
69
70 static 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  */
125 int     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  */
909 static 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  */
943 static 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  */
976 static 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  */
1004 static 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  */
1013 static 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  */
1030 static 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  */
1088 static 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  */
1101 uint 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  */
1128 uint 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  */
1157 struct 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  */
1223 uint 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
1252 char *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
1311 char *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 }