/* $NetBSD: x68kConfig.c,v 1.3 2014/03/04 12:11:59 tsutsui Exp $ */ /*------------------------------------------------------------------------- * Copyright (c) 1996 Yasushi Yamasaki * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgement: * This product includes software developed by Yasushi Yamasaki * 4. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *-----------------------------------------------------------------------*/ #include #include "x68k.h" #include "opaque.h" static PixmapFormatRec *x68kFormat = NULL; static PixmapFormatRec defaultFormat = { 1, 1, BITMAP_SCANLINE_PAD }; static X68kScreenRec x68kScreen[X68K_FB_TYPES]; static X68kFbProcRec x68kFbProc[X68K_FB_TYPES]; /*------------------------------------------------------------------------- * function "x68kGetScreenRec" * * purpose: get corresponding screen record * argument: (int)sindex : screen index * returns: (X68kScreenRec *) : X68k dependent screen record *-----------------------------------------------------------------------*/ X68kScreenRec * x68kGetScreenRec(int sindex) { return &x68kScreen[sindex]; } /*------------------------------------------------------------------------- * function "x68kGetScreenRecByType" * * purpose: search screen record by type * argument: (int)type : screen type * returns: (X68kScreenRec *) : X68k dependent screen record *-----------------------------------------------------------------------*/ X68kScreenRec * x68kGetScreenRecByType(int type) { int i; for (i = 0; i < X68K_FB_TYPES; i++) { if (x68kScreen[i].type == type) return &x68kScreen[i]; } return NULL; } /*------------------------------------------------------------------------- * function "x68kGetFbProcRec" * * purpose: get corresponding frame buffer procedure record * argument: (int)sindex : screen index * returns: (X68kFbProcRec *) : frame buffer procedure record *-----------------------------------------------------------------------*/ X68kFbProcRec * x68kGetFbProcRec(int sindex) { return &x68kFbProc[sindex]; } /*------------------------------------------------------------------------- * function "x68kRegisterPixmapFormats" * * purpose: register pixmap formats into ScreenInfo struct * argument: (ScreenInfo *)pScreenInfo * returns: nothing *-----------------------------------------------------------------------*/ void x68kRegisterPixmapFormats(ScreenInfo *pScreenInfo) { /* supports only one pixmap format for each screen type */ pScreenInfo->numPixmapFormats = 1; pScreenInfo->formats[0] = defaultFormat; if (x68kFormat) pScreenInfo->formats[pScreenInfo->numPixmapFormats++] = *x68kFormat; } /*------------------------------------------------------------------------- * function "x68kConfig" * * purpose: process general configuration by reading "X68kConfig" file * is the default location of this file * argument: nothing * returns: the number of screens *-----------------------------------------------------------------------*/ const char *hostConfigFilename = "/etc/X68kConfig"; const char *siteConfigFilename = X11_LIBDIR "/X68kConfig"; const char *configFilename = NULL; static FILE *config; char modeSet = FALSE; static int parseCommand(void); int x68kConfig(void) { if (configFilename) config = fopen(configFilename, "r"); else { configFilename = hostConfigFilename; config = fopen(configFilename, "r"); if (config == NULL) { configFilename = siteConfigFilename; config = fopen(configFilename, "r"); } } if (config == NULL) FatalError("Can't open X68kConfig file"); while (parseCommand()) ; fclose(config); if (!modeSet) FatalError("No mode set."); return 1; } /*------------------------------------------------------------------------- * X68KConfig parsing part *-----------------------------------------------------------------------*/ void parseError(int line, const char *str, ...); enum TokenType { TOKEN_EOF, TOKEN_SYMBOL, TOKEN_LITERAL, TOKEN_OPEN_PARENTHESIS, TOKEN_CLOSE_PARENTHESIS }; typedef struct { enum TokenType type; int line; union { char *symbol; int literal; } content; } Token; /*------------------------------------------------------------------------- * function "getToken" * * purpose: cut out a token from configration file stream * argument: nothing * returns: (Token *) : cut token *-----------------------------------------------------------------------*/ static Token * getToken(void) { int c; static int line = 1; Token *ret; ret = (Token *)malloc(sizeof(Token)); if (ret == NULL) FatalError("Out of memory"); while (TRUE) { /* slip white spaces */ do { c = fgetc(config); if (c == '\n') line++; } while (isspace(c)); if (c != ';') break; /* skip a comment */ do { c = fgetc(config); } while (c != '\n'); line++; } ret->line = line; if (c == EOF) { ret->type = TOKEN_EOF; return ret; } /* is a symbol? */ if (isalpha(c)) { int i = 0; ret->content.symbol = (char *)malloc(32 * sizeof(char)); if (ret->content.symbol == NULL) FatalError("Out of memory"); do { if (i < 31) ret->content.symbol[i++] = c; c = fgetc(config); } while (isalnum(c) || c == '_'); ungetc(c, config); ret->content.symbol[i] = '\0'; ret->type = TOKEN_SYMBOL; return ret; } /* is a literal number? */ if (isdigit(c)) { char tmp[32]; int i = 0; do { if (i < 31) tmp[i++] = c; c = fgetc(config); } while (isdigit(c)); ungetc(c, config); tmp[i] = '\0'; if (sscanf(tmp, "%d", &ret->content.literal) != 1) parseError(line, "illegal literal value"); ret->type = TOKEN_LITERAL; return ret; } /* others */ switch(c) { case '(': ret->type = TOKEN_OPEN_PARENTHESIS; break; case ')': ret->type = TOKEN_CLOSE_PARENTHESIS; break; default: parseError(line, NULL); } return ret; } typedef struct { const char *symbol; void (*proc)(int argc, Token **argv); } Command; static void parseModeDef(int argc, Token **argv); static void parseMouse(int argc, Token **argv); static void parseKeyboard(int argc, Token **argv); static void parseMode(int argc, Token **argv); Command command[] = { { "ModeDef", parseModeDef }, { "Mouse", parseMouse }, { "Keyboard", parseKeyboard }, { "Mode", parseMode }, }; #define NCOMMANDS (sizeof(command)/sizeof(command[0])) /*------------------------------------------------------------------------- * function "parseCommand" * * purpose: parse generic command. every command parsing departs here. * argument: nothing * returns: (int) : FALSE if there's no rest * TRUE otherwise *-----------------------------------------------------------------------*/ static int parseCommand(void) { Token **argv = 0, *token; int argc = 0; int i; token = getToken(); if (token->type == TOKEN_EOF) return FALSE; if (token->type != TOKEN_OPEN_PARENTHESIS) parseError(token->line, "missing parenthesis"); free(token); /* get command name and arguments */ while (TRUE) { token = getToken(); if (token->type == TOKEN_EOF) parseError(token->line, "reached EOF"); if (token->type == TOKEN_CLOSE_PARENTHESIS) { free(token); break; } argc++; argv = (Token **)realloc(argv, sizeof(Token *) * argc); if (argv == NULL) FatalError("Out of memory"); argv[argc-1] = token; } if (argc == 0) return TRUE; /* call corresponding command procedure */ if (argv[0]->type != TOKEN_SYMBOL) parseError(argv[0]->line, "command name required"); for (i = 0; i < NCOMMANDS; i++) { if (strcasecmp(command[i].symbol, argv[0]->content.symbol) == 0) { /* parse command */ command[i].proc(argc, argv); break; } } if (i == NCOMMANDS) parseError(argv[0]->line, "unknown command `%s'", argv[0]->content.symbol); /* free arguments */ for (i = 0; i < argc; i++) { if (argv[i]->type == TOKEN_SYMBOL) free(argv[i]->content.symbol); free(argv[i]); } free(argv); return TRUE; } /*------------------------------------------------------------------------- * function "checkArguments" * * purpose: examine the number of arguments and the type of each * argument. * argument: (int)n : correct number of arguments * (enum TokenType *)type : table of types * (int)argc_m1 : actual number of arguments * (Token **)argv : command and arguments * returns: nothing *-----------------------------------------------------------------------*/ static void checkArguments(int n, enum TokenType *type, int argc_m1, Token **argv) { int i; if (argc_m1 < n) parseError(argv[0]->line, "too few arguments to command `%s'", argv[0]->content.symbol); if (argc_m1 > n) parseError(argv[0]->line, "too many arguments to command `%s'", argv[0]->content.symbol); for (i = 0; i < n; i++) { if (argv[i+1]->type != type[i]) parseError(argv[i+1]->line, "type mismatch. argument %d to command `%s'", i+1, argv[0]->content.symbol); } } typedef struct _Mode { struct _Mode *next; char *name; int type; int depth; int class; int width, height; X68kFbReg reg; } Mode; Mode *modeList = NULL; /*------------------------------------------------------------------------- * function "parseModeDef" * * purpose: define a mode * argument: (int)argc, (Token **)argv : command and arguments * returns: nothing *-----------------------------------------------------------------------*/ static void parseModeDef(int argc, Token **argv) { enum TokenType argtype[] = { /* name type depth class */ TOKEN_SYMBOL, TOKEN_SYMBOL, TOKEN_LITERAL, TOKEN_SYMBOL, /* width height */ TOKEN_LITERAL, TOKEN_LITERAL, /* register values */ TOKEN_LITERAL, TOKEN_LITERAL, TOKEN_LITERAL, TOKEN_LITERAL, TOKEN_LITERAL, TOKEN_LITERAL, TOKEN_LITERAL, TOKEN_LITERAL, TOKEN_LITERAL, TOKEN_LITERAL, TOKEN_LITERAL, TOKEN_LITERAL }; Mode *mode; char *symbol; int class, width, height; checkArguments(18, argtype, argc-1, argv); mode = (Mode *)malloc(sizeof(Mode)); if (mode == NULL) FatalError("Out of memory"); mode->name = strdup(argv[1]->content.symbol); /* parse frame buffer type */ symbol = argv[2]->content.symbol; if (strcasecmp("Text", symbol) == 0) mode->type = X68K_FB_TEXT; else if (strcasecmp("Graphic", symbol) == 0) mode->type = X68K_FB_GRAPHIC; else parseError(argv[2]->line, "unknown frame buffer type"); mode->depth = argv[3]->content.literal; /* parse frame buffer class */ symbol = argv[4]->content.symbol; if (strcasecmp("StaticGray", symbol) == 0) mode->class = StaticGray; else if (strcasecmp("GrayScale", symbol) == 0) mode->class = GrayScale; else if (strcasecmp("StaticColor", symbol) == 0) mode->class = StaticColor; else if (strcasecmp("PseudoColor", symbol) == 0) mode->class = PseudoColor; else if (strcasecmp("TrueColor", symbol) == 0) mode->class = TrueColor; else if (strcasecmp("DirectColor", symbol) == 0) mode->class = DirectColor; else parseError(argv[4]->line, "unknown frame buffer class"); class = mode->class; width = mode->width = argv[5]->content.literal; height = mode->height = argv[6]->content.literal; /* examine whether type, depth, class, width, and height are a legal combination or not, and then set mode registers */ switch (mode->type) { case X68K_FB_TEXT: if (mode->depth == 1 && class == StaticGray && width <= 1024 && height <= 1024) { mode->reg.videoc.r1 = 0x21e4; mode->reg.videoc.r2 = 0x0020; goto legal; } break; case X68K_FB_GRAPHIC: switch (mode->depth) { case 4: if ( (class == StaticGray || class == PseudoColor) && width <= 1024 && height <= 1024 ) { mode->reg.videoc.r1 = 0x21e4; mode->reg.videoc.r2 = 0x0010; goto legal; } break; case 8: if (class == PseudoColor && width <= 512 && height <= 512) { mode->reg.videoc.r1 = 0x21e4; mode->reg.videoc.r2 = 0x0003; goto legal; } break; case 15: if (class == TrueColor && width <= 512 && height <= 512) { mode->reg.videoc.r1 = 0x21e4; mode->reg.videoc.r2 = 0x000f; goto legal; } break; } break; } parseError(argv[0]->line, "illegal combination of mode parameters"); legal: /* store register values */ mode->reg.crtc.r00 = argv[7]->content.literal; mode->reg.crtc.r01 = argv[8]->content.literal; mode->reg.crtc.r02 = argv[9]->content.literal; mode->reg.crtc.r03 = argv[10]->content.literal; mode->reg.crtc.r04 = argv[11]->content.literal; mode->reg.crtc.r05 = argv[12]->content.literal; mode->reg.crtc.r06 = argv[13]->content.literal; mode->reg.crtc.r07 = argv[14]->content.literal; mode->reg.crtc.r08 = argv[15]->content.literal; mode->reg.crtc.r20 = argv[16]->content.literal; mode->reg.videoc.r0 = argv[17]->content.literal; mode->reg.dotClock = argv[18]->content.literal; /* set scroll registers to zero */ mode->reg.crtc.r12 = 0; mode->reg.crtc.r13 = 0; mode->reg.crtc.r14 = 0; mode->reg.crtc.r15 = 0; mode->reg.crtc.r16 = 0; mode->reg.crtc.r17 = 0; mode->reg.crtc.r18 = 0; mode->reg.crtc.r19 = 0; /* add new mode to linked mode list */ mode->next = modeList; modeList = mode; } /*------------------------------------------------------------------------- * function "parseMode" * * purpose: choose a mode from predefined modes * argument: (int)argc, (Token **)argv : command and arguments * returns: nothing *-----------------------------------------------------------------------*/ static void parseMode(int argc, Token **argv) { enum TokenType argtype[]= { TOKEN_SYMBOL }; Mode *mode; checkArguments(1, argtype, argc-1, argv); /* search mode to set from mode list */ for (mode = modeList; mode != NULL; mode = mode->next) { if (strcmp(mode->name, argv[1]->content.symbol) == 0) break; } if (mode == NULL) parseError(argv[1]->line, "undefined mode `%s'", argv[1]->content.symbol); x68kScreen[0].type = mode->type; x68kScreen[0].depth = mode->depth; x68kScreen[0].class = mode->class; x68kScreen[0].dpi = 75; x68kScreen[0].x68kreg = mode->reg; x68kScreen[0].scr_width = mode->width; x68kScreen[0].scr_height = mode->height; switch (mode->type) { /* for TVRAM frame buffer */ case X68K_FB_TEXT: x68kFbProc[0].open = x68kTextOpen; x68kFbProc[0].init = x68kTextInit; x68kFbProc[0].close = x68kTextClose; x68kScreen[0].fb_width = 1024; x68kScreen[0].fb_height = 1024; break; /* for GVRAM frame buffer */ case X68K_FB_GRAPHIC: x68kFbProc[0].open = x68kGraphOpen; x68kFbProc[0].init = x68kGraphInit; x68kFbProc[0].close = x68kGraphClose; x68kFormat = (PixmapFormatRec*) malloc (sizeof(PixmapFormatRec)); x68kFormat->scanlinePad = BITMAP_SCANLINE_PAD; x68kFormat->bitsPerPixel = 16; switch (mode->depth) { case 4: x68kFormat->depth = 4; x68kScreen[0].fb_width = 1024; x68kScreen[0].fb_height = 1024; break; case 8: x68kFormat->depth = 8; x68kScreen[0].fb_width = 512; x68kScreen[0].fb_height = 512; break; case 15: x68kFormat->depth = 15; x68kScreen[0].fb_width = 512; x68kScreen[0].fb_height = 512; } } modeSet = TRUE; } /*------------------------------------------------------------------------- * function "parseMouse" * * purpose: set mouse attribute. * argument: (int)argc, (Token **)argv : command and arguments * returns: nothing *-----------------------------------------------------------------------*/ static void parseMouse(int argc, Token **argv) { enum TokenType argtype[] = { TOKEN_SYMBOL }; checkArguments(1, argtype, argc-1, argv); /* only `standard' mouse allowed */ if (strcasecmp("standard", argv[1]->content.symbol) != 0) parseError(argv[1]->line, "unknown mouse type `%s'", argv[1]->content.symbol); } /*------------------------------------------------------------------------- * function "parseKeyboard" * * purpose: select keyboard map * argument: (int)argc, (Token **)argv : command and arguments * returns: nothing *-----------------------------------------------------------------------*/ static void parseKeyboard(int argc, Token **argv) { enum TokenType argtype[] = { TOKEN_SYMBOL }; checkArguments(1, argtype, argc-1, argv); if (strcasecmp("standard", argv[1]->content.symbol) == 0) { x68kKeySyms = &jisKeySyms; x68kKbdPriv.type = X68K_KB_STANDARD; } else if (strcasecmp("ascii", argv[1]->content.symbol) == 0) { x68kKeySyms = &asciiKeySyms; x68kKbdPriv.type = X68K_KB_ASCII; } else parseError(argv[1]->line, "unknown keyboard type `%s'", argv[1]->content.symbol); } /*------------------------------------------------------------------------- * function "parseError" * * purpose: print error message to stderr and abort Xserver. * this uses the same procedure of the function "FatalError" * argument: (int)line : the line in which some error was detected * (char *)str : error message * returns: nothing *-----------------------------------------------------------------------*/ void parseError(int line, const char *str, ...) { va_list arglist; fprintf(stderr, "%s:%d: ", configFilename, line); if (str != NULL) { va_start(arglist, str); vfprintf(stderr, str, arglist); va_end(arglist); fputc('\n', stderr); } else fprintf(stderr, "parse error\n"); fflush(stderr); if (CoreDump) abort(); exit(1); } /* EOF x68kConfig.c */