/* * Copyright 2003 Digi International (www.digi.com) * Scott H Kilau * * 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 #include #include #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 ""; } 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; }