Author: mmu_man Date: 2011-08-19 14:12:22 +0200 (Fri, 19 Aug 2011) New Revision: 42640 Changeset: https://dev.haiku-os.org/changeset/42640 Modified: haiku/trunk/src/system/boot/platform/atari_m68k/video.cpp Log: Add support for enumerating video modes using the Milan API and the ST/TT XBIOS calls. Not really tested, ARAnyM doesn't emulate the Milan stuff, and the ST resolutions aren't exactly chunky anyway (will need patching the framebuffer kernel args to include the mode/4CC instead of just bit depth). Modified: haiku/trunk/src/system/boot/platform/atari_m68k/video.cpp =================================================================== --- haiku/trunk/src/system/boot/platform/atari_m68k/video.cpp 2011-08-19 12:08:57 UTC (rev 42639) +++ haiku/trunk/src/system/boot/platform/atari_m68k/video.cpp 2011-08-19 12:12:22 UTC (rev 42640) @@ -25,7 +25,7 @@ #include <string.h> -//#define TRACE_VIDEO +#define TRACE_VIDEO #ifdef TRACE_VIDEO # define TRACE(x) dprintf x #else @@ -204,6 +204,202 @@ } +// #pragma mark - ST/TT XBIOS API + +class STModeOps : public ModeOps { +public: + STModeOps() : ModeOps("ST/TT") {}; + ~STModeOps() {}; + virtual status_t Init(); + + virtual status_t Enumerate(); + virtual status_t Decode(int16 id, struct video_mode *mode); + virtual status_t Get(struct video_mode *mode); + virtual status_t Set(const struct video_mode *mode); + virtual status_t Unset(const struct video_mode *mode); + + virtual status_t SetPalette(const struct video_mode *mode, + const uint8 *palette); + virtual addr_t Framebuffer(); + virtual void MakeLabel(const struct video_mode *mode, + char *label, size_t len); +private: + static int16 fPreviousMode; + static bool fIsTT; +}; + + +int16 STModeOps::fPreviousMode = -1; +bool STModeOps::fIsTT = false; + + +status_t +STModeOps::Init() +{ + const tos_cookie *c = tos_find_cookie('_VDO'); + if (c == NULL) + return ENODEV; + if (c->ivalue >> 16 < 1) + return ENODEV; + if (c->ivalue >= 2) + fIsTT = true; + fInitStatus = B_OK; + return fInitStatus; +} + + + +status_t +STModeOps::Enumerate() +{ + if (fInitStatus < B_OK) + return fInitStatus; + + static int16 modes[] = { 0, /*TT:*/ 4, 7 }; + for (int i = 0; i < sizeof(modes) / sizeof(int16); i++) { + if (!fIsTT && i > 0) + break; + + video_mode *videoMode = AllocMode(); + if (videoMode == NULL) + continue; + + if (Decode(modes[i], videoMode) != B_OK) + continue; + add_video_mode(videoMode); + + } + return B_OK; + +#if 0 + // TODO: use TT video monitor detection and build possible mode list there... + return ENODEV; +#endif +} + + +status_t +STModeOps::Decode(int16 id, struct video_mode *mode) +{ + mode->ops = this; + mode->mode = id; + + switch (id) { + case 0: + mode->width = 320; + mode->height = 200; + mode->bits_per_pixel = 4; + break; + case 4: + mode->width = 640; + mode->height = 480; + mode->bits_per_pixel = 4; + break; + case 7: + mode->width = 320; + mode->height = 480; + mode->bits_per_pixel = 8; + break; + default: + mode->bits_per_pixel = 0; + break; + } + + mode->bytes_per_row = mode->width * mode->bits_per_pixel / 8; + return B_OK; +} + + +status_t +STModeOps::Get(struct video_mode *mode) +{ + if (fInitStatus < B_OK) + return fInitStatus; + + int16 m = Getrez(); + return Decode(m, mode); +} + + +status_t +STModeOps::Set(const struct video_mode *mode) +{ + if (fInitStatus < B_OK) + return fInitStatus; + if (mode == NULL) + return B_BAD_VALUE; + + fPreviousMode = Getrez(); + +#warning M68K: FIXME: allocate framebuffer + dprintf("Switching to mode 0x%04x\n", mode->mode); + //VsetScreen(((uint32)0x00d00000), ((uint32)0x00d00000), 3, mode->mode); + Setscreen(-1, -1, mode->mode, 0); + if (Getrez() != mode->mode) { + dprintf("failed to set mode %d. Current is %d\n", mode->mode, fPreviousMode); + fPreviousMode = -1; + } + + return B_OK; +} + + +status_t +STModeOps::Unset(const struct video_mode *mode) +{ + if (fInitStatus < B_OK) + return fInitStatus; + + if (fPreviousMode != -1) { + dprintf("Reverting to mode 0x%04x\n", fPreviousMode); + Setscreen(-1, -1, fPreviousMode, 0); + fPreviousMode = -1; + } + + return B_OK; +} + + +status_t +STModeOps::SetPalette(const struct video_mode *mode, const uint8 *palette) +{ + switch (mode->bits_per_pixel) { + case 4: + //VsetRGB(0, 16, palette); + //XXX: Use ESet* + break; + case 8: + //VsetRGB(0, 256, palette); + //XXX: Use ESet* + break; + default: + break; + } +} + + +addr_t +STModeOps::Framebuffer() +{ + addr_t fb = (addr_t)Physbase(); + return fb; +} + + +void +STModeOps::MakeLabel(const struct video_mode *mode, char *label, + size_t len) +{ + ModeOps::MakeLabel(mode, label, len); + label += strlen(label); + // XXX no len check + sprintf(label, " 0x%04x", mode->mode); +} + + +static STModeOps sSTModeOps; + + // #pragma mark - Falcon XBIOS API class FalconModeOps : public ModeOps { @@ -345,7 +541,9 @@ #warning M68K: FIXME: allocate framebuffer dprintf("Switching to mode 0x%04x\n", mode->mode); - VsetScreen(((uint32)0x00d00000), ((uint32)0x00d00000), 3, mode->mode); + //VsetScreen(((uint32)0x00d00000), ((uint32)0x00d00000), 3, mode->mode); + VsetScreen(((uint32)0x00c00000), ((uint32)0x00c00000), 3, mode->mode); + //VsetScreen(((uint32)-1), ((uint32)-1), 3, mode->mode); return B_OK; } @@ -412,6 +610,221 @@ static FalconModeOps sFalconModeOps; +// #pragma mark - Milan XBIOS API + +class MilanModeOps : public ModeOps { +public: + MilanModeOps() : ModeOps("Milan") {}; + ~MilanModeOps() {}; + virtual status_t Init(); + + virtual status_t Enumerate(); + virtual status_t Decode(int16 id, struct video_mode *mode); + virtual status_t Get(struct video_mode *mode); + virtual status_t Set(const struct video_mode *mode); + virtual status_t Unset(const struct video_mode *mode); + + virtual status_t SetPalette(const struct video_mode *mode, + const uint8 *palette); + virtual addr_t Framebuffer(); + virtual void MakeLabel(const struct video_mode *mode, + char *label, size_t len); +private: + static int16 fPreviousMode; +}; + + +int16 MilanModeOps::fPreviousMode = -1; + + +status_t +MilanModeOps::Init() +{ + const tos_cookie *c = tos_find_cookie('_MIL'); + if (c == NULL) + return ENODEV; + fInitStatus = B_OK; + return fInitStatus; +} + + + +status_t +MilanModeOps::Enumerate() +{ + if (fInitStatus < B_OK) + return fInitStatus; + + SCREENINFO info; + info.size = sizeof(info); + + + static int16 modes[] = { + 0x001b, 0x001c, 0x002b, 0x002c, + 0x003a, 0x003b, 0x003c, 0x000c, + 0x0034, 0x0004 + /*0x003a, 0x003b, 0x0003, 0x000c, + 0x000b, 0x0033, 0x000c, 0x001c*/ }; + for (int i = 0; i < sizeof(modes) / sizeof(int16); i++) { + video_mode *videoMode = AllocMode(); + if (videoMode == NULL) + continue; + + if (Decode(modes[i], videoMode) != B_OK) + continue; + add_video_mode(videoMode); + + } + return B_OK; + +#if 0 + // TODO: use Milan video monitor detection and build possible mode list there... + int16 monitor; + bool vga = false; + bool tv = false; + monitor = VgetMonitor(); + switch (monitor) { + case 0: + panic("Monochrome ?\n"); + break; + case 2: + vga = true; + break; + case 3: + tv = true; + break; + //case 4 & 5: check for CT60 + case 1: + default: + dprintf("monitor type %d\n", monitor); + break; + } + return ENODEV; +#endif +} + + +status_t +MilanModeOps::Decode(int16 id, struct video_mode *mode) +{ + SCREENINFO info; + info.size = sizeof(info); + info.devID = mode->mode; + info.scrFlags = 0; + + mode->ops = this; + mode->mode = id; + + Setscreen(-1,&info,MI_MAGIC,CMD_GETINFO); + + if (info.scrFlags & SCRINFO_OK == 0) + return B_ERROR; + + // cf. F30.TXT + mode->width = info.scrWidth; + mode->height = info.scrHeight; + mode->bits_per_pixel = info.scrPlanes; + mode->bytes_per_row = mode->width * mode->bits_per_pixel / 8; + return B_OK; +} + + +status_t +MilanModeOps::Get(struct video_mode *mode) +{ + if (fInitStatus < B_OK) + return fInitStatus; + + int16 m = -1; + Setscreen(-1,&m,MI_MAGIC,CMD_GETMODE); + if (m == -1) + return B_ERROR; + return Decode(m, mode); +} + + +status_t +MilanModeOps::Set(const struct video_mode *mode) +{ + if (fInitStatus < B_OK) + return fInitStatus; + if (mode == NULL) + return B_BAD_VALUE; + + Setscreen(-1,&fPreviousMode,MI_MAGIC,CMD_GETMODE); + +#warning M68K: FIXME: allocate framebuffer + dprintf("Switching to mode 0x%04x\n", mode->mode); + //VsetScreen(((uint32)0x00d00000), ((uint32)0x00d00000), 3, mode->mode); + //VsetScreen(((uint32)-1), ((uint32)-1), 3, mode->mode); + Setscreen(-1,mode->mode,MI_MAGIC,CMD_SETMODE); + + return B_OK; +} + + +status_t +MilanModeOps::Unset(const struct video_mode *mode) +{ + if (fInitStatus < B_OK) + return fInitStatus; + + if (fPreviousMode != -1) { + dprintf("Reverting to mode 0x%04x\n", fPreviousMode); + Setscreen(-1,fPreviousMode,MI_MAGIC,CMD_SETMODE); + fPreviousMode = -1; + } + + return B_OK; +} + + +status_t +MilanModeOps::SetPalette(const struct video_mode *mode, const uint8 *palette) +{ + switch (mode->bits_per_pixel) { + case 4: + //VsetRGB(0, 16, palette); + break; + case 8: + //VsetRGB(0, 256, palette); + break; + default: + break; + } +} + + +addr_t +MilanModeOps::Framebuffer() +{ + //XXX + addr_t fb = (addr_t)Physbase(); + return fb; +} + + +void +MilanModeOps::MakeLabel(const struct video_mode *mode, char *label, + size_t len) +{ + ModeOps::MakeLabel(mode, label, len); + label += strlen(label); + // XXX no len check + int16 m = mode->mode; + sprintf(label, " 0x%04x", mode->mode); + /*sprintf(label, "%s%s%s%s", + m & 0x0010 ? " vga" : " tv", + m & 0x0020 ? " pal" : "", + m & 0x0040 ? " oscan" : "", + //m & 0x0080 ? " tv" : "", + m & 0x0100 ? " ilace" : "");*/ +} + + +static MilanModeOps sMilanModeOps; + + // #pragma mark - ARAnyM NFVDI API /* NatFeat VDI */ @@ -723,7 +1136,7 @@ } gKernelArgs.frame_buffer.enabled = true; -#if 0 +#if 1 // If the new frame buffer is either larger than the old one or located at // a different address, we need to remap it, so we first have to throw // away its previous mapping @@ -777,7 +1190,11 @@ //sNFVDIModeOps.Init(); //sNFVDIModeOps.Enumerate(); - if (sFalconModeOps.Init() == B_OK) { + if (sMilanModeOps.Init() == B_OK) { + sMilanModeOps.Enumerate(); + } else if (sSTModeOps.Init() == B_OK) { + sSTModeOps.Enumerate(); + } else if (sFalconModeOps.Init() == B_OK) { sFalconModeOps.Enumerate(); } else { dprintf("No usable video API found\n");