2 * Copyright (c) 1995 Andrew McRae. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 * $FreeBSD: src/usr.sbin/pccard/pccardd/file.c,v 1.24.2.5 2001/06/05 07:01:40 imp Exp $
27 * $DragonFly: src/usr.sbin/pccard/pccardd/Attic/file.c,v 1.3 2004/06/19 20:38:22 joerg Exp $
33 #include <sys/types.h>
37 static int includes = 0;
42 } configfiles[MAXINCLUDES] = {{NULL, NULL, 0}, };
44 static int pushc, pusht;
46 static char *filename;
48 static char *keys[] = {
61 "debuglevel", /* 13 */
80 #define KWD_DEBUGLEVEL 13
81 #define KWD_INCLUDE 14
82 #define KWD_FUNCTION 15
85 /* for keyword compatibility with PAO/plain FreeBSD */
90 {"generic", KWD_FUNCTION},
101 static void parsefile(void);
102 static char *getline(void);
103 static char *next_tok(void);
104 static int num_tok(void);
105 static void error(char *);
106 static int keyword(char *);
107 static int irq_tok(int);
108 static int config_tok(unsigned char *);
109 static int func_tok(void);
110 static int debuglevel_tok(int);
111 static struct allocblk *ioblk_tok(int);
112 static struct allocblk *memblk_tok(int);
113 static struct driver *new_driver(char *);
114 static int iosize_tok(void);
115 static void file_include(char *);
117 static void addcmd(struct cmd **);
118 static void parse_card(int);
121 delete_card(struct card *cp)
123 struct ether *etherp, *ether_next;
124 struct card_config *configp, *config_next;
125 struct cmd *cmdp, *cmd_next;
134 /* free structures */
135 for (etherp = cp->ether; etherp; etherp = ether_next) {
136 ether_next = etherp->next;
139 for (configp = cp->config; configp; configp = config_next) {
140 config_next = configp->next;
143 for (cmdp = cp->insert; cmdp; cmdp = cmd_next) {
144 cmd_next = cmdp->next;
148 for (cmdp = cp->remove; cmdp; cmdp = cmd_next) {
149 cmd_next = cmdp->next;
157 * Read a file and parse the pcmcia configuration data.
158 * After parsing, verify the links.
164 struct card *cp, *card_next;
165 struct card *genericp, *tail_gp;
166 struct card_config *configp;
168 /* delete all card configuration data before we proceed */
171 cards = last_card = 0;
173 card_next = cp->next;
175 /* check whether this card is in use */
177 for (configp = cp->config; configp; configp = configp->next) {
178 if (configp->inuse) {
185 * don't delete entry in use for consistency.
186 * leave normal entry in the cards list,
187 * insert generic entry into the list after re-loading config files.
190 cp->next = 0; /* unchain from the cards list */
191 switch (cp->deftype) {
193 /* don't delete this entry for consistency */
194 if (debug_level >= 1) {
195 logmsg("Card \"%s\"(\"%s\") is in use, "
196 "can't change configuration\n",
197 cp->manuf, cp->version);
199 /* add this to the card list */
201 cards = last_card = cp;
203 last_card->next = cp;
209 /* generic entry must be inserted to the list later */
210 if (debug_level >= 1) {
211 logmsg("Generic entry is in use, "
212 "can't change configuration\n");
225 for (i = 0; i < MAXINCLUDES; i++) {
226 if (configfiles[i].filep) {
227 fclose(configfiles[i].filep);
228 configfiles[i].filep = NULL;
230 free(configfiles[i].filename);
234 in = fopen(name, "r");
240 configfiles[includes].filep = in;
241 filename = configfiles[includes].filename = name;
244 for (cp = cards; cp; cp = cp->next) {
246 logmsg("warning: card %s(%s) has no valid configuration\n",
247 cp->manuf, cp->version);
250 /* insert generic entries in use into the top of generic entries */
252 /* search tail of generic entries in use */
253 for (tail_gp = genericp; tail_gp->next; tail_gp = tail_gp->next)
257 * if the top of cards list is generic entry,
258 * insert generic entries in use before it.
260 if (cards && cards->deftype == DT_FUNC) {
261 tail_gp->next = cards;
266 /* search top of generic entries */
267 for (cp = cards; cp; cp = cp->next) {
268 if (cp->next && cp->next->deftype == DT_FUNC) {
274 * if we have generic entry in the cards list,
275 * insert generic entries in use into there.
278 tail_gp->next = cp->next;
284 * otherwise we don't have generic entries in
285 * cards list, just add them to the list.
290 last_card->next = genericp;
297 /* save the initial state of resource pool */
298 bcopy(io_avail, io_init, bitstr_size(IOPORTS));
299 bcopy(mem_avail, mem_init, bitstr_size(MEMBLKS));
300 bcopy(pool_irq, irq_init, sizeof(pool_irq));
308 struct allocblk *bp, *next;
314 switch (keyword(next_tok())) {
319 /* override reserved I/O blocks */
320 bit_nclear(io_avail, 0, IOPORTS-1);
321 for (bp = pool_ioblks; bp; bp = next) {
327 while ((bp = ioblk_tok(0)) != 0) {
328 if (bp->size == 0 || bp->addr == 0) {
332 bit_nset(io_avail, bp->addr,
333 bp->addr + bp->size - 1);
334 bp->next = pool_ioblks;
340 /* override reserved irqs */
341 bzero(pool_irq, sizeof(pool_irq));
342 while ((i = irq_tok(0)) > 0)
347 /* override reserved memory blocks. */
348 bit_nclear(mem_avail, 0, MEMBLKS-1);
349 for (bp = pool_mem; bp; bp = next) {
355 while ((bp = memblk_tok(0)) != 0) {
356 if (bp->size == 0 || bp->addr == 0) {
360 bit_nset(mem_avail, MEM2BIT(bp->addr),
361 MEM2BIT(bp->addr + bp->size) - 1);
368 /* Card definition. */
372 /* Function definition. */
376 i = debuglevel_tok(0);
381 incl = newstr(next_tok());
385 error("syntax error");
387 if (errors++ >= MAXERRORS) {
388 error("too many errors, giving up");
396 * Parse a card definition.
399 parse_card(int deftype)
401 char *man, *vers, *tmp;
403 unsigned char index_type;
406 struct card_config *confp, *lastp;
410 cp = xmalloc(sizeof(*cp));
411 cp->deftype = deftype;
414 man = newstr(next_tok());
415 vers = newstr(next_tok());
416 add_info = newstr(next_tok());
417 if (keyword(add_info)) {
420 cp->add_info1 = NULL;
421 cp->add_info2 = NULL;
423 cp->add_info1 = add_info;
424 add_info = newstr(next_tok());
425 if (keyword(add_info)) {
428 cp->add_info2 = NULL;
430 cp->add_info2 = add_info;
436 asprintf(&cp->logstr, "%s (%s)", man, vers);
443 cp->func_id = (u_char) func_tok();
446 fprintf(stderr, "parse_card: unknown deftype %d\n", deftype);
452 cards = last_card = cp;
454 last_card->next = cp;
458 switch (keyword(next_tok())) {
461 i = config_tok(&index_type);
463 error("illegal card config index");
466 confp = xmalloc(sizeof(*confp));
468 confp->driver = new_driver(man);
469 confp->irq = irq_tok(1);
470 confp->flags = num_tok();
471 if (confp->flags == -1) {
475 if (confp->irq < 0 || confp->irq > 15) {
476 error("illegal card IRQ value");
479 confp->index = i & 0x3F;
480 confp->index_type = index_type;
483 * If no valid driver for this config, then do not save
484 * this configuration entry.
490 for (lastp = cp->config; lastp->next;
491 lastp = lastp->next);
501 error("illegal card reset time");
508 ether = xmalloc(sizeof(*ether));
509 ether->type = ETHTYPE_GENERIC;
511 if (strcmp("attr2", tmp) == 0)
512 ether->type = ETHTYPE_ATTR2;
515 ether->value = num_tok();
516 if (ether->value == -1) {
517 error("illegal ether address offset");
522 ether->next = cp->ether;
535 iosize = iosize_tok();
537 error("Illegal cardio arguments");
541 error("iosize should be placed after config");
548 cp->logstr = newstr(next_tok());
558 * Generate a new driver structure. If one exists, use
559 * that one after confirming the correct class.
561 static struct driver *
562 new_driver(char *name)
567 for (drvp = drivers; drvp; drvp = drvp->next)
568 if (strcmp(drvp->name, name) == 0)
570 drvp = xmalloc(sizeof(*drvp));
571 drvp->next = drivers;
573 drvp->name = newstr(name);
574 drvp->kernel = newstr(name);
577 if (*p >= '0' && *p <= '9') {
578 drvp->unit = atoi(p);
583 printf("Drv %s%d created\n", drvp->kernel, drvp->unit);
590 * Parse one I/O block.
592 static struct allocblk *
598 /* ignore the keyword to allow separete blocks in multiple lines */
599 if (keyword(next_tok()) != KWD_IO) {
603 if ((i = num_tok()) >= 0) {
604 if (strcmp("-", next_tok()) || (j = num_tok()) < 0 || j < i) {
605 error("I/O block format error");
608 io = xmalloc(sizeof(*io));
610 io->size = j - i + 1;
612 error("I/O port out of range");
617 io->addr = io->size = 0;
622 error("illegal or missing I/O block spec");
627 * Parse a memory block.
629 static struct allocblk *
630 memblk_tok(int force)
632 struct allocblk *mem;
635 /* ignore the keyword to allow separete blocks in multiple lines */
636 if (keyword(next_tok()) != KWD_MEMORY) {
640 if ((i = num_tok()) >= 0) {
641 if ((j = num_tok()) < 0)
642 error("illegal memory block");
644 mem = xmalloc(sizeof(*mem));
645 mem->addr = i & ~(MEMUNIT - 1);
646 mem->size = (j + MEMUNIT - 1) & ~(MEMUNIT - 1);
647 if (i < MEMSTART || (i + j) > MEMEND) {
648 error("memory address out of range");
653 mem->addr = mem->size = 0;
659 error("illegal or missing memory block spec");
664 * IRQ token. Must be number > 0 && < 16.
665 * If force is set, IRQ must exist, and can also be '?'.
672 /* ignore the keyword to allow separete blocks in multiple lines */
673 if (keyword(next_tok()) != KWD_IRQ) {
677 if (strcmp("?", next_tok()) == 0 && force)
684 error("illegal IRQ value");
692 config_tok(unsigned char *index_type)
694 if (strcmp("default", next_tok()) == 0) {
695 *index_type = DEFAULT_INDEX;
699 if (strcmp("auto", next_tok()) == 0) {
700 *index_type = AUTO_INDEX;
704 *index_type = NORMAL_INDEX;
713 if (strcmp("serial", next_tok()) == 0)
716 if (strcmp("fixed_disk", next_tok()) == 0)
724 * debuglevel token. Must be between 0 and 9.
727 debuglevel_tok(int force)
732 if (i >= 0 && i <= 9)
739 * iosize {<size>|auto}
745 if (strcmp("auto", next_tok()) == 0)
746 iosize = -1; /* wildcard */
755 printf("iosize: size=%x\n", iosize);
762 * search the table for a match.
770 for (s = keys; *s; s++, i++)
771 if (strcmp(*s, str) == 0)
774 /* search keyword aliases too */
775 for (i = 0; key_aliases[i].key ; i++)
776 if (strcmp(key_aliases[i].alias, str) == 0)
777 return (key_aliases[i].key);
783 * addcmd - Append the command line to the list of
787 addcmd(struct cmd **cp)
793 ncp = xmalloc(sizeof(*ncp));
806 logmsg("%s: %s at line %d, near %s\n",
807 filename, msg, lineno, next_tok());
811 static int last_char;
827 return (last_char = c);
839 while (((c = get()) != '\n') && (c != EOF));
840 return (last_char = c);
844 * num_tok - expecting a number token. If not a number,
846 * Handles octal (who uses octal anymore?)
849 * Looks for a 'k' at the end of decimal numbers
850 * and multiplies by 1024.
855 char *s = next_tok(), c;
863 if (c == '\0') return 0;
864 else if (c == 'x' || c == 'X') {
873 if (val && base == 10 && *s == 0)
886 val = val * base + c - '0';
894 val = val * base + c - '0';
903 val = val * base + c - 'a' + 10;
914 val = val * base + c - 'A' + 10;
919 } while ((c = *s++) != 0);
923 static char *_next_tok(void);
928 char *s = _next_tok();
930 printf("Tok = %s\n", s);
936 * get one token. Handles string quoting etc.
941 static char buf[1024];
942 char *p = buf, instr = 0;
964 error("unterminated string");
969 /* Eat whitespace unless in a string. */
981 /* Special characters that are tokens on their own. */
996 /* go back to previous config file */
998 in = configfiles[includes].filep;
999 filename = configfiles[includes].filename;
1000 lineno = configfiles[includes].lineno;
1001 return _next_tok(); /* recursive */
1007 strcpy(buf, "__EOF__");
1014 * get the rest of the line. If the
1015 * last character scanned was a newline, then
1016 * return an empty line. If this isn't checked, then
1017 * a getline may incorrectly return the next line.
1022 char buf[1024], *p = buf;
1025 if (last_char == '\n')
1026 return (newstr(""));
1029 } while (c == ' ' || c == '\t');
1030 for (; c != '\n' && c != EOF; c = get())
1031 if (i++ < sizeof(buf) - 10)
1034 return (newstr(buf));
1038 * Include configuration file
1041 file_include(char *incl)
1046 /* check nesting overflow */
1047 if (includes >= MAXINCLUDES) {
1048 if (debug_level >= 1) {
1049 logmsg("%s: include nesting overflow "
1050 "at line %d, near %s\n", filename, lineno, incl);
1056 /* check recursive inclusion */
1057 for (i = 0, included = 0; i <= includes; i++) {
1058 if (strcmp(incl, configfiles[i].filename) == 0) {
1063 if (included == 1) {
1064 if (debug_level >= 1) {
1065 logmsg("%s: can't include the same file twice "
1066 "at line %d, near %s\n", filename, lineno, incl);
1072 if (!(fp = fopen(incl, "r"))) {
1073 if (debug_level >= 1) {
1074 logmsg("%s: can't open include file "
1075 "at line %d, near %s\n", filename, lineno, incl);
1081 /* save line number of the current config file */
1082 configfiles[includes].lineno = lineno;
1085 /* now we start parsing new config file */
1087 in = configfiles[includes].filep = fp;
1088 filename = configfiles[includes].filename = incl;