blob: ff9d19449b43c1dc41d8b0a8ba0e9bdc3c2a0116 [file] [log] [blame]
/*
* 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 occurrence 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;
n = kmalloc(sizeof(struct cnode), GFP_ATOMIC);
if (n != 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 occurrence 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;
}