x68kConfig.c revision ba64b02e
1/* $NetBSD: x68kConfig.c,v 1.1 2014/03/01 19:34:47 tsutsui Exp $ */ 2/*------------------------------------------------------------------------- 3 * Copyright (c) 1996 Yasushi Yamasaki 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Yasushi Yamasaki 17 * 4. The name of the author may not be used to endorse or promote products 18 * derived from this software without specific prior written permission 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 *-----------------------------------------------------------------------*/ 31 32#include <stdarg.h> 33#include "x68k.h" 34#include "opaque.h" 35 36static PixmapFormatRec *x68kFormat = NULL; 37static PixmapFormatRec defaultFormat = { 38 1, 39 1, 40 BITMAP_SCANLINE_PAD 41}; 42static X68kScreenRec x68kScreen[X68K_FB_TYPES]; 43static X68kFbProcRec x68kFbProc[X68K_FB_TYPES]; 44 45/*------------------------------------------------------------------------- 46 * function "x68kGetScreenRec" 47 * 48 * purpose: get corresponding screen record 49 * argument: (int)sindex : screen index 50 * returns: (X68kScreenRec *) : X68k dependent screen record 51 *-----------------------------------------------------------------------*/ 52X68kScreenRec * 53x68kGetScreenRec(int sindex) 54{ 55 return &x68kScreen[sindex]; 56} 57 58/*------------------------------------------------------------------------- 59 * function "x68kGetScreenRecByType" 60 * 61 * purpose: search screen record by type 62 * argument: (int)type : screen type 63 * returns: (X68kScreenRec *) : X68k dependent screen record 64 *-----------------------------------------------------------------------*/ 65X68kScreenRec * 66x68kGetScreenRecByType(int type) 67{ 68 int i; 69 70 for (i = 0; i < X68K_FB_TYPES; i++) { 71 if (x68kScreen[i].type == type) 72 return &x68kScreen[i]; 73 } 74 return NULL; 75} 76 77/*------------------------------------------------------------------------- 78 * function "x68kGetFbProcRec" 79 * 80 * purpose: get corresponding frame buffer procedure record 81 * argument: (int)sindex : screen index 82 * returns: (X68kFbProcRec *) : frame buffer procedure record 83 *-----------------------------------------------------------------------*/ 84X68kFbProcRec * 85x68kGetFbProcRec(int sindex) 86{ 87 return &x68kFbProc[sindex]; 88} 89 90/*------------------------------------------------------------------------- 91 * function "x68kRegisterPixmapFormats" 92 * 93 * purpose: register pixmap formats into ScreenInfo struct 94 * argument: (ScreenInfo *)pScreenInfo 95 * returns: nothing 96 *-----------------------------------------------------------------------*/ 97void 98x68kRegisterPixmapFormats(ScreenInfo *pScreenInfo) 99{ 100 /* supports only one pixmap format for each screen type */ 101 pScreenInfo->numPixmapFormats = 1; 102 pScreenInfo->formats[0] = defaultFormat; 103 104 if (x68kFormat) 105 pScreenInfo->formats[pScreenInfo->numPixmapFormats++] = *x68kFormat; 106} 107 108/*------------------------------------------------------------------------- 109 * function "x68kConfig" 110 * 111 * purpose: process general configuration by reading "X68kConfig" file 112 * /usr/X11R6/lib/X11/ is the default location of this file 113 * argument: nothing 114 * returns: the number of screens 115 *-----------------------------------------------------------------------*/ 116const char *hostConfigFilename = "/etc/X68kConfig"; 117const char *siteConfigFilename = X11_LIBDIR "/X68kConfig"; 118const char *configFilename = NULL; 119static FILE *config; 120char modeSet = FALSE; 121 122static int parseCommand(void); 123 124int 125x68kConfig(void) 126{ 127 if (configFilename) 128 config = fopen(configFilename, "r"); 129 else { 130 configFilename = hostConfigFilename; 131 config = fopen(configFilename, "r"); 132 if (config == NULL) { 133 configFilename = siteConfigFilename; 134 config = fopen(configFilename, "r"); 135 } 136 } 137 if (config == NULL) 138 FatalError("Can't open X68kConfig file"); 139 while (parseCommand()) 140 ; 141 fclose(config); 142 if (!modeSet) 143 FatalError("No mode set."); 144 return 1; 145} 146 147 148/*------------------------------------------------------------------------- 149 * X68KConfig parsing part 150 *-----------------------------------------------------------------------*/ 151void parseError(int line, const char *str, ...); 152 153enum TokenType { 154 TOKEN_EOF, 155 TOKEN_SYMBOL, 156 TOKEN_LITERAL, 157 TOKEN_OPEN_PARENTHESIS, 158 TOKEN_CLOSE_PARENTHESIS 159}; 160 161typedef struct { 162 enum TokenType type; 163 int line; 164 union { 165 char *symbol; 166 int literal; 167 } content; 168} Token; 169 170/*------------------------------------------------------------------------- 171 * function "getToken" 172 * 173 * purpose: cut out a token from configration file stream 174 * argument: nothing 175 * returns: (Token *) : cut token 176 *-----------------------------------------------------------------------*/ 177static Token * 178getToken(void) 179{ 180 int c; 181 static int line = 1; 182 Token *ret; 183 184 ret = (Token *)xalloc(sizeof(Token)); 185 if (ret == NULL) 186 FatalError("Out of memory"); 187 while (TRUE) { 188 /* slip white spaces */ 189 do { 190 c = fgetc(config); 191 if (c == '\n') 192 line++; 193 } while (isspace(c)); 194 if (c != ';') 195 break; 196 /* skip a comment */ 197 do { 198 c = fgetc(config); 199 } while (c != '\n'); 200 line++; 201 } 202 ret->line = line; 203 if (c == EOF) { 204 ret->type = TOKEN_EOF; 205 return ret; 206 } 207 /* is a symbol? */ 208 if (isalpha(c)) { 209 int i = 0; 210 ret->content.symbol = (char *)xalloc(32 * sizeof(char)); 211 if (ret->content.symbol == NULL) 212 FatalError("Out of memory"); 213 do { 214 if (i < 31) 215 ret->content.symbol[i++] = c; 216 c = fgetc(config); 217 } while (isalnum(c) || c == '_'); 218 ungetc(c, config); 219 ret->content.symbol[i] = '\0'; 220 ret->type = TOKEN_SYMBOL; 221 return ret; 222 } 223 /* is a literal number? */ 224 if (isdigit(c)) { 225 char tmp[32]; 226 int i = 0; 227 do { 228 if (i < 31) 229 tmp[i++] = c; 230 c = fgetc(config); 231 } while (isdigit(c)); 232 ungetc(c, config); 233 tmp[i] = '\0'; 234 if (sscanf(tmp, "%d", &ret->content.literal) != 1) 235 parseError(line, "illegal literal value"); 236 ret->type = TOKEN_LITERAL; 237 return ret; 238 } 239 /* others */ 240 switch(c) { 241 case '(': 242 ret->type = TOKEN_OPEN_PARENTHESIS; 243 break; 244 case ')': 245 ret->type = TOKEN_CLOSE_PARENTHESIS; 246 break; 247 default: 248 parseError(line, NULL); 249 } 250 return ret; 251} 252 253typedef struct { 254 const char *symbol; 255 void (*proc)(int argc, Token **argv); 256} Command; 257 258static void parseModeDef(int argc, Token **argv); 259static void parseMouse(int argc, Token **argv); 260static void parseKeyboard(int argc, Token **argv); 261static void parseMode(int argc, Token **argv); 262 263Command command[] = { 264 { "ModeDef", parseModeDef }, 265 { "Mouse", parseMouse }, 266 { "Keyboard", parseKeyboard }, 267 { "Mode", parseMode }, 268}; 269#define NCOMMANDS (sizeof(command)/sizeof(command[0])) 270 271/*------------------------------------------------------------------------- 272 * function "parseCommand" 273 * 274 * purpose: parse generic command. every command parsing departs here. 275 * argument: nothing 276 * returns: (int) : FALSE if there's no rest 277 * TRUE otherwise 278 *-----------------------------------------------------------------------*/ 279static int 280parseCommand(void) 281{ 282 Token **argv = 0, *token; 283 int argc = 0; 284 int i; 285 286 token = getToken(); 287 if (token->type == TOKEN_EOF) 288 return FALSE; 289 if (token->type != TOKEN_OPEN_PARENTHESIS) 290 parseError(token->line, "missing parenthesis"); 291 xfree(token); 292 293 /* get command name and arguments */ 294 while (TRUE) { 295 token = getToken(); 296 if (token->type == TOKEN_EOF) 297 parseError(token->line, "reached EOF"); 298 if (token->type == TOKEN_CLOSE_PARENTHESIS) { 299 xfree(token); 300 break; 301 } 302 argc++; 303 argv = (Token **)xrealloc(argv, sizeof(Token *) * argc); 304 if (argv == NULL) 305 FatalError("Out of memory"); 306 argv[argc-1] = token; 307 } 308 if (argc == 0) 309 return TRUE; 310 311 /* call corresponding command procedure */ 312 if (argv[0]->type != TOKEN_SYMBOL) 313 parseError(argv[0]->line, "command name required"); 314 for (i = 0; i < NCOMMANDS; i++) { 315 if (strcasecmp(command[i].symbol, argv[0]->content.symbol) == 0) { 316 /* parse command */ 317 command[i].proc(argc, argv); 318 break; 319 } 320 } 321 if (i == NCOMMANDS) 322 parseError(argv[0]->line, "unknown command `%s'", 323 argv[0]->content.symbol); 324 325 /* free arguments */ 326 for (i = 0; i < argc; i++) { 327 if (argv[i]->type == TOKEN_SYMBOL) 328 xfree(argv[i]->content.symbol); 329 xfree(argv[i]); 330 } 331 xfree(argv); 332 return TRUE; 333} 334 335/*------------------------------------------------------------------------- 336 * function "checkArguments" 337 * 338 * purpose: examine the number of arguments and the type of each 339 * argument. 340 * argument: (int)n : correct number of arguments 341 * (enum TokenType *)type : table of types 342 * (int)argc_m1 : actual number of arguments 343 * (Token **)argv : command and arguments 344 * returns: nothing 345 *-----------------------------------------------------------------------*/ 346static void 347checkArguments(int n, enum TokenType *type, int argc_m1, Token **argv) 348{ 349 int i; 350 351 if (argc_m1 < n) 352 parseError(argv[0]->line, "too few arguments to command `%s'", 353 argv[0]->content.symbol); 354 if (argc_m1 > n) 355 parseError(argv[0]->line, "too many arguments to command `%s'", 356 argv[0]->content.symbol); 357 for (i = 0; i < n; i++) { 358 if (argv[i+1]->type != type[i]) 359 parseError(argv[i+1]->line, 360 "type mismatch. argument %d to command `%s'", 361 i+1, argv[0]->content.symbol); 362 } 363} 364 365typedef struct _Mode { 366 struct _Mode *next; 367 char *name; 368 int type; 369 int depth; 370 int class; 371 int width, height; 372 X68kFbReg reg; 373} Mode; 374 375Mode *modeList = NULL; 376 377/*------------------------------------------------------------------------- 378 * function "parseModeDef" 379 * 380 * purpose: define a mode 381 * argument: (int)argc, (Token **)argv : command and arguments 382 * returns: nothing 383 *-----------------------------------------------------------------------*/ 384static void 385parseModeDef(int argc, Token **argv) 386{ 387 enum TokenType argtype[] = { 388 /* name type depth class */ 389 TOKEN_SYMBOL, TOKEN_SYMBOL, TOKEN_LITERAL, TOKEN_SYMBOL, 390 /* width height */ 391 TOKEN_LITERAL, TOKEN_LITERAL, 392 /* register values */ 393 TOKEN_LITERAL, TOKEN_LITERAL, TOKEN_LITERAL, TOKEN_LITERAL, 394 TOKEN_LITERAL, TOKEN_LITERAL, TOKEN_LITERAL, TOKEN_LITERAL, 395 TOKEN_LITERAL, TOKEN_LITERAL, TOKEN_LITERAL, TOKEN_LITERAL 396 }; 397 Mode *mode; 398 char *symbol; 399 int class, width, height; 400 401 checkArguments(18, argtype, argc-1, argv); 402 403 mode = (Mode *)xalloc(sizeof(Mode)); 404 if (mode == NULL) 405 FatalError("Out of memory"); 406 mode->name = strdup(argv[1]->content.symbol); 407 408 /* parse frame buffer type */ 409 symbol = argv[2]->content.symbol; 410 if (strcasecmp("Text", symbol) == 0) 411 mode->type = X68K_FB_TEXT; 412 else if (strcasecmp("Graphic", symbol) == 0) 413 mode->type = X68K_FB_GRAPHIC; 414 else 415 parseError(argv[2]->line, "unknown frame buffer type"); 416 mode->depth = argv[3]->content.literal; 417 418 /* parse frame buffer class */ 419 symbol = argv[4]->content.symbol; 420 if (strcasecmp("StaticGray", symbol) == 0) 421 mode->class = StaticGray; 422 else if (strcasecmp("GrayScale", symbol) == 0) 423 mode->class = GrayScale; 424 else if (strcasecmp("StaticColor", symbol) == 0) 425 mode->class = StaticColor; 426 else if (strcasecmp("PseudoColor", symbol) == 0) 427 mode->class = PseudoColor; 428 else if (strcasecmp("TrueColor", symbol) == 0) 429 mode->class = TrueColor; 430 else if (strcasecmp("DirectColor", symbol) == 0) 431 mode->class = DirectColor; 432 else 433 parseError(argv[4]->line, "unknown frame buffer class"); 434 435 class = mode->class; 436 width = mode->width = argv[5]->content.literal; 437 height = mode->height = argv[6]->content.literal; 438 439 /* examine whether type, depth, class, width, and height are 440 a legal combination or not, and then set mode registers */ 441 switch (mode->type) { 442 case X68K_FB_TEXT: 443 if (mode->depth == 1 && class == StaticGray && 444 width <= 1024 && height <= 1024) { 445 mode->reg.videoc.r1 = 0x21e4; 446 mode->reg.videoc.r2 = 0x0020; 447 goto legal; 448 } 449 break; 450 case X68K_FB_GRAPHIC: 451 switch (mode->depth) { 452 case 4: 453 if ( (class == StaticGray || class == PseudoColor) && 454 width <= 1024 && height <= 1024 ) { 455 mode->reg.videoc.r1 = 0x21e4; 456 mode->reg.videoc.r2 = 0x0010; 457 goto legal; 458 } 459 break; 460 case 8: 461 if (class == PseudoColor && 462 width <= 512 && height <= 512) { 463 mode->reg.videoc.r1 = 0x21e4; 464 mode->reg.videoc.r2 = 0x0003; 465 goto legal; 466 } 467 break; 468 case 15: 469 if (class == TrueColor && 470 width <= 512 && height <= 512) { 471 mode->reg.videoc.r1 = 0x21e4; 472 mode->reg.videoc.r2 = 0x000f; 473 goto legal; 474 } 475 break; 476 } 477 break; 478 } 479 parseError(argv[0]->line, "illegal combination of mode parameters"); 480 legal: 481 482 /* store register values */ 483 mode->reg.crtc.r00 = argv[7]->content.literal; 484 mode->reg.crtc.r01 = argv[8]->content.literal; 485 mode->reg.crtc.r02 = argv[9]->content.literal; 486 mode->reg.crtc.r03 = argv[10]->content.literal; 487 mode->reg.crtc.r04 = argv[11]->content.literal; 488 mode->reg.crtc.r05 = argv[12]->content.literal; 489 mode->reg.crtc.r06 = argv[13]->content.literal; 490 mode->reg.crtc.r07 = argv[14]->content.literal; 491 mode->reg.crtc.r08 = argv[15]->content.literal; 492 mode->reg.crtc.r20 = argv[16]->content.literal; 493 mode->reg.videoc.r0 = argv[17]->content.literal; 494 mode->reg.dotClock = argv[18]->content.literal; 495 496 /* set scroll registers to zero */ 497 mode->reg.crtc.r12 = 0; mode->reg.crtc.r13 = 0; 498 mode->reg.crtc.r14 = 0; mode->reg.crtc.r15 = 0; 499 mode->reg.crtc.r16 = 0; mode->reg.crtc.r17 = 0; 500 mode->reg.crtc.r18 = 0; mode->reg.crtc.r19 = 0; 501 502 /* add new mode to linked mode list */ 503 mode->next = modeList; 504 modeList = mode; 505} 506 507/*------------------------------------------------------------------------- 508 * function "parseMode" 509 * 510 * purpose: choose a mode from predefined modes 511 * argument: (int)argc, (Token **)argv : command and arguments 512 * returns: nothing 513 *-----------------------------------------------------------------------*/ 514static void 515parseMode(int argc, Token **argv) 516{ 517 enum TokenType argtype[]= { TOKEN_SYMBOL }; 518 Mode *mode; 519 520 checkArguments(1, argtype, argc-1, argv); 521 522 /* search mode to set from mode list */ 523 for (mode = modeList; mode != NULL; mode = mode->next) { 524 if (strcmp(mode->name, argv[1]->content.symbol) == 0) 525 break; 526 } 527 if (mode == NULL) 528 parseError(argv[1]->line, "undefined mode `%s'", 529 argv[1]->content.symbol); 530 531 x68kScreen[0].type = mode->type; 532 x68kScreen[0].depth = mode->depth; 533 x68kScreen[0].class = mode->class; 534 x68kScreen[0].dpi = 75; 535 x68kScreen[0].x68kreg = mode->reg; 536 x68kScreen[0].scr_width = mode->width; 537 x68kScreen[0].scr_height = mode->height; 538 539 switch (mode->type) { 540 /* for TVRAM frame buffer */ 541 case X68K_FB_TEXT: 542 x68kFbProc[0].open = x68kTextOpen; 543 x68kFbProc[0].init = x68kTextInit; 544 x68kFbProc[0].close = x68kTextClose; 545 x68kScreen[0].fb_width = 1024; 546 x68kScreen[0].fb_height = 1024; 547 break; 548 /* for GVRAM frame buffer */ 549 case X68K_FB_GRAPHIC: 550 x68kFbProc[0].open = x68kGraphOpen; 551 x68kFbProc[0].init = x68kGraphInit; 552 x68kFbProc[0].close = x68kGraphClose; 553 x68kFormat = (PixmapFormatRec*) xalloc (sizeof(PixmapFormatRec)); 554 x68kFormat->scanlinePad = BITMAP_SCANLINE_PAD; 555 x68kFormat->bitsPerPixel = 16; 556 switch (mode->depth) { 557 case 4: 558 x68kFormat->depth = 4; 559 x68kScreen[0].fb_width = 1024; 560 x68kScreen[0].fb_height = 1024; 561 break; 562 case 8: 563 x68kFormat->depth = 8; 564 x68kScreen[0].fb_width = 512; 565 x68kScreen[0].fb_height = 512; 566 break; 567 case 15: 568 x68kFormat->depth = 15; 569 x68kScreen[0].fb_width = 512; 570 x68kScreen[0].fb_height = 512; 571 } 572 } 573 modeSet = TRUE; 574} 575 576/*------------------------------------------------------------------------- 577 * function "parseMouse" 578 * 579 * purpose: set mouse attribute. 580 * argument: (int)argc, (Token **)argv : command and arguments 581 * returns: nothing 582 *-----------------------------------------------------------------------*/ 583static void 584parseMouse(int argc, Token **argv) 585{ 586 enum TokenType argtype[] = { TOKEN_SYMBOL }; 587 588 checkArguments(1, argtype, argc-1, argv); 589 /* only `standard' mouse allowed */ 590 if (strcasecmp("standard", argv[1]->content.symbol) != 0) 591 parseError(argv[1]->line, "unknown mouse type `%s'", 592 argv[1]->content.symbol); 593} 594 595/*------------------------------------------------------------------------- 596 * function "parseKeyboard" 597 * 598 * purpose: select keyboard map 599 * argument: (int)argc, (Token **)argv : command and arguments 600 * returns: nothing 601 *-----------------------------------------------------------------------*/ 602static void 603parseKeyboard(int argc, Token **argv) 604{ 605 enum TokenType argtype[] = { TOKEN_SYMBOL }; 606 607 checkArguments(1, argtype, argc-1, argv); 608 if (strcasecmp("standard", argv[1]->content.symbol) == 0) { 609 x68kKeySyms = &jisKeySyms; 610 x68kKbdPriv.type = X68K_KB_STANDARD; 611 } else if (strcasecmp("ascii", argv[1]->content.symbol) == 0) { 612 x68kKeySyms = &asciiKeySyms; 613 x68kKbdPriv.type = X68K_KB_ASCII; 614 } else 615 parseError(argv[1]->line, "unknown keyboard type `%s'", 616 argv[1]->content.symbol); 617} 618 619/*------------------------------------------------------------------------- 620 * function "parseError" 621 * 622 * purpose: print error message to stderr and abort Xserver. 623 * this uses the same procedure of the function "FatalError" 624 * argument: (int)line : the line in which some error was detected 625 * (char *)str : error message 626 * returns: nothing 627 *-----------------------------------------------------------------------*/ 628void 629parseError(int line, const char *str, ...) 630{ 631 va_list arglist; 632 633 fprintf(stderr, "%s:%d: ", configFilename, line); 634 if (str != NULL) { 635 va_start(arglist, str); 636 vfprintf(stderr, str, arglist); 637 va_end(arglist); 638 fputc('\n', stderr); 639 } else 640 fprintf(stderr, "parse error\n"); 641 fflush(stderr); 642 if (CoreDump) 643 abort(); 644 exit(1); 645} 646 647/* EOF x68kConfig.c */ 648