1 /* 2 * Copyright 2008-2010, François Revol, revol@free.fr. All rights reserved. 3 * Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de. 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 #include "toscalls.h" 9 #include "video.h" 10 #include "mmu.h" 11 //#include "images.h" 12 13 #include <arch/cpu.h> 14 #include <boot/stage2.h> 15 #include <boot/platform.h> 16 #include <boot/menu.h> 17 #include <boot/kernel_args.h> 18 #include <boot/platform/generic/video.h> 19 #include <util/list.h> 20 #include <drivers/driver_settings.h> 21 #include <GraphicsDefs.h> 22 23 #include <stdio.h> 24 #include <stdlib.h> 25 #include <string.h> 26 27 28 #define TRACE_VIDEO 29 #ifdef TRACE_VIDEO 30 # define TRACE(x) dprintf x 31 #else 32 # define TRACE(x) ; 33 #endif 34 35 36 static void 37 dump_vars() { 38 dprintf("v_bas_ad: %d\n", *TOSVAR_v_bas_ad); 39 dprintf("Physbase %p\n", Physbase()); 40 dprintf("Logbase %p\n", Logbase()); 41 42 } 43 44 // There are several API available to set video modes on atari platforms, 45 // cf. http://toshyp.atari.org/en/004.html 46 47 class ModeOps { 48 public: 49 ModeOps(const char *name) { fName = name; fInitStatus = B_NO_INIT; }; 50 ~ModeOps() {}; 51 const char *Name() const { return fName; }; 52 virtual status_t Init() { fInitStatus = B_OK; }; 53 status_t InitStatus() const { return fInitStatus; }; 54 struct video_mode *AllocMode(); 55 56 // mode handling 57 virtual status_t Enumerate() = 0; 58 virtual status_t Decode(int16 id, struct video_mode *mode); 59 virtual status_t Get(struct video_mode *mode) = 0; 60 virtual status_t Set(const struct video_mode *mode) = 0; 61 virtual status_t Unset(const struct video_mode *mode) { return B_OK; }; 62 63 // current settings 64 virtual status_t SetPalette(const struct video_mode *mode, 65 const uint8 *palette) { return B_OK; }; 66 virtual addr_t Framebuffer() { return NULL; }; 67 68 virtual int16 Width(const struct video_mode *mode=NULL); 69 virtual int16 Height(const struct video_mode *mode=NULL); 70 virtual int16 Depth(const struct video_mode *mode=NULL); 71 virtual int16 BytesPerRow(const struct video_mode *mode=NULL); 72 73 virtual void MakeLabel(const struct video_mode *mode, char *label, 74 size_t len); 75 76 private: 77 const char *fName; 78 protected: 79 status_t fInitStatus; 80 }; 81 82 struct video_mode { 83 list_link link; 84 ModeOps *ops; 85 color_space space; 86 uint16 mode; 87 uint16 width, height, bits_per_pixel; 88 uint32 bytes_per_row; 89 status_t Set() { ops->Set(this); }; 90 status_t Unset() { ops->Unset(this); }; 91 }; 92 93 static struct list sModeList; 94 static video_mode *sMode, *sDefaultMode; 95 static uint32 sModeCount; 96 static addr_t sFrameBuffer; 97 static bool sModeChosen; 98 99 100 static int 101 compare_video_modes(video_mode *a, video_mode *b) 102 { 103 int compare = a->width - b->width; 104 if (compare != 0) 105 return compare; 106 107 compare = a->height - b->height; 108 if (compare != 0) 109 return compare; 110 111 compare = a->bits_per_pixel - b->bits_per_pixel; 112 if (compare != 0) 113 return compare; 114 115 compare = a->mode - b->mode; 116 if (compare != 0) 117 return compare; 118 119 return 0; 120 } 121 122 123 /*! Insert the video mode into the list, sorted by resolution and bit depth. 124 Higher resolutions/depths come first. 125 */ 126 static void 127 add_video_mode(video_mode *videoMode) 128 { 129 video_mode *mode = NULL; 130 while ((mode = (video_mode *)list_get_next_item(&sModeList, mode)) 131 != NULL) { 132 int compare = compare_video_modes(videoMode, mode); 133 if (compare == 0) { 134 // mode already exists 135 return; 136 } 137 138 if (compare > 0) 139 break; 140 } 141 142 list_insert_item_before(&sModeList, mode, videoMode); 143 sModeCount++; 144 } 145 146 // #pragma mark - 147 148 149 struct video_mode * 150 ModeOps::AllocMode() 151 { 152 153 video_mode *videoMode = (video_mode *)malloc(sizeof(struct video_mode)); 154 if (videoMode == NULL) 155 return NULL; 156 157 videoMode->ops = this; 158 return videoMode; 159 } 160 161 status_t 162 ModeOps::Decode(int16 id, struct video_mode *mode) 163 { 164 mode->ops = this; 165 mode->mode = id; 166 return B_OK; 167 } 168 169 170 int16 171 ModeOps::Width(const struct video_mode *mode) 172 { 173 return mode ? mode->width : 0; 174 } 175 176 177 int16 178 ModeOps::Height(const struct video_mode *mode) 179 { 180 return mode ? mode->height : 0; 181 } 182 183 184 int16 185 ModeOps::Depth(const struct video_mode *mode) 186 { 187 return mode ? mode->bits_per_pixel : 0; 188 } 189 190 191 int16 192 ModeOps::BytesPerRow(const struct video_mode *mode) 193 { 194 return mode ? mode->bytes_per_row : 0; 195 } 196 197 198 void 199 ModeOps::MakeLabel(const struct video_mode *mode, char *label, size_t len) 200 { 201 sprintf(label, "%ux%u %u bit (%s)", mode->width, mode->height, 202 mode->bits_per_pixel, mode->ops->Name()); 203 204 } 205 206 207 // #pragma mark - ST/TT XBIOS API 208 209 class STModeOps : public ModeOps { 210 public: 211 STModeOps() : ModeOps("ST/TT") {}; 212 ~STModeOps() {}; 213 virtual status_t Init(); 214 215 virtual status_t Enumerate(); 216 virtual status_t Decode(int16 id, struct video_mode *mode); 217 virtual status_t Get(struct video_mode *mode); 218 virtual status_t Set(const struct video_mode *mode); 219 virtual status_t Unset(const struct video_mode *mode); 220 221 virtual status_t SetPalette(const struct video_mode *mode, 222 const uint8 *palette); 223 virtual addr_t Framebuffer(); 224 virtual void MakeLabel(const struct video_mode *mode, 225 char *label, size_t len); 226 private: 227 static int16 fPreviousMode; 228 static bool fIsTT; 229 }; 230 231 232 int16 STModeOps::fPreviousMode = -1; 233 bool STModeOps::fIsTT = false; 234 235 236 status_t 237 STModeOps::Init() 238 { 239 const tos_cookie *c = tos_find_cookie('_VDO'); 240 if (c == NULL) 241 return ENODEV; 242 if (c->ivalue >> 16 < 1) 243 return ENODEV; 244 if (c->ivalue >= 2) 245 fIsTT = true; 246 fInitStatus = B_OK; 247 return fInitStatus; 248 } 249 250 251 252 status_t 253 STModeOps::Enumerate() 254 { 255 if (fInitStatus < B_OK) 256 return fInitStatus; 257 258 static int16 modes[] = { 0, /*TT:*/ 4, 7 }; 259 for (int i = 0; i < sizeof(modes) / sizeof(int16); i++) { 260 if (!fIsTT && i > 0) 261 break; 262 263 video_mode *videoMode = AllocMode(); 264 if (videoMode == NULL) 265 continue; 266 267 if (Decode(modes[i], videoMode) != B_OK) 268 continue; 269 add_video_mode(videoMode); 270 271 } 272 return B_OK; 273 274 #if 0 275 // TODO: use TT video monitor detection and build possible mode list there... 276 return ENODEV; 277 #endif 278 } 279 280 281 status_t 282 STModeOps::Decode(int16 id, struct video_mode *mode) 283 { 284 mode->ops = this; 285 mode->mode = id; 286 287 switch (id) { 288 case 0: 289 mode->width = 320; 290 mode->height = 200; 291 mode->bits_per_pixel = 4; 292 break; 293 case 4: 294 mode->width = 640; 295 mode->height = 480; 296 mode->bits_per_pixel = 4; 297 break; 298 case 7: 299 mode->width = 320; 300 mode->height = 480; 301 mode->bits_per_pixel = 8; 302 break; 303 default: 304 mode->bits_per_pixel = 0; 305 break; 306 } 307 308 mode->bytes_per_row = mode->width * mode->bits_per_pixel / 8; 309 return B_OK; 310 } 311 312 313 status_t 314 STModeOps::Get(struct video_mode *mode) 315 { 316 if (fInitStatus < B_OK) 317 return fInitStatus; 318 319 int16 m = Getrez(); 320 return Decode(m, mode); 321 } 322 323 324 status_t 325 STModeOps::Set(const struct video_mode *mode) 326 { 327 if (fInitStatus < B_OK) 328 return fInitStatus; 329 if (mode == NULL) 330 return B_BAD_VALUE; 331 332 fPreviousMode = Getrez(); 333 334 #warning M68K: FIXME: allocate framebuffer 335 dprintf("Switching to mode 0x%04x\n", mode->mode); 336 //VsetScreen(((uint32)0x00d00000), ((uint32)0x00d00000), 3, mode->mode); 337 Setscreen(-1, -1, mode->mode, 0); 338 if (Getrez() != mode->mode) { 339 dprintf("failed to set mode %d. Current is %d\n", mode->mode, fPreviousMode); 340 fPreviousMode = -1; 341 } 342 343 return B_OK; 344 } 345 346 347 status_t 348 STModeOps::Unset(const struct video_mode *mode) 349 { 350 if (fInitStatus < B_OK) 351 return fInitStatus; 352 353 if (fPreviousMode != -1) { 354 dprintf("Reverting to mode 0x%04x\n", fPreviousMode); 355 Setscreen(-1, -1, fPreviousMode, 0); 356 fPreviousMode = -1; 357 } 358 359 return B_OK; 360 } 361 362 363 status_t 364 STModeOps::SetPalette(const struct video_mode *mode, const uint8 *palette) 365 { 366 switch (mode->bits_per_pixel) { 367 case 4: 368 //VsetRGB(0, 16, palette); 369 //XXX: Use ESet* 370 break; 371 case 8: 372 //VsetRGB(0, 256, palette); 373 //XXX: Use ESet* 374 break; 375 default: 376 break; 377 } 378 } 379 380 381 addr_t 382 STModeOps::Framebuffer() 383 { 384 addr_t fb = (addr_t)Physbase(); 385 return fb; 386 } 387 388 389 void 390 STModeOps::MakeLabel(const struct video_mode *mode, char *label, 391 size_t len) 392 { 393 ModeOps::MakeLabel(mode, label, len); 394 label += strlen(label); 395 // XXX no len check 396 sprintf(label, " 0x%04x", mode->mode); 397 } 398 399 400 static STModeOps sSTModeOps; 401 402 403 // #pragma mark - Falcon XBIOS API 404 405 class FalconModeOps : public ModeOps { 406 public: 407 FalconModeOps() : ModeOps("Falcon") {}; 408 ~FalconModeOps() {}; 409 virtual status_t Init(); 410 411 virtual status_t Enumerate(); 412 virtual status_t Decode(int16 id, struct video_mode *mode); 413 virtual status_t Get(struct video_mode *mode); 414 virtual status_t Set(const struct video_mode *mode); 415 virtual status_t Unset(const struct video_mode *mode); 416 417 virtual status_t SetPalette(const struct video_mode *mode, 418 const uint8 *palette); 419 virtual addr_t Framebuffer(); 420 virtual void MakeLabel(const struct video_mode *mode, 421 char *label, size_t len); 422 private: 423 static int16 fPreviousMode; 424 }; 425 426 427 int16 FalconModeOps::fPreviousMode = -1; 428 429 430 status_t 431 FalconModeOps::Init() 432 { 433 const tos_cookie *c = tos_find_cookie('_VDO'); 434 if (c == NULL) 435 return ENODEV; 436 if (c->ivalue < 0x00030000) 437 return ENODEV; 438 fInitStatus = B_OK; 439 return fInitStatus; 440 } 441 442 443 444 status_t 445 FalconModeOps::Enumerate() 446 { 447 if (fInitStatus < B_OK) 448 return fInitStatus; 449 450 static int16 modes[] = { 451 0x001b, 0x001c, 0x002b, 0x002c, 452 0x003a, 0x003b, 0x003c, 0x000c, 453 0x0034, 0x0004 454 /*0x003a, 0x003b, 0x0003, 0x000c, 455 0x000b, 0x0033, 0x000c, 0x001c*/ }; 456 for (int i = 0; i < sizeof(modes) / sizeof(int16); i++) { 457 video_mode *videoMode = AllocMode(); 458 if (videoMode == NULL) 459 continue; 460 461 if (Decode(modes[i], videoMode) != B_OK) 462 continue; 463 add_video_mode(videoMode); 464 465 } 466 return B_OK; 467 468 #if 0 469 // TODO: use falcon video monitor detection and build possible mode list there... 470 int16 monitor; 471 bool vga = false; 472 bool tv = false; 473 monitor = VgetMonitor(); 474 switch (monitor) { 475 case 0: 476 panic("Monochrome ?\n"); 477 break; 478 case 2: 479 vga = true; 480 break; 481 case 3: 482 tv = true; 483 break; 484 //case 4 & 5: check for CT60 485 case 1: 486 default: 487 dprintf("monitor type %d\n", monitor); 488 break; 489 } 490 return ENODEV; 491 #endif 492 } 493 494 495 status_t 496 FalconModeOps::Decode(int16 id, struct video_mode *mode) 497 { 498 bool vga = (id & 0x0010) != 0; 499 //bool pal = (id & 0x0020) != 0; 500 bool overscan = (id & 0x0040) != 0; 501 bool st = (id & 0x0080) != 0; 502 bool interlace = (id & 0x0100) != 0; 503 bool dbl = interlace; 504 505 mode->ops = this; 506 mode->mode = id; 507 // cf. F30.TXT 508 mode->width = (id & 0x0008) ? 640 : 320; 509 mode->height = (vga ? (interlace ? 400 : 200) : (dbl ? 240 : 480)); 510 if (overscan) { 511 // *= 1.2 512 mode->width = (mode->width * 12) / 10; 513 mode->height = (mode->width * 12) / 10; 514 } 515 mode->bits_per_pixel = 1 << (id & 0x0007); 516 mode->bytes_per_row = mode->width * mode->bits_per_pixel / 8; 517 return B_OK; 518 } 519 520 521 status_t 522 FalconModeOps::Get(struct video_mode *mode) 523 { 524 if (fInitStatus < B_OK) 525 return fInitStatus; 526 527 int16 m = VsetMode(VM_INQUIRE); 528 return Decode(m, mode); 529 } 530 531 532 status_t 533 FalconModeOps::Set(const struct video_mode *mode) 534 { 535 if (fInitStatus < B_OK) 536 return fInitStatus; 537 if (mode == NULL) 538 return B_BAD_VALUE; 539 540 fPreviousMode = VsetMode(VM_INQUIRE); 541 542 #warning M68K: FIXME: allocate framebuffer 543 dprintf("Switching to mode 0x%04x\n", mode->mode); 544 //VsetScreen(((uint32)0x00d00000), ((uint32)0x00d00000), 3, mode->mode); 545 VsetScreen(((uint32)0x00c00000), ((uint32)0x00c00000), 3, mode->mode); 546 //VsetScreen(((uint32)-1), ((uint32)-1), 3, mode->mode); 547 548 return B_OK; 549 } 550 551 552 status_t 553 FalconModeOps::Unset(const struct video_mode *mode) 554 { 555 if (fInitStatus < B_OK) 556 return fInitStatus; 557 558 if (fPreviousMode != -1) { 559 dprintf("Reverting to mode 0x%04x\n", fPreviousMode); 560 VsetScreen(-1, -1, 3, fPreviousMode); 561 fPreviousMode = -1; 562 } 563 564 return B_OK; 565 } 566 567 568 status_t 569 FalconModeOps::SetPalette(const struct video_mode *mode, const uint8 *palette) 570 { 571 switch (mode->bits_per_pixel) { 572 case 4: 573 VsetRGB(0, 16, palette); 574 break; 575 case 8: 576 VsetRGB(0, 256, palette); 577 break; 578 default: 579 break; 580 } 581 } 582 583 584 addr_t 585 FalconModeOps::Framebuffer() 586 { 587 addr_t fb = (addr_t)Physbase(); 588 return fb; 589 } 590 591 592 void 593 FalconModeOps::MakeLabel(const struct video_mode *mode, char *label, 594 size_t len) 595 { 596 ModeOps::MakeLabel(mode, label, len); 597 label += strlen(label); 598 // XXX no len check 599 int16 m = mode->mode; 600 sprintf(label, " 0x%04x", mode->mode); 601 /*sprintf(label, "%s%s%s%s", 602 m & 0x0010 ? " vga" : " tv", 603 m & 0x0020 ? " pal" : "", 604 m & 0x0040 ? " oscan" : "", 605 //m & 0x0080 ? " tv" : "", 606 m & 0x0100 ? " ilace" : "");*/ 607 } 608 609 610 static FalconModeOps sFalconModeOps; 611 612 613 // #pragma mark - Milan XBIOS API 614 615 class MilanModeOps : public ModeOps { 616 public: 617 MilanModeOps() : ModeOps("Milan") {}; 618 ~MilanModeOps() {}; 619 virtual status_t Init(); 620 621 virtual status_t Enumerate(); 622 virtual status_t Decode(int16 id, struct video_mode *mode); 623 virtual status_t Get(struct video_mode *mode); 624 virtual status_t Set(const struct video_mode *mode); 625 virtual status_t Unset(const struct video_mode *mode); 626 627 virtual status_t SetPalette(const struct video_mode *mode, 628 const uint8 *palette); 629 virtual addr_t Framebuffer(); 630 virtual void MakeLabel(const struct video_mode *mode, 631 char *label, size_t len); 632 private: 633 static int16 fPreviousMode; 634 }; 635 636 637 int16 MilanModeOps::fPreviousMode = -1; 638 639 640 status_t 641 MilanModeOps::Init() 642 { 643 const tos_cookie *c = tos_find_cookie('_MIL'); 644 if (c == NULL) 645 return ENODEV; 646 fInitStatus = B_OK; 647 return fInitStatus; 648 } 649 650 651 652 status_t 653 MilanModeOps::Enumerate() 654 { 655 if (fInitStatus < B_OK) 656 return fInitStatus; 657 658 SCREENINFO info; 659 info.size = sizeof(info); 660 661 662 static int16 modes[] = { 663 0x001b, 0x001c, 0x002b, 0x002c, 664 0x003a, 0x003b, 0x003c, 0x000c, 665 0x0034, 0x0004 666 /*0x003a, 0x003b, 0x0003, 0x000c, 667 0x000b, 0x0033, 0x000c, 0x001c*/ }; 668 for (int i = 0; i < sizeof(modes) / sizeof(int16); i++) { 669 video_mode *videoMode = AllocMode(); 670 if (videoMode == NULL) 671 continue; 672 673 if (Decode(modes[i], videoMode) != B_OK) 674 continue; 675 add_video_mode(videoMode); 676 677 } 678 return B_OK; 679 680 #if 0 681 // TODO: use Milan video monitor detection and build possible mode list there... 682 int16 monitor; 683 bool vga = false; 684 bool tv = false; 685 monitor = VgetMonitor(); 686 switch (monitor) { 687 case 0: 688 panic("Monochrome ?\n"); 689 break; 690 case 2: 691 vga = true; 692 break; 693 case 3: 694 tv = true; 695 break; 696 //case 4 & 5: check for CT60 697 case 1: 698 default: 699 dprintf("monitor type %d\n", monitor); 700 break; 701 } 702 return ENODEV; 703 #endif 704 } 705 706 707 status_t 708 MilanModeOps::Decode(int16 id, struct video_mode *mode) 709 { 710 SCREENINFO info; 711 info.size = sizeof(info); 712 info.devID = mode->mode; 713 info.scrFlags = 0; 714 715 mode->ops = this; 716 mode->mode = id; 717 718 Setscreen(-1,&info,MI_MAGIC,CMD_GETINFO); 719 720 if (info.scrFlags & SCRINFO_OK == 0) 721 return B_ERROR; 722 723 // cf. F30.TXT 724 mode->width = info.scrWidth; 725 mode->height = info.scrHeight; 726 mode->bits_per_pixel = info.scrPlanes; 727 mode->bytes_per_row = mode->width * mode->bits_per_pixel / 8; 728 return B_OK; 729 } 730 731 732 status_t 733 MilanModeOps::Get(struct video_mode *mode) 734 { 735 if (fInitStatus < B_OK) 736 return fInitStatus; 737 738 int16 m = -1; 739 Setscreen(-1,&m,MI_MAGIC,CMD_GETMODE); 740 if (m == -1) 741 return B_ERROR; 742 return Decode(m, mode); 743 } 744 745 746 status_t 747 MilanModeOps::Set(const struct video_mode *mode) 748 { 749 if (fInitStatus < B_OK) 750 return fInitStatus; 751 if (mode == NULL) 752 return B_BAD_VALUE; 753 754 Setscreen(-1,&fPreviousMode,MI_MAGIC,CMD_GETMODE); 755 756 #warning M68K: FIXME: allocate framebuffer 757 dprintf("Switching to mode 0x%04x\n", mode->mode); 758 //VsetScreen(((uint32)0x00d00000), ((uint32)0x00d00000), 3, mode->mode); 759 //VsetScreen(((uint32)-1), ((uint32)-1), 3, mode->mode); 760 Setscreen(-1,mode->mode,MI_MAGIC,CMD_SETMODE); 761 762 return B_OK; 763 } 764 765 766 status_t 767 MilanModeOps::Unset(const struct video_mode *mode) 768 { 769 if (fInitStatus < B_OK) 770 return fInitStatus; 771 772 if (fPreviousMode != -1) { 773 dprintf("Reverting to mode 0x%04x\n", fPreviousMode); 774 Setscreen(-1,fPreviousMode,MI_MAGIC,CMD_SETMODE); 775 fPreviousMode = -1; 776 } 777 778 return B_OK; 779 } 780 781 782 status_t 783 MilanModeOps::SetPalette(const struct video_mode *mode, const uint8 *palette) 784 { 785 switch (mode->bits_per_pixel) { 786 case 4: 787 //VsetRGB(0, 16, palette); 788 break; 789 case 8: 790 //VsetRGB(0, 256, palette); 791 break; 792 default: 793 break; 794 } 795 } 796 797 798 addr_t 799 MilanModeOps::Framebuffer() 800 { 801 //XXX 802 addr_t fb = (addr_t)Physbase(); 803 return fb; 804 } 805 806 807 void 808 MilanModeOps::MakeLabel(const struct video_mode *mode, char *label, 809 size_t len) 810 { 811 ModeOps::MakeLabel(mode, label, len); 812 label += strlen(label); 813 // XXX no len check 814 int16 m = mode->mode; 815 sprintf(label, " 0x%04x", mode->mode); 816 /*sprintf(label, "%s%s%s%s", 817 m & 0x0010 ? " vga" : " tv", 818 m & 0x0020 ? " pal" : "", 819 m & 0x0040 ? " oscan" : "", 820 //m & 0x0080 ? " tv" : "", 821 m & 0x0100 ? " ilace" : "");*/ 822 } 823 824 825 static MilanModeOps sMilanModeOps; 826 827 828 // #pragma mark - ARAnyM NFVDI API 829 830 /* NatFeat VDI */ 831 #define FVDIDRV_NFAPI_VERSION 0x14000960L 832 #define FVDI_GET_VERSION 0 833 #define FVDI_GET_FBADDR 11 834 #define FVDI_SET_RESOLUTION 12 835 #define FVDI_GET_WIDTH 13 836 #define FVDI_GET_HEIGHT 14 837 #define FVDI_OPENWK 15 838 #define FVDI_CLOSEWK 16 839 #define FVDI_GETBPP 17 840 841 842 class NFVDIModeOps : public ModeOps { 843 public: 844 NFVDIModeOps() : ModeOps("NFVDI") {}; 845 ~NFVDIModeOps() {}; 846 virtual status_t Init(); 847 virtual status_t Enumerate(); 848 virtual status_t Get(struct video_mode *mode); 849 virtual status_t Set(const struct video_mode *mode); 850 virtual status_t Unset(const struct video_mode *mode); 851 virtual addr_t Framebuffer(); 852 853 virtual int16 Width(const struct video_mode *mode=NULL); 854 virtual int16 Height(const struct video_mode *mode=NULL); 855 virtual int16 Depth(const struct video_mode *mode=NULL); 856 857 private: 858 int32 fNatFeatId; 859 }; 860 861 862 status_t 863 NFVDIModeOps::Init() 864 { 865 // NF calls not available when the ctor is called 866 fNatFeatId = nat_feat_getid("fVDI"); 867 if (fNatFeatId == 0) 868 return B_ERROR; 869 dprintf("fVDI natfeat id 0x%08lx\n", fNatFeatId); 870 871 int32 version = nat_feat_call(fNatFeatId, FVDI_GET_VERSION); 872 dprintf("fVDI NF version %lx\n", version); 873 if (version < FVDIDRV_NFAPI_VERSION) 874 return B_ERROR; 875 fInitStatus = B_OK; 876 return fInitStatus; 877 } 878 879 880 status_t 881 NFVDIModeOps::Enumerate() 882 { 883 if (fNatFeatId == 0) 884 return B_NO_INIT; 885 886 video_mode * mode; 887 888 mode = AllocMode(); 889 if (mode == NULL) 890 return B_ERROR; 891 892 Get(mode); 893 //mode->space = ; 894 mode->mode = 0; 895 mode->width = 800; 896 mode->height = 600; 897 mode->bits_per_pixel = 8; 898 mode->bytes_per_row = mode->width * mode->bits_per_pixel / 8; 899 900 add_video_mode(mode); 901 902 903 mode = AllocMode(); 904 if (mode == NULL) 905 return B_ERROR; 906 907 Get(mode); 908 //mode->space = ; 909 mode->mode = 0; 910 mode->width = 1024; 911 mode->height = 768; 912 mode->bits_per_pixel = 16; 913 mode->bytes_per_row = mode->width * mode->bits_per_pixel / 8; 914 915 add_video_mode(mode); 916 917 918 return B_OK; 919 } 920 921 922 status_t 923 NFVDIModeOps::Get(struct video_mode *mode) 924 { 925 if (mode == NULL) 926 return B_BAD_VALUE; 927 if (fNatFeatId == 0) 928 return B_NOT_SUPPORTED; 929 mode->width = Width(); 930 mode->height = Height(); 931 mode->bits_per_pixel = Depth(); 932 mode->bytes_per_row = mode->width * mode->bits_per_pixel / 8; 933 dprintf("Get: %dx%d\n", mode->width, mode->height); 934 return B_OK; 935 } 936 937 938 status_t 939 NFVDIModeOps::Set(const struct video_mode *mode) 940 { 941 if (mode == NULL) 942 return B_BAD_VALUE; 943 if (fNatFeatId == 0) 944 return B_NOT_SUPPORTED; 945 status_t err; 946 dprintf("fVDI::Set(%ldx%ld %ld)\n", 947 (int32)Width(mode), (int32)Height(mode), (int32)Depth(mode)); 948 err = nat_feat_call(fNatFeatId, FVDI_SET_RESOLUTION, 949 (int32)Width(mode), (int32)Height(mode), (int32)Depth(mode)); 950 err = toserror(err); 951 err = nat_feat_call(fNatFeatId, FVDI_OPENWK); 952 953 return B_OK; 954 } 955 956 957 status_t 958 NFVDIModeOps::Unset(const struct video_mode *mode) 959 { 960 if (mode == NULL) 961 return B_BAD_VALUE; 962 if (fNatFeatId == 0) 963 return B_NOT_SUPPORTED; 964 nat_feat_call(fNatFeatId, FVDI_CLOSEWK); 965 return B_OK; 966 } 967 968 969 addr_t 970 NFVDIModeOps::Framebuffer() 971 { 972 addr_t fb; 973 if (fNatFeatId == 0) 974 return (addr_t)NULL; 975 fb = (addr_t)nat_feat_call(fNatFeatId, FVDI_GET_FBADDR); 976 dprintf("fb 0x%08lx\n", fb); 977 return fb; 978 } 979 980 981 int16 982 NFVDIModeOps::Width(const struct video_mode *mode) 983 { 984 if (mode) 985 return ModeOps::Width(mode); 986 if (fNatFeatId == 0) 987 return 0; 988 return (int16)nat_feat_call(fNatFeatId, FVDI_GET_WIDTH); 989 } 990 991 992 int16 993 NFVDIModeOps::Height(const struct video_mode *mode) 994 { 995 if (mode) 996 return ModeOps::Height(mode); 997 if (fNatFeatId == 0) 998 return 0; 999 return (int16)nat_feat_call(fNatFeatId, FVDI_GET_HEIGHT); 1000 } 1001 1002 1003 int16 1004 NFVDIModeOps::Depth(const struct video_mode *mode) 1005 { 1006 if (mode) 1007 return ModeOps::Depth(mode); 1008 if (fNatFeatId == 0) 1009 return 0; 1010 return (int16)nat_feat_call(fNatFeatId, FVDI_GETBPP); 1011 } 1012 1013 1014 static NFVDIModeOps sNFVDIModeOps; 1015 1016 1017 // #pragma mark - 1018 1019 1020 bool 1021 video_mode_hook(Menu *menu, MenuItem *item) 1022 { 1023 // find selected mode 1024 video_mode *mode = NULL; 1025 1026 menu = item->Submenu(); 1027 item = menu->FindMarked(); 1028 if (item != NULL) { 1029 switch (menu->IndexOf(item)) { 1030 case 0: 1031 // "Default" mode special 1032 sMode = sDefaultMode; 1033 sModeChosen = false; 1034 return true; 1035 //case 1: 1036 // "Standard VGA" mode special 1037 // sets sMode to NULL which triggers VGA mode 1038 //break; 1039 default: 1040 mode = (video_mode *)item->Data(); 1041 break; 1042 } 1043 } 1044 1045 if (mode != sMode) { 1046 // update standard mode 1047 // ToDo: update fb settings! 1048 sMode = mode; 1049 platform_switch_to_logo(); 1050 } 1051 1052 sModeChosen = true; 1053 return true; 1054 } 1055 1056 1057 Menu * 1058 video_mode_menu() 1059 { 1060 Menu *menu = new(nothrow) Menu(CHOICE_MENU, "Select Video Mode"); 1061 MenuItem *item; 1062 1063 menu->AddItem(item = new(nothrow) MenuItem("Default")); 1064 item->SetMarked(true); 1065 item->Select(true); 1066 item->SetHelpText("The Default video mode is the one currently configured " 1067 "in the system. If there is no mode configured yet, a viable mode will " 1068 "be chosen automatically."); 1069 1070 //menu->AddItem(new(nothrow) MenuItem("Standard VGA")); 1071 1072 video_mode *mode = NULL; 1073 while ((mode = (video_mode *)list_get_next_item(&sModeList, mode)) != NULL) { 1074 char label[64]; 1075 mode->ops->MakeLabel(mode, label, sizeof(label)); 1076 1077 menu->AddItem(item = new(nothrow) MenuItem(label)); 1078 item->SetData(mode); 1079 } 1080 1081 menu->AddSeparatorItem(); 1082 menu->AddItem(item = new(nothrow) MenuItem("Return to main menu")); 1083 item->SetType(MENU_ITEM_NO_CHOICE); 1084 1085 return menu; 1086 } 1087 1088 1089 void 1090 platform_blit4(addr_t frameBuffer, const uint8 *data, 1091 uint16 width, uint16 height, uint16 imageWidth, uint16 left, uint16 top) 1092 { 1093 if (!data) 1094 return; 1095 } 1096 1097 1098 extern "C" void 1099 platform_set_palette(const uint8 *palette) 1100 { 1101 if (sMode) 1102 sMode->ops->SetPalette(sMode, palette); 1103 } 1104 1105 1106 // #pragma mark - 1107 1108 1109 extern "C" void 1110 platform_switch_to_logo(void) 1111 { 1112 // in debug mode, we'll never show the logo 1113 if ((platform_boot_options() & BOOT_OPTION_DEBUG_OUTPUT) != 0) 1114 return; 1115 1116 addr_t lastBase = gKernelArgs.frame_buffer.physical_buffer.start; 1117 size_t lastSize = gKernelArgs.frame_buffer.physical_buffer.size; 1118 1119 if (sMode != NULL) { 1120 sMode->Set(); 1121 1122 gKernelArgs.frame_buffer.width = sMode->ops->Width(sMode); 1123 gKernelArgs.frame_buffer.height = sMode->ops->Height(sMode); 1124 gKernelArgs.frame_buffer.bytes_per_row = sMode->ops->BytesPerRow(sMode); 1125 gKernelArgs.frame_buffer.depth = sMode->ops->Depth(sMode); 1126 gKernelArgs.frame_buffer.physical_buffer.size = 1127 gKernelArgs.frame_buffer.height 1128 * gKernelArgs.frame_buffer.bytes_per_row; 1129 gKernelArgs.frame_buffer.physical_buffer.start = 1130 sMode->ops->Framebuffer(); 1131 //XXX: FIXME: this is just for testing... 1132 sFrameBuffer = sMode->ops->Framebuffer(); 1133 } else { 1134 gKernelArgs.frame_buffer.enabled = false; 1135 return; 1136 } 1137 gKernelArgs.frame_buffer.enabled = true; 1138 1139 #if 1 1140 // If the new frame buffer is either larger than the old one or located at 1141 // a different address, we need to remap it, so we first have to throw 1142 // away its previous mapping 1143 if (lastBase != 0 1144 && (lastBase != gKernelArgs.frame_buffer.physical_buffer.start 1145 || lastSize < gKernelArgs.frame_buffer.physical_buffer.size)) { 1146 mmu_free((void *)sFrameBuffer, lastSize); 1147 lastBase = 0; 1148 } 1149 if (lastBase == 0) { 1150 // the graphics memory has not been mapped yet! 1151 sFrameBuffer = mmu_map_physical_memory( 1152 gKernelArgs.frame_buffer.physical_buffer.start, 1153 gKernelArgs.frame_buffer.physical_buffer.size, kDefaultPageFlags); 1154 } 1155 #endif 1156 video_display_splash(sFrameBuffer); 1157 dump_vars(); 1158 spin(10000000); 1159 platform_switch_to_text_mode(); 1160 dprintf("splash done\n"); 1161 dump_vars(); 1162 } 1163 1164 1165 extern "C" void 1166 platform_switch_to_text_mode(void) 1167 { 1168 if (!gKernelArgs.frame_buffer.enabled) { 1169 return; 1170 } 1171 1172 if (sMode) 1173 sMode->Unset(); 1174 1175 gKernelArgs.frame_buffer.enabled = 0; 1176 } 1177 1178 1179 extern "C" status_t 1180 platform_init_video(void) 1181 { 1182 gKernelArgs.frame_buffer.enabled = 0; 1183 list_init(&sModeList); 1184 1185 dprintf("current video mode: \n"); 1186 dprintf("Vsetmode(-1): 0x%08x\n", VsetMode(VM_INQUIRE)); 1187 dump_vars(); 1188 1189 // NF VDI does not implement FVDI_GET_FBADDR :( 1190 //sNFVDIModeOps.Init(); 1191 //sNFVDIModeOps.Enumerate(); 1192 1193 if (sMilanModeOps.Init() == B_OK) { 1194 sMilanModeOps.Enumerate(); 1195 } else if (sFalconModeOps.Init() == B_OK) { 1196 sFalconModeOps.Enumerate(); 1197 } else if (sSTModeOps.Init() == B_OK) { 1198 sSTModeOps.Enumerate(); 1199 } else { 1200 dprintf("No usable video API found\n"); 1201 } 1202 1203 return B_OK; 1204 } 1205 1206