diff options
Diffstat (limited to 'drivers/staging/dgap/dgap_parse.c')
-rw-r--r-- | drivers/staging/dgap/dgap_parse.c | 1371 |
1 files changed, 1371 insertions, 0 deletions
diff --git a/drivers/staging/dgap/dgap_parse.c b/drivers/staging/dgap/dgap_parse.c new file mode 100644 index 000000000000..5497e6de0608 --- /dev/null +++ b/drivers/staging/dgap/dgap_parse.c @@ -0,0 +1,1371 @@ +/* + * Copyright 2003 Digi International (www.digi.com) + * Scott H Kilau <Scott_Kilau at digi dot com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY, EXPRESS OR IMPLIED; without even the + * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * NOTE TO LINUX KERNEL HACKERS: DO NOT REFORMAT THIS CODE! + * + * This is shared code between Digi's CVS archive and the + * Linux Kernel sources. + * Changing the source just for reformatting needlessly breaks + * our CVS diff history. + * + * Send any bug fixes/changes to: Eng.Linux at digi dot com. + * Thank you. + * + * + ***************************************************************************** + * + * dgap_parse.c - Parses the configuration information from the input file. + * + * $Id: dgap_parse.c,v 1.1 2009/10/23 14:01:57 markh Exp $ + * + */ +#include <linux/kernel.h> +#include <linux/ctype.h> +#include <linux/slab.h> + +#include "dgap_types.h" +#include "dgap_fep5.h" +#include "dgap_driver.h" +#include "dgap_conf.h" + + +/* + * Function prototypes. + */ +static int dgap_gettok(char **in, struct cnode *p); +static char *dgap_getword(char **in); +static char *dgap_savestring(char *s); +static struct cnode *dgap_newnode(int t); +static int dgap_checknode(struct cnode *p); +static void dgap_err(char *s); + +/* + * Our needed internal static variables... + */ +static struct cnode dgap_head; +#define MAXCWORD 200 +static char dgap_cword[MAXCWORD]; + +struct toklist { + int token; + char *string; +}; + +static struct toklist dgap_tlist[] = { + { BEGIN, "config_begin" }, + { END, "config_end" }, + { BOARD, "board" }, + { PCX, "Digi_AccelePort_C/X_PCI" }, /* C/X_PCI */ + { PEPC, "Digi_AccelePort_EPC/X_PCI" }, /* EPC/X_PCI */ + { PPCM, "Digi_AccelePort_Xem_PCI" }, /* PCI/Xem */ + { APORT2_920P, "Digi_AccelePort_2r_920_PCI" }, + { APORT4_920P, "Digi_AccelePort_4r_920_PCI" }, + { APORT8_920P, "Digi_AccelePort_8r_920_PCI" }, + { PAPORT4, "Digi_AccelePort_4r_PCI(EIA-232/RS-422)" }, + { PAPORT8, "Digi_AccelePort_8r_PCI(EIA-232/RS-422)" }, + { IO, "io" }, + { PCIINFO, "pciinfo" }, + { LINE, "line" }, + { CONC, "conc" }, + { CONC, "concentrator" }, + { CX, "cx" }, + { CX, "ccon" }, + { EPC, "epccon" }, + { EPC, "epc" }, + { MOD, "module" }, + { ID, "id" }, + { STARTO, "start" }, + { SPEED, "speed" }, + { CABLE, "cable" }, + { CONNECT, "connect" }, + { METHOD, "method" }, + { STATUS, "status" }, + { CUSTOM, "Custom" }, + { BASIC, "Basic" }, + { MEM, "mem" }, + { MEM, "memory" }, + { PORTS, "ports" }, + { MODEM, "modem" }, + { NPORTS, "nports" }, + { TTYN, "ttyname" }, + { CU, "cuname" }, + { PRINT, "prname" }, + { CMAJOR, "major" }, + { ALTPIN, "altpin" }, + { USEINTR, "useintr" }, + { TTSIZ, "ttysize" }, + { CHSIZ, "chsize" }, + { BSSIZ, "boardsize" }, + { UNTSIZ, "schedsize" }, + { F2SIZ, "f2200size" }, + { VPSIZ, "vpixsize" }, + { 0, NULL } +}; + + +/* + * Parse a configuration file read into memory as a string. + */ +int dgap_parsefile(char **in, int Remove) +{ + struct cnode *p, *brd, *line, *conc; + int rc; + char *s = NULL, *s2 = NULL; + int linecnt = 0; + + p = &dgap_head; + brd = line = conc = NULL; + + /* perhaps we are adding to an existing list? */ + while (p->next != NULL) { + p = p->next; + } + + /* file must start with a BEGIN */ + while ( (rc = dgap_gettok(in,p)) != BEGIN ) { + if (rc == 0) { + dgap_err("unexpected EOF"); + return(-1); + } + } + + for (; ; ) { + rc = dgap_gettok(in,p); + if (rc == 0) { + dgap_err("unexpected EOF"); + return(-1); + } + + switch (rc) { + case 0: + dgap_err("unexpected end of file"); + return(-1); + + case BEGIN: /* should only be 1 begin */ + dgap_err("unexpected config_begin\n"); + return(-1); + + case END: + return(0); + + case BOARD: /* board info */ + if (dgap_checknode(p)) + return(-1); + if ( (p->next = dgap_newnode(BNODE)) == NULL ) { + dgap_err("out of memory"); + return(-1); + } + p = p->next; + + p->u.board.status = dgap_savestring("No"); + line = conc = NULL; + brd = p; + linecnt = -1; + break; + + case APORT2_920P: /* AccelePort_4 */ + if (p->type != BNODE) { + dgap_err("unexpected Digi_2r_920 string"); + return(-1); + } + p->u.board.type = APORT2_920P; + p->u.board.v_type = 1; + DPR_INIT(("Adding Digi_2r_920 PCI to config...\n")); + break; + + case APORT4_920P: /* AccelePort_4 */ + if (p->type != BNODE) { + dgap_err("unexpected Digi_4r_920 string"); + return(-1); + } + p->u.board.type = APORT4_920P; + p->u.board.v_type = 1; + DPR_INIT(("Adding Digi_4r_920 PCI to config...\n")); + break; + + case APORT8_920P: /* AccelePort_8 */ + if (p->type != BNODE) { + dgap_err("unexpected Digi_8r_920 string"); + return(-1); + } + p->u.board.type = APORT8_920P; + p->u.board.v_type = 1; + DPR_INIT(("Adding Digi_8r_920 PCI to config...\n")); + break; + + case PAPORT4: /* AccelePort_4 PCI */ + if (p->type != BNODE) { + dgap_err("unexpected Digi_4r(PCI) string"); + return(-1); + } + p->u.board.type = PAPORT4; + p->u.board.v_type = 1; + DPR_INIT(("Adding Digi_4r PCI to config...\n")); + break; + + case PAPORT8: /* AccelePort_8 PCI */ + if (p->type != BNODE) { + dgap_err("unexpected Digi_8r string"); + return(-1); + } + p->u.board.type = PAPORT8; + p->u.board.v_type = 1; + DPR_INIT(("Adding Digi_8r PCI to config...\n")); + break; + + case PCX: /* PCI C/X */ + if (p->type != BNODE) { + dgap_err("unexpected Digi_C/X_(PCI) string"); + return(-1); + } + p->u.board.type = PCX; + p->u.board.v_type = 1; + p->u.board.conc1 = 0; + p->u.board.conc2 = 0; + p->u.board.module1 = 0; + p->u.board.module2 = 0; + DPR_INIT(("Adding PCI C/X to config...\n")); + break; + + case PEPC: /* PCI EPC/X */ + if (p->type != BNODE) { + dgap_err("unexpected \"Digi_EPC/X_(PCI)\" string"); + return(-1); + } + p->u.board.type = PEPC; + p->u.board.v_type = 1; + p->u.board.conc1 = 0; + p->u.board.conc2 = 0; + p->u.board.module1 = 0; + p->u.board.module2 = 0; + DPR_INIT(("Adding PCI EPC/X to config...\n")); + break; + + case PPCM: /* PCI/Xem */ + if (p->type != BNODE) { + dgap_err("unexpected PCI/Xem string"); + return(-1); + } + p->u.board.type = PPCM; + p->u.board.v_type = 1; + p->u.board.conc1 = 0; + p->u.board.conc2 = 0; + DPR_INIT(("Adding PCI XEM to config...\n")); + break; + + case IO: /* i/o port */ + if (p->type != BNODE) { + dgap_err("IO port only vaild for boards"); + return(-1); + } + s = dgap_getword(in); + if (s == NULL) { + dgap_err("unexpected end of file"); + return(-1); + } + p->u.board.portstr = dgap_savestring(s); + p->u.board.port = (short)simple_strtol(s, &s2, 0); + if ((short)strlen(s) > (short)(s2 - s)) { + dgap_err("bad number for IO port"); + return(-1); + } + p->u.board.v_port = 1; + DPR_INIT(("Adding IO (%s) to config...\n", s)); + break; + + case MEM: /* memory address */ + if (p->type != BNODE) { + dgap_err("memory address only vaild for boards"); + return(-1); + } + s = dgap_getword(in); + if (s == NULL) { + dgap_err("unexpected end of file"); + return(-1); + } + p->u.board.addrstr = dgap_savestring(s); + p->u.board.addr = simple_strtoul(s, &s2, 0); + if ((int)strlen(s) > (int)(s2 - s)) { + dgap_err("bad number for memory address"); + return(-1); + } + p->u.board.v_addr = 1; + DPR_INIT(("Adding MEM (%s) to config...\n", s)); + break; + + case PCIINFO: /* pci information */ + if (p->type != BNODE) { + dgap_err("memory address only vaild for boards"); + return(-1); + } + s = dgap_getword(in); + if (s == NULL) { + dgap_err("unexpected end of file"); + return(-1); + } + p->u.board.pcibusstr = dgap_savestring(s); + p->u.board.pcibus = simple_strtoul(s, &s2, 0); + if ((int)strlen(s) > (int)(s2 - s)) { + dgap_err("bad number for pci bus"); + return(-1); + } + p->u.board.v_pcibus = 1; + s = dgap_getword(in); + if (s == NULL) { + dgap_err("unexpected end of file"); + return(-1); + } + p->u.board.pcislotstr = dgap_savestring(s); + p->u.board.pcislot = simple_strtoul(s, &s2, 0); + if ((int)strlen(s) > (int)(s2 - s)) { + dgap_err("bad number for pci slot"); + return(-1); + } + p->u.board.v_pcislot = 1; + + DPR_INIT(("Adding PCIINFO (%s %s) to config...\n", p->u.board.pcibusstr, + p->u.board.pcislotstr)); + break; + + case METHOD: + if (p->type != BNODE) { + dgap_err("install method only vaild for boards"); + return(-1); + } + s = dgap_getword(in); + if (s == NULL) { + dgap_err("unexpected end of file"); + return(-1); + } + p->u.board.method = dgap_savestring(s); + p->u.board.v_method = 1; + DPR_INIT(("Adding METHOD (%s) to config...\n", s)); + break; + + case STATUS: + if (p->type != BNODE) { + dgap_err("config status only vaild for boards"); + return(-1); + } + s = dgap_getword(in); + if (s == NULL) { + dgap_err("unexpected end of file"); + return(-1); + } + p->u.board.status = dgap_savestring(s); + DPR_INIT(("Adding STATUS (%s) to config...\n", s)); + break; + + case NPORTS: /* number of ports */ + if (p->type == BNODE) { + s = dgap_getword(in); + if (s == NULL) { + dgap_err("unexpected end of file"); + return(-1); + } + p->u.board.nport = (char)simple_strtol(s, &s2, 0); + if ((int)strlen(s) > (int)(s2 - s)) { + dgap_err("bad number for number of ports"); + return(-1); + } + p->u.board.v_nport = 1; + } else if (p->type == CNODE) { + s = dgap_getword(in); + if (s == NULL) { + dgap_err("unexpected end of file"); + return(-1); + } + p->u.conc.nport = (char)simple_strtol(s, &s2, 0); + if ((int)strlen(s) > (int)(s2 - s)) { + dgap_err("bad number for number of ports"); + return(-1); + } + p->u.conc.v_nport = 1; + } else if (p->type == MNODE) { + s = dgap_getword(in); + if (s == NULL) { + dgap_err("unexpected end of file"); + return(-1); + } + p->u.module.nport = (char)simple_strtol(s, &s2, 0); + if ((int)strlen(s) > (int)(s2 - s)) { + dgap_err("bad number for number of ports"); + return(-1); + } + p->u.module.v_nport = 1; + } else { + dgap_err("nports only valid for concentrators or modules"); + return(-1); + } + DPR_INIT(("Adding NPORTS (%s) to config...\n", s)); + break; + + case ID: /* letter ID used in tty name */ + s = dgap_getword(in); + if (s == NULL) { + dgap_err("unexpected end of file"); + return(-1); + } + + p->u.board.status = dgap_savestring(s); + + if (p->type == CNODE) { + p->u.conc.id = dgap_savestring(s); + p->u.conc.v_id = 1; + } else if (p->type == MNODE) { + p->u.module.id = dgap_savestring(s); + p->u.module.v_id = 1; + } else { + dgap_err("id only valid for concentrators or modules"); + return(-1); + } + DPR_INIT(("Adding ID (%s) to config...\n", s)); + break; + + case STARTO: /* start offset of ID */ + if (p->type == BNODE) { + s = dgap_getword(in); + if (s == NULL) { + dgap_err("unexpected end of file"); + return(-1); + } + p->u.board.start = simple_strtol(s, &s2, 0); + if ((int)strlen(s) > (int)(s2 - s)) { + dgap_err("bad number for start of tty count"); + return(-1); + } + p->u.board.v_start = 1; + } else if (p->type == CNODE) { + s = dgap_getword(in); + if (s == NULL) { + dgap_err("unexpected end of file"); + return(-1); + } + p->u.conc.start = simple_strtol(s, &s2, 0); + if ((int)strlen(s) > (int)(s2 - s)) { + dgap_err("bad number for start of tty count"); + return(-1); + } + p->u.conc.v_start = 1; + } else if (p->type == MNODE) { + s = dgap_getword(in); + if (s == NULL) { + dgap_err("unexpected end of file"); + return(-1); + } + p->u.module.start = simple_strtol(s, &s2, 0); + if ((int)strlen(s) > (int)(s2 - s)) { + dgap_err("bad number for start of tty count"); + return(-1); + } + p->u.module.v_start = 1; + } else { + dgap_err("start only valid for concentrators or modules"); + return(-1); + } + DPR_INIT(("Adding START (%s) to config...\n", s)); + break; + + case TTYN: /* tty name prefix */ + if (dgap_checknode(p)) + return(-1); + if ( (p->next = dgap_newnode(TNODE)) == NULL ) { + dgap_err("out of memory"); + return(-1); + } + p = p->next; + if ( (s = dgap_getword(in)) == NULL ) { + dgap_err("unexpeced end of file"); + return(-1); + } + if ( (p->u.ttyname = dgap_savestring(s)) == NULL ) { + dgap_err("out of memory"); + return(-1); + } + DPR_INIT(("Adding TTY (%s) to config...\n", s)); + break; + + case CU: /* cu name prefix */ + if (dgap_checknode(p)) + return(-1); + if ( (p->next = dgap_newnode(CUNODE)) == NULL ) { + dgap_err("out of memory"); + return(-1); + } + p = p->next; + if ( (s = dgap_getword(in)) == NULL ) { + dgap_err("unexpeced end of file"); + return(-1); + } + if ( (p->u.cuname = dgap_savestring(s)) == NULL ) { + dgap_err("out of memory"); + return(-1); + } + DPR_INIT(("Adding CU (%s) to config...\n", s)); + break; + + case LINE: /* line information */ + if (dgap_checknode(p)) + return(-1); + if (brd == NULL) { + dgap_err("must specify board before line info"); + return(-1); + } + switch (brd->u.board.type) { + case PPCM: + dgap_err("line not vaild for PC/em"); + return(-1); + } + if ( (p->next = dgap_newnode(LNODE)) == NULL ) { + dgap_err("out of memory"); + return(-1); + } + p = p->next; + conc = NULL; + line = p; + linecnt++; + DPR_INIT(("Adding LINE to config...\n")); + break; + + case CONC: /* concentrator information */ + if (dgap_checknode(p)) + return(-1); + if (line == NULL) { + dgap_err("must specify line info before concentrator"); + return(-1); + } + if ( (p->next = dgap_newnode(CNODE)) == NULL ) { + dgap_err("out of memory"); + return(-1); + } + p = p->next; + conc = p; + if (linecnt) + brd->u.board.conc2++; + else + brd->u.board.conc1++; + + DPR_INIT(("Adding CONC to config...\n")); + break; + + case CX: /* c/x type concentrator */ + if (p->type != CNODE) { + dgap_err("cx only valid for concentrators"); + return(-1); + } + p->u.conc.type = CX; + p->u.conc.v_type = 1; + DPR_INIT(("Adding CX to config...\n")); + break; + + case EPC: /* epc type concentrator */ + if (p->type != CNODE) { + dgap_err("cx only valid for concentrators"); + return(-1); + } + p->u.conc.type = EPC; + p->u.conc.v_type = 1; + DPR_INIT(("Adding EPC to config...\n")); + break; + + case MOD: /* EBI module */ + if (dgap_checknode(p)) + return(-1); + if (brd == NULL) { + dgap_err("must specify board info before EBI modules"); + return(-1); + } + switch (brd->u.board.type) { + case PPCM: + linecnt = 0; + break; + default: + if (conc == NULL) { + dgap_err("must specify concentrator info before EBI module"); + return(-1); + } + } + if ( (p->next = dgap_newnode(MNODE)) == NULL ) { + dgap_err("out of memory"); + return(-1); + } + p = p->next; + if (linecnt) + brd->u.board.module2++; + else + brd->u.board.module1++; + + DPR_INIT(("Adding MOD to config...\n")); + break; + + case PORTS: /* ports type EBI module */ + if (p->type != MNODE) { + dgap_err("ports only valid for EBI modules"); + return(-1); + } + p->u.module.type = PORTS; + p->u.module.v_type = 1; + DPR_INIT(("Adding PORTS to config...\n")); + break; + + case MODEM: /* ports type EBI module */ + if (p->type != MNODE) { + dgap_err("modem only valid for modem modules"); + return(-1); + } + p->u.module.type = MODEM; + p->u.module.v_type = 1; + DPR_INIT(("Adding MODEM to config...\n")); + break; + + case CABLE: + if (p->type == LNODE) { + if ((s = dgap_getword(in)) == NULL) { + dgap_err("unexpected end of file"); + return(-1); + } + p->u.line.cable = dgap_savestring(s); + p->u.line.v_cable = 1; + } + DPR_INIT(("Adding CABLE (%s) to config...\n", s)); + break; + + case SPEED: /* sync line speed indication */ + if (p->type == LNODE) { + s = dgap_getword(in); + if (s == NULL) { + dgap_err("unexpected end of file"); + return(-1); + } + p->u.line.speed = (char)simple_strtol(s, &s2, 0); + if ((short)strlen(s) > (short)(s2 - s)) { + dgap_err("bad number for line speed"); + return(-1); + } + p->u.line.v_speed = 1; + } else if (p->type == CNODE) { + s = dgap_getword(in); + if (s == NULL) { + dgap_err("unexpected end of file"); + return(-1); + } + p->u.conc.speed = (char)simple_strtol(s, &s2, 0); + if ((short)strlen(s) > (short)(s2 - s)) { + dgap_err("bad number for line speed"); + return(-1); + } + p->u.conc.v_speed = 1; + } else { + dgap_err("speed valid only for lines or concentrators."); + return(-1); + } + DPR_INIT(("Adding SPEED (%s) to config...\n", s)); + break; + + case CONNECT: + if (p->type == CNODE) { + if ((s = dgap_getword(in)) == NULL) { + dgap_err("unexpected end of file"); + return(-1); + } + p->u.conc.connect = dgap_savestring(s); + p->u.conc.v_connect = 1; + } + DPR_INIT(("Adding CONNECT (%s) to config...\n", s)); + break; + case PRINT: /* transparent print name prefix */ + if (dgap_checknode(p)) + return(-1); + if ( (p->next = dgap_newnode(PNODE)) == NULL ) { + dgap_err("out of memory"); + return(-1); + } + p = p->next; + if ( (s = dgap_getword(in)) == NULL ) { + dgap_err("unexpeced end of file"); + return(-1); + } + if ( (p->u.printname = dgap_savestring(s)) == NULL ) { + dgap_err("out of memory"); + return(-1); + } + DPR_INIT(("Adding PRINT (%s) to config...\n", s)); + break; + + case CMAJOR: /* major number */ + if (dgap_checknode(p)) + return(-1); + if ( (p->next = dgap_newnode(JNODE)) == NULL ) { + dgap_err("out of memory"); + return(-1); + } + p = p->next; + s = dgap_getword(in); + if (s == NULL) { + dgap_err("unexpected end of file"); + return(-1); + } + p->u.majornumber = simple_strtol(s, &s2, 0); + if ((int)strlen(s) > (int)(s2 - s)) { + dgap_err("bad number for major number"); + return(-1); + } + DPR_INIT(("Adding CMAJOR (%s) to config...\n", s)); + break; + + case ALTPIN: /* altpin setting */ + if (dgap_checknode(p)) + return(-1); + if ( (p->next = dgap_newnode(ANODE)) == NULL ) { + dgap_err("out of memory"); + return(-1); + } + p = p->next; + s = dgap_getword(in); + if (s == NULL) { + dgap_err("unexpected end of file"); + return(-1); + } + p->u.altpin = simple_strtol(s, &s2, 0); + if ((int)strlen(s) > (int)(s2 - s)) { + dgap_err("bad number for altpin"); + return(-1); + } + DPR_INIT(("Adding ALTPIN (%s) to config...\n", s)); + break; + + case USEINTR: /* enable interrupt setting */ + if (dgap_checknode(p)) + return(-1); + if ( (p->next = dgap_newnode(INTRNODE)) == NULL ) { + dgap_err("out of memory"); + return(-1); + } + p = p->next; + s = dgap_getword(in); + if (s == NULL) { + dgap_err("unexpected end of file"); + return(-1); + } + p->u.useintr = simple_strtol(s, &s2, 0); + if ((int)strlen(s) > (int)(s2 - s)) { + dgap_err("bad number for useintr"); + return(-1); + } + DPR_INIT(("Adding USEINTR (%s) to config...\n", s)); + break; + + case TTSIZ: /* size of tty structure */ + if (dgap_checknode(p)) + return(-1); + if ( (p->next = dgap_newnode(TSNODE)) == NULL ) { + dgap_err("out of memory"); + return(-1); + } + p = p->next; + s = dgap_getword(in); + if (s == NULL) { + dgap_err("unexpected end of file"); + return(-1); + } + p->u.ttysize = simple_strtol(s, &s2, 0); + if ((int)strlen(s) > (int)(s2 - s)) { + dgap_err("bad number for ttysize"); + return(-1); + } + DPR_INIT(("Adding TTSIZ (%s) to config...\n", s)); + break; + + case CHSIZ: /* channel structure size */ + if (dgap_checknode(p)) + return(-1); + if ( (p->next = dgap_newnode(CSNODE)) == NULL ) { + dgap_err("out of memory"); + return(-1); + } + p = p->next; + s = dgap_getword(in); + if (s == NULL) { + dgap_err("unexpected end of file"); + return(-1); + } + p->u.chsize = simple_strtol(s, &s2, 0); + if ((int)strlen(s) > (int)(s2 - s)) { + dgap_err("bad number for chsize"); + return(-1); + } + DPR_INIT(("Adding CHSIZE (%s) to config...\n", s)); + break; + + case BSSIZ: /* board structure size */ + if (dgap_checknode(p)) + return(-1); + if ( (p->next = dgap_newnode(BSNODE)) == NULL ) { + dgap_err("out of memory"); + return(-1); + } + p = p->next; + s = dgap_getword(in); + if (s == NULL) { + dgap_err("unexpected end of file"); + return(-1); + } + p->u.bssize = simple_strtol(s, &s2, 0); + if ((int)strlen(s) > (int)(s2 - s)) { + dgap_err("bad number for bssize"); + return(-1); + } + DPR_INIT(("Adding BSSIZ (%s) to config...\n", s)); + break; + + case UNTSIZ: /* sched structure size */ + if (dgap_checknode(p)) + return(-1); + if ( (p->next = dgap_newnode(USNODE)) == NULL ) { + dgap_err("out of memory"); + return(-1); + } + p = p->next; + s = dgap_getword(in); + if (s == NULL) { + dgap_err("unexpected end of file"); + return(-1); + } + p->u.unsize = simple_strtol(s, &s2, 0); + if ((int)strlen(s) > (int)(s2 - s)) { + dgap_err("bad number for schedsize"); + return(-1); + } + DPR_INIT(("Adding UNTSIZ (%s) to config...\n", s)); + break; + + case F2SIZ: /* f2200 structure size */ + if (dgap_checknode(p)) + return(-1); + if ( (p->next = dgap_newnode(FSNODE)) == NULL ) { + dgap_err("out of memory"); + return(-1); + } + p = p->next; + s = dgap_getword(in); + if (s == NULL) { + dgap_err("unexpected end of file"); + return(-1); + } + p->u.f2size = simple_strtol(s, &s2, 0); + if ((int)strlen(s) > (int)(s2 - s)) { + dgap_err("bad number for f2200size"); + return(-1); + } + DPR_INIT(("Adding F2SIZ (%s) to config...\n", s)); + break; + + case VPSIZ: /* vpix structure size */ + if (dgap_checknode(p)) + return(-1); + if ( (p->next = dgap_newnode(VSNODE)) == NULL ) { + dgap_err("out of memory"); + return(-1); + } + p = p->next; + s = dgap_getword(in); + if (s == NULL) { + dgap_err("unexpected end of file"); + return(-1); + } + p->u.vpixsize = simple_strtol(s, &s2, 0); + if ((int)strlen(s) > (int)(s2 - s)) { + dgap_err("bad number for vpixsize"); + return(-1); + } + DPR_INIT(("Adding VPSIZ (%s) to config...\n", s)); + break; + } + } +} + + +/* + * dgap_sindex: much like index(), but it looks for a match of any character in + * the group, and returns that position. If the first character is a ^, then + * this will match the first occurence not in that group. + */ +static char *dgap_sindex (char *string, char *group) +{ + char *ptr; + + if (!string || !group) + return (char *) NULL; + + if (*group == '^') { + group++; + for (; *string; string++) { + for (ptr = group; *ptr; ptr++) { + if (*ptr == *string) + break; + } + if (*ptr == '\0') + return string; + } + } + else { + for (; *string; string++) { + for (ptr = group; *ptr; ptr++) { + if (*ptr == *string) + return string; + } + } + } + + return (char *) NULL; +} + + +/* + * Get a token from the input file; return 0 if end of file is reached + */ +static int dgap_gettok(char **in, struct cnode *p) +{ + char *w; + struct toklist *t; + + if (strstr(dgap_cword, "boar")) { + w = dgap_getword(in); + snprintf(dgap_cword, MAXCWORD, "%s", w); + for (t = dgap_tlist; t->token != 0; t++) { + if ( !strcmp(w, t->string)) { + return(t->token); + } + } + dgap_err("board !!type not specified"); + return(1); + } + else { + while ( (w = dgap_getword(in)) != NULL ) { + snprintf(dgap_cword, MAXCWORD, "%s", w); + for (t = dgap_tlist; t->token != 0; t++) { + if ( !strcmp(w, t->string) ) + return(t->token); + } + } + return(0); + } +} + + +/* + * get a word from the input stream, also keep track of current line number. + * words are separated by whitespace. + */ +static char *dgap_getword(char **in) +{ + char *ret_ptr = *in; + + char *ptr = dgap_sindex(*in, " \t\n"); + + /* If no word found, return null */ + if (!ptr) + return NULL; + + /* Mark new location for our buffer */ + *ptr = '\0'; + *in = ptr + 1; + + /* Eat any extra spaces/tabs/newlines that might be present */ + while (*in && **in && ((**in == ' ') || (**in == '\t') || (**in == '\n'))) { + **in = '\0'; + *in = *in + 1; + } + + return ret_ptr; +} + + +/* + * print an error message, giving the line number in the file where + * the error occurred. + */ +static void dgap_err(char *s) +{ + printk("DGAP: parse: %s\n", s); +} + + +/* + * allocate a new configuration node of type t + */ +static struct cnode *dgap_newnode(int t) +{ + struct cnode *n; + if ( (n = (struct cnode *) kmalloc(sizeof(struct cnode ), GFP_ATOMIC) ) != NULL) { + memset( (char *)n, 0, sizeof(struct cnode ) ); + n->type = t; + } + return(n); +} + + +/* + * dgap_checknode: see if all the necessary info has been supplied for a node + * before creating the next node. + */ +static int dgap_checknode(struct cnode *p) +{ + switch (p->type) { + case BNODE: + if (p->u.board.v_type == 0) { + dgap_err("board type !not specified"); + return(1); + } + + return(0); + + case LNODE: + if (p->u.line.v_speed == 0) { + dgap_err("line speed not specified"); + return(1); + } + return(0); + + case CNODE: + if (p->u.conc.v_type == 0) { + dgap_err("concentrator type not specified"); + return(1); + } + if (p->u.conc.v_speed == 0) { + dgap_err("concentrator line speed not specified"); + return(1); + } + if (p->u.conc.v_nport == 0) { + dgap_err("number of ports on concentrator not specified"); + return(1); + } + if (p->u.conc.v_id == 0) { + dgap_err("concentrator id letter not specified"); + return(1); + } + return(0); + + case MNODE: + if (p->u.module.v_type == 0) { + dgap_err("EBI module type not specified"); + return(1); + } + if (p->u.module.v_nport == 0) { + dgap_err("number of ports on EBI module not specified"); + return(1); + } + if (p->u.module.v_id == 0) { + dgap_err("EBI module id letter not specified"); + return(1); + } + return(0); + } + return(0); +} + +/* + * save a string somewhere + */ +static char *dgap_savestring(char *s) +{ + char *p; + if ( (p = kmalloc(strlen(s) + 1, GFP_ATOMIC) ) != NULL) { + strcpy(p, s); + } + return(p); +} + + +/* + * Given a board pointer, returns whether we should use interrupts or not. + */ +uint dgap_config_get_useintr(struct board_t *bd) +{ + struct cnode *p = NULL; + + if (!bd) + return(0); + + for (p = bd->bd_config; p; p = p->next) { + switch (p->type) { + case INTRNODE: + /* + * check for pcxr types. + */ + return p->u.useintr; + default: + break; + } + } + + /* If not found, then don't turn on interrupts. */ + return 0; +} + + +/* + * Given a board pointer, returns whether we turn on altpin or not. + */ +uint dgap_config_get_altpin(struct board_t *bd) +{ + struct cnode *p = NULL; + + if (!bd) + return(0); + + for (p = bd->bd_config; p; p = p->next) { + switch (p->type) { + case ANODE: + /* + * check for pcxr types. + */ + return p->u.altpin; + default: + break; + } + } + + /* If not found, then don't turn on interrupts. */ + return 0; +} + + + +/* + * Given a specific type of board, if found, detached link and + * returns the first occurance in the list. + */ +struct cnode *dgap_find_config(int type, int bus, int slot) +{ + struct cnode *p, *prev = NULL, *prev2 = NULL, *found = NULL; + + p = &dgap_head; + + while (p->next != NULL) { + prev = p; + p = p->next; + + if (p->type == BNODE) { + + if (p->u.board.type == type) { + + if (p->u.board.v_pcibus && p->u.board.pcibus != bus) { + DPR(("Found matching board, but wrong bus position. System says bus %d, we want bus %ld\n", + bus, p->u.board.pcibus)); + continue; + } + if (p->u.board.v_pcislot && p->u.board.pcislot != slot) { + DPR_INIT(("Found matching board, but wrong slot position. System says slot %d, we want slot %ld\n", + slot, p->u.board.pcislot)); + continue; + } + + DPR_INIT(("Matched type in config file\n")); + + found = p; + /* + * Keep walking thru the list till we find the next board. + */ + while (p->next != NULL) { + prev2 = p; + p = p->next; + if (p->type == BNODE) { + + /* + * Mark the end of our 1 board chain of configs. + */ + prev2->next = NULL; + + /* + * Link the "next" board to the previous board, + * effectively "unlinking" our board from the main config. + */ + prev->next = p; + + return found; + } + } + /* + * It must be the last board in the list. + */ + prev->next = NULL; + return found; + } + } + } + return NULL; +} + +/* + * Given a board pointer, walks the config link, counting up + * all ports user specified should be on the board. + * (This does NOT mean they are all actually present right now tho) + */ +uint dgap_config_get_number_of_ports(struct board_t *bd) +{ + int count = 0; + struct cnode *p = NULL; + + if (!bd) + return(0); + + for (p = bd->bd_config; p; p = p->next) { + + switch (p->type) { + case BNODE: + /* + * check for pcxr types. + */ + if (p->u.board.type > EPCFE) + count += p->u.board.nport; + break; + case CNODE: + count += p->u.conc.nport; + break; + case MNODE: + count += p->u.module.nport; + break; + } + } + return (count); +} + +char *dgap_create_config_string(struct board_t *bd, char *string) +{ + char *ptr = string; + struct cnode *p = NULL; + struct cnode *q = NULL; + int speed; + + if (!bd) { + *ptr = 0xff; + return string; + } + + for (p = bd->bd_config; p; p = p->next) { + + switch (p->type) { + case LNODE: + *ptr = '\0'; + ptr++; + *ptr = p->u.line.speed; + ptr++; + break; + case CNODE: + /* + * Because the EPC/con concentrators can have EM modules + * hanging off of them, we have to walk ahead in the list + * and keep adding the number of ports on each EM to the config. + * UGH! + */ + speed = p->u.conc.speed; + q = p->next; + if ((q != NULL) && (q->type == MNODE) ) { + *ptr = (p->u.conc.nport + 0x80); + ptr++; + p = q; + while ((q->next != NULL) && (q->next->type) == MNODE) { + *ptr = (q->u.module.nport + 0x80); + ptr++; + p = q; + q = q->next; + } + *ptr = q->u.module.nport; + ptr++; + } else { + *ptr = p->u.conc.nport; + ptr++; + } + + *ptr = speed; + ptr++; + break; + } + } + + *ptr = 0xff; + return string; +} + + + +char *dgap_get_config_letters(struct board_t *bd, char *string) +{ + int found = FALSE; + char *ptr = string; + struct cnode *cptr = NULL; + int len = 0; + int left = MAXTTYNAMELEN; + + if (!bd) { + return "<NULL>"; + } + + for (cptr = bd->bd_config; cptr; cptr = cptr->next) { + + if ((cptr->type == BNODE) && + ((cptr->u.board.type == APORT2_920P) || (cptr->u.board.type == APORT4_920P) || + (cptr->u.board.type == APORT8_920P) || (cptr->u.board.type == PAPORT4) || + (cptr->u.board.type == PAPORT8))) { + + found = TRUE; + } + + if (cptr->type == TNODE && found == TRUE) { + char *ptr1; + if (strstr(cptr->u.ttyname, "tty")) { + ptr1 = cptr->u.ttyname; + ptr1 += 3; + } + else { + ptr1 = cptr->u.ttyname; + } + if (ptr1) { + len = snprintf(ptr, left, "%s", ptr1); + left -= len; + ptr += len; + if (left <= 0) + break; + } + } + + if (cptr->type == CNODE) { + if (cptr->u.conc.id) { + len = snprintf(ptr, left, "%s", cptr->u.conc.id); + left -= len; + ptr += len; + if (left <= 0) + break; + } + } + + if (cptr->type == MNODE) { + if (cptr->u.module.id) { + len = snprintf(ptr, left, "%s", cptr->u.module.id); + left -= len; + ptr += len; + if (left <= 0) + break; + } + } + } + + return string; +} |