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
dump_vars()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:
ModeOps(const char * name)49 ModeOps(const char *name) { fName = name; fInitStatus = B_NO_INIT; };
~ModeOps()50 ~ModeOps() {};
Name() const51 const char *Name() const { return fName; };
Init()52 virtual status_t Init() { fInitStatus = B_OK; };
InitStatus() const53 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;
Unset(const struct video_mode * mode)61 virtual status_t Unset(const struct video_mode *mode) { return B_OK; };
62
63 // current settings
SetPalette(const struct video_mode * mode,const uint8 * palette)64 virtual status_t SetPalette(const struct video_mode *mode,
65 const uint8 *palette) { return B_OK; };
Framebuffer()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;
Setvideo_mode89 status_t Set() { ops->Set(this); };
Unsetvideo_mode90 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
compare_video_modes(video_mode * a,video_mode * b)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
add_video_mode(video_mode * videoMode)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 *
AllocMode()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
Decode(int16 id,struct video_mode * mode)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
Width(const struct video_mode * mode)171 ModeOps::Width(const struct video_mode *mode)
172 {
173 return mode ? mode->width : 0;
174 }
175
176
177 int16
Height(const struct video_mode * mode)178 ModeOps::Height(const struct video_mode *mode)
179 {
180 return mode ? mode->height : 0;
181 }
182
183
184 int16
Depth(const struct video_mode * mode)185 ModeOps::Depth(const struct video_mode *mode)
186 {
187 return mode ? mode->bits_per_pixel : 0;
188 }
189
190
191 int16
BytesPerRow(const struct video_mode * mode)192 ModeOps::BytesPerRow(const struct video_mode *mode)
193 {
194 return mode ? mode->bytes_per_row : 0;
195 }
196
197
198 void
MakeLabel(const struct video_mode * mode,char * label,size_t len)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:
STModeOps()211 STModeOps() : ModeOps("ST/TT") {};
~STModeOps()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
Init()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
Enumerate()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
Decode(int16 id,struct video_mode * mode)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
Get(struct video_mode * mode)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
Set(const struct video_mode * mode)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
Unset(const struct video_mode * mode)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
SetPalette(const struct video_mode * mode,const uint8 * palette)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
Framebuffer()382 STModeOps::Framebuffer()
383 {
384 addr_t fb = (addr_t)Physbase();
385 return fb;
386 }
387
388
389 void
MakeLabel(const struct video_mode * mode,char * label,size_t len)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:
FalconModeOps()407 FalconModeOps() : ModeOps("Falcon") {};
~FalconModeOps()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
Init()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
Enumerate()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
Decode(int16 id,struct video_mode * mode)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
Get(struct video_mode * mode)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
Set(const struct video_mode * mode)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
Unset(const struct video_mode * mode)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
SetPalette(const struct video_mode * mode,const uint8 * palette)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
Framebuffer()585 FalconModeOps::Framebuffer()
586 {
587 addr_t fb = (addr_t)Physbase();
588 return fb;
589 }
590
591
592 void
MakeLabel(const struct video_mode * mode,char * label,size_t len)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:
MilanModeOps()617 MilanModeOps() : ModeOps("Milan") {};
~MilanModeOps()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
Init()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
Enumerate()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
Decode(int16 id,struct video_mode * mode)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
Get(struct video_mode * mode)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
Set(const struct video_mode * mode)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
Unset(const struct video_mode * mode)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
SetPalette(const struct video_mode * mode,const uint8 * palette)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
Framebuffer()799 MilanModeOps::Framebuffer()
800 {
801 //XXX
802 addr_t fb = (addr_t)Physbase();
803 return fb;
804 }
805
806
807 void
MakeLabel(const struct video_mode * mode,char * label,size_t len)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:
NFVDIModeOps()844 NFVDIModeOps() : ModeOps("NFVDI") {};
~NFVDIModeOps()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
Init()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
Enumerate()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
Get(struct video_mode * mode)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
Set(const struct video_mode * mode)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
Unset(const struct video_mode * mode)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
Framebuffer()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
Width(const struct video_mode * mode)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
Height(const struct video_mode * mode)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
Depth(const struct video_mode * mode)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
video_mode_hook(Menu * menu,MenuItem * item)1021 video_mode_hook(Menu *menu, MenuItem *item)
1022 {
1023 // find selected mode
1024 video_mode *mode = NULL;
1025
1026 Menu* submenu = item->Submenu();
1027 MenuItem* subitem = submenu->FindMarked();
1028 if (subitem != NULL) {
1029 switch (submenu->IndexOf(subitem)) {
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 *)subitem->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 *
video_mode_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
platform_blit4(addr_t frameBuffer,const uint8 * data,uint16 width,uint16 height,uint16 imageWidth,uint16 left,uint16 top)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
platform_set_palette(const uint8 * palette)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
platform_switch_to_logo(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
platform_switch_to_text_mode(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
platform_init_video(void)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