From aa3d547d095ff07fdc39ffc5ae4c371844b504ab Mon Sep 17 00:00:00 2001 From: Xin LI Date: Tue, 2 Mar 2010 01:56:55 +0000 Subject: MFC x86emu/x86bios emulator and make previously i386 only dpms and vesa framebuffer driver, etc. work on FreeBSD/amd64. A significant amount of improvements were done by jkim@ during the recent months to make vesa(4) work better, over the initial code import. This work is based on OpenBSD's x86emu implementation and contributed by paradox and swell.k at gmail com. Hopefully I have stolen all their work to 8-STABLE :) All bugs in this commit are mine, as usual. --- sys/dev/syscons/scvesactl.c | 2 +- sys/dev/syscons/scvgarndr.c | 20 ++++++- sys/dev/syscons/scvidctl.c | 77 ++++++++++++++++-------- sys/dev/syscons/syscons.c | 138 +++++++++++++++++++++++++++++++++++++------- sys/dev/syscons/syscons.h | 8 ++- 5 files changed, 194 insertions(+), 51 deletions(-) (limited to 'sys/dev/syscons') diff --git a/sys/dev/syscons/scvesactl.c b/sys/dev/syscons/scvesactl.c index 9a2c253869c8..b896484bb76e 100644 --- a/sys/dev/syscons/scvesactl.c +++ b/sys/dev/syscons/scvesactl.c @@ -43,7 +43,7 @@ __FBSDID("$FreeBSD$"); #include #include -#include +#include #include #include diff --git a/sys/dev/syscons/scvgarndr.c b/sys/dev/syscons/scvgarndr.c index 1ab41d2e5e4d..fd823ce434ba 100644 --- a/sys/dev/syscons/scvgarndr.c +++ b/sys/dev/syscons/scvgarndr.c @@ -193,6 +193,8 @@ static u_short mouse_or_mask[16] = { case 15: \ writew(pos, vga_palette15[color]); \ break; \ + case 8: \ + writeb(pos, (uint8_t)color); \ } static uint32_t vga_palette32[16] = { @@ -215,6 +217,7 @@ static uint16_t vga_palette15[16] = { #ifndef SC_NO_CUTPASTE static uint32_t mouse_buf32[256]; static uint16_t mouse_buf16[256]; +static uint8_t mouse_buf8[256]; #endif #endif @@ -498,7 +501,9 @@ vga_rndrinit(scr_stat *scp) scp->rndr->draw_cursor = vga_pxlcursor_planar; scp->rndr->blink_cursor = vga_pxlblink_planar; scp->rndr->draw_mouse = vga_pxlmouse_planar; - } else if (scp->sc->adp->va_info.vi_mem_model == V_INFO_MM_DIRECT) { + } else + if (scp->sc->adp->va_info.vi_mem_model == V_INFO_MM_DIRECT || + scp->sc->adp->va_info.vi_mem_model == V_INFO_MM_PACKED) { scp->rndr->clear = vga_pxlclear_direct; scp->rndr->draw_border = vga_pxlborder_direct; scp->rndr->draw = vga_vgadraw_direct; @@ -1148,6 +1153,7 @@ vga_pxlmouse_direct(scr_stat *scp, int x, int y, int on) int i, j; uint32_t *u32; uint16_t *u16; + uint8_t *u8; int bpp; if (!on) @@ -1179,6 +1185,10 @@ vga_pxlmouse_direct(scr_stat *scp, int x, int y, int on) u16 = (uint16_t*)(p + j * pixel_size); writew(u16, mouse_buf16[i * 16 + j]); break; + case 8: + u8 = (uint8_t*)(p + j * pixel_size); + writeb(u8, mouse_buf8[i * 16 + j]); + break; } } @@ -1214,6 +1224,14 @@ vga_pxlmouse_direct(scr_stat *scp, int x, int y, int on) else if (mouse_and_mask[i] & (1 << (15 - j))) writew(u16, 0); break; + case 8: + u8 = (uint8_t*)(p + j * pixel_size); + mouse_buf8[i * 16 + j] = *u8; + if (mouse_or_mask[i] & (1 << (15 - j))) + writeb(u8, 15); + else if (mouse_and_mask[i] & (1 << (15 - j))) + writeb(u8, 0); + break; } } diff --git a/sys/dev/syscons/scvidctl.c b/sys/dev/syscons/scvidctl.c index d69e0a8fc36f..0f55499bac74 100644 --- a/sys/dev/syscons/scvidctl.c +++ b/sys/dev/syscons/scvidctl.c @@ -369,30 +369,7 @@ sc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize, if ((info.vi_width < xsize*8) || (info.vi_height < ysize*fontsize)) return EINVAL; - /* - * We currently support the following graphic modes: - * - * - 4 bpp planar modes whose memory size does not exceed 64K - * - 15, 16, 24 and 32 bpp linear modes - */ - - if (info.vi_mem_model == V_INFO_MM_PLANAR) { - if (info.vi_planes != 4) - return ENODEV; - - /* - * A memory size >64K requires bank switching to access the entire - * screen. XXX - */ - - if (info.vi_width * info.vi_height / 8 > info.vi_window_size) - return ENODEV; - } else if (info.vi_mem_model == V_INFO_MM_DIRECT) { - if (!(info.vi_flags & V_INFO_LINEAR) && - (info.vi_depth != 15) && (info.vi_depth != 16) && - (info.vi_depth != 24) && (info.vi_depth != 32)) - return ENODEV; - } else + if (!sc_support_pixel_mode(&info)) return ENODEV; /* stop screen saver, etc */ @@ -468,6 +445,48 @@ sc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize, #endif /* SC_PIXEL_MODE */ } +int +sc_support_pixel_mode(void *arg) +{ +#ifdef SC_PIXEL_MODE + video_info_t *info = arg; + + if ((info->vi_flags & V_INFO_GRAPHICS) == 0) + return (0); + + /* + * We currently support the following graphic modes: + * + * - 4 bpp planar modes whose memory size does not exceed 64K + * - 15, 16, 24 and 32 bpp linear modes + */ + switch (info->vi_mem_model) { + case V_INFO_MM_PLANAR: + if (info->vi_planes != 4) + break; + /* + * A memory size >64K requires bank switching to access + * the entire screen. XXX + */ + if (info->vi_width * info->vi_height / 8 > info->vi_window_size) + break; + return (1); + case V_INFO_MM_DIRECT: + if ((info->vi_flags & V_INFO_LINEAR) == 0 && + info->vi_depth != 15 && info->vi_depth != 16 && + info->vi_depth != 24 && info->vi_depth != 32) + break; + return (1); + case V_INFO_MM_PACKED: + if ((info->vi_flags & V_INFO_LINEAR) == 0 && + info->vi_depth != 8) + break; + return (1); + } +#endif + return (0); +} + #define fb_ioctl(a, c, d) \ (((a) == NULL) ? ENODEV : \ vidd_ioctl((a), (c), (caddr_t)(d))) @@ -721,6 +740,11 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td) #endif #ifndef SC_NO_PALETTE_LOADING +#ifdef SC_PIXEL_MODE + if ((adp->va_flags & V_ADP_DAC8) != 0) + vidd_load_palette(adp, scp->sc->palette2); + else +#endif vidd_load_palette(adp, scp->sc->palette); #endif @@ -778,7 +802,10 @@ sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td) if (scp == scp->sc->cur_scp) { set_mode(scp); #ifndef SC_NO_PALETTE_LOADING - vidd_load_palette(adp, scp->sc->palette); + if ((adp->va_flags & V_ADP_DAC8) != 0) + vidd_load_palette(adp, scp->sc->palette2); + else + vidd_load_palette(adp, scp->sc->palette); #endif } sc_clear_screen(scp); diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c index 653ff08274a9..8dffe5cd5380 100644 --- a/sys/dev/syscons/syscons.c +++ b/sys/dev/syscons/syscons.c @@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include @@ -342,16 +343,105 @@ sc_alloc_tty(int index, int devnum) return (tp); } +#ifdef SC_PIXEL_MODE +static void +sc_set_vesa_mode(scr_stat *scp, sc_softc_t *sc, int unit) +{ + video_info_t info; + int depth; + int i; + int vmode; + + vmode = 0; + (void)resource_int_value("sc", unit, "vesa_mode", &vmode); + if (vmode < M_VESA_BASE || vmode > M_VESA_MODE_MAX || + vidd_get_info(sc->adp, vmode, &info) != 0 || + !sc_support_pixel_mode(&info)) + vmode = 0; + + /* + * If the mode is unset or unsupported, search for an available + * 800x600 graphics mode with the highest color depth. + */ + if (vmode == 0) { + for (depth = 0, i = M_VESA_BASE; i <= M_VESA_MODE_MAX; i++) + if (vidd_get_info(sc->adp, i, &info) == 0 && + info.vi_width == 800 && info.vi_height == 600 && + sc_support_pixel_mode(&info) && + info.vi_depth > depth) { + vmode = i; + depth = info.vi_depth; + } + if (vmode == 0) + return; + vidd_get_info(sc->adp, vmode, &info); + } + +#ifndef SC_NO_FONT_LOADING + if ((sc->fonts_loaded & FONT_16) == 0) + return; +#endif +#ifdef DEV_SPLASH + if ((sc->flags & SC_SPLASH_SCRN) != 0) + splash_term(sc->adp); +#endif +#ifndef SC_NO_HISTORY + if (scp->history != NULL) { + sc_vtb_append(&scp->vtb, 0, scp->history, + scp->ypos * scp->xsize + scp->xpos); + scp->history_pos = sc_vtb_tail(scp->history); + } +#endif + vidd_set_mode(sc->adp, vmode); + scp->status |= (UNKNOWN_MODE | PIXEL_MODE | MOUSE_HIDDEN); + scp->status &= ~(GRAPHICS_MODE | MOUSE_VISIBLE); + scp->xpixel = info.vi_width; + scp->ypixel = info.vi_height; + scp->xsize = scp->xpixel / 8; + scp->ysize = scp->ypixel / 16; + scp->xpos = 0; + scp->ypos = scp->ysize - 1; + scp->xoff = scp->yoff = 0; +#ifndef SC_NO_FONT_LOADING + scp->font = sc->font_16; +#else + scp->font = NULL; +#endif + scp->font_size = 16; + scp->font_width = 8; + scp->start = scp->xsize * scp->ysize - 1; + scp->end = 0; + scp->cursor_pos = scp->cursor_oldpos = scp->xsize * scp->xsize; + scp->mode = sc->initial_mode = vmode; +#ifndef __sparc64__ + sc_vtb_init(&scp->scr, VTB_FRAMEBUFFER, scp->xsize, scp->ysize, + (void *)sc->adp->va_window, FALSE); +#endif + sc_alloc_scr_buffer(scp, FALSE, FALSE); + sc_init_emulator(scp, NULL); +#ifndef SC_NO_CUTPASTE + sc_alloc_cut_buffer(scp, FALSE); +#endif +#ifndef SC_NO_HISTORY + sc_alloc_history_buffer(scp, 0, 0, FALSE); +#endif + sc_set_border(scp, scp->border); + sc_set_cursor_image(scp); + scp->status &= ~UNKNOWN_MODE; +#ifdef DEV_SPLASH + if ((sc->flags & SC_SPLASH_SCRN) != 0) + splash_init(sc->adp, scsplash_callback, sc); +#endif +} +#endif + int sc_attach_unit(int unit, int flags) { sc_softc_t *sc; scr_stat *scp; -#ifdef SC_PIXEL_MODE - video_info_t info; -#endif - int vc; struct cdev *dev; + int vc; flags &= ~SC_KERNEL_CONSOLE; @@ -373,21 +463,8 @@ sc_attach_unit(int unit, int flags) sc_console = scp; #ifdef SC_PIXEL_MODE - if ((sc->config & SC_VESA800X600) - && (vidd_get_info(sc->adp, M_VESA_800x600, &info) == 0)) { -#ifdef DEV_SPLASH - if (sc->flags & SC_SPLASH_SCRN) - splash_term(sc->adp); -#endif - sc_set_graphics_mode(scp, NULL, M_VESA_800x600); - sc_set_pixel_mode(scp, NULL, COL, ROW, 16, 8); - sc->initial_mode = M_VESA_800x600; -#ifdef DEV_SPLASH - /* put up the splash again! */ - if (sc->flags & SC_SPLASH_SCRN) - splash_init(sc->adp, scsplash_callback, sc); -#endif - } + if ((sc->config & SC_VESAMODE) != 0) + sc_set_vesa_mode(scp, sc, unit); #endif /* SC_PIXEL_MODE */ /* initialize cursor */ @@ -517,7 +594,7 @@ sctty_open(struct tty *tp) if (scp == NULL) { scp = SC_STAT(tp) = alloc_scp(sc, SC_VTY(tp)); if (ISGRAPHSC(scp)) - sc_set_pixel_mode(scp, NULL, COL, ROW, 16, 8); + sc_set_pixel_mode(scp, NULL, 0, 0, 16, 8); } if (!tp->t_winsize.ws_col && !tp->t_winsize.ws_row) { tp->t_winsize.ws_col = scp->xsize; @@ -2049,6 +2126,11 @@ restore_scrn_saver_mode(scr_stat *scp, int changemode) } if (set_mode(scp) == 0) { #ifndef SC_NO_PALETTE_LOADING +#ifdef SC_PIXEL_MODE + if ((scp->sc->adp->va_flags & V_ADP_DAC8) != 0) + vidd_load_palette(scp->sc->adp, scp->sc->palette2); + else +#endif vidd_load_palette(scp->sc->adp, scp->sc->palette); #endif --scrn_blanked; @@ -2452,8 +2534,14 @@ exchange_scr(sc_softc_t *sc) if (!ISGRAPHSC(scp)) sc_set_cursor_image(scp); #ifndef SC_NO_PALETTE_LOADING - if (ISGRAPHSC(sc->old_scp)) + if (ISGRAPHSC(sc->old_scp)) { +#ifdef SC_PIXEL_MODE + if ((sc->adp->va_flags & V_ADP_DAC8) != 0) + vidd_load_palette(sc->adp, sc->palette2); + else +#endif vidd_load_palette(sc->adp, sc->palette); + } #endif sc_set_border(scp, scp->border); @@ -2802,6 +2890,10 @@ scinit(int unit, int flags) #ifndef SC_NO_PALETTE_LOADING vidd_save_palette(sc->adp, sc->palette); +#ifdef SC_PIXEL_MODE + for (i = 0; i < sizeof(sc->palette2); i++) + sc->palette2[i] = i / 3; +#endif #endif #ifdef DEV_SPLASH @@ -2995,6 +3087,8 @@ init_scp(sc_softc_t *sc, int vty, scr_stat *scp) scp->ysize = info.vi_height; scp->xpixel = scp->xsize*info.vi_cwidth; scp->ypixel = scp->ysize*info.vi_cheight; + } + scp->font_size = info.vi_cheight; scp->font_width = info.vi_cwidth; if (info.vi_cheight < 14) { @@ -3016,7 +3110,7 @@ init_scp(sc_softc_t *sc, int vty, scr_stat *scp) scp->font = NULL; #endif } - } + sc_vtb_init(&scp->vtb, VTB_MEMORY, 0, 0, NULL, FALSE); #ifndef __sparc64__ sc_vtb_init(&scp->scr, VTB_FRAMEBUFFER, 0, 0, NULL, FALSE); diff --git a/sys/dev/syscons/syscons.h b/sys/dev/syscons/syscons.h index c0ed6c1fd642..aab6b5c82f1c 100644 --- a/sys/dev/syscons/syscons.h +++ b/sys/dev/syscons/syscons.h @@ -191,7 +191,7 @@ struct tty; typedef struct sc_softc { int unit; /* unit # */ int config; /* configuration flags */ -#define SC_VESA800X600 (1 << 7) +#define SC_VESAMODE (1 << 7) #define SC_AUTODETECT_KBD (1 << 8) #define SC_KERNEL_CONSOLE (1 << 9) @@ -245,7 +245,10 @@ typedef struct sc_softc { #endif #ifndef SC_NO_PALETTE_LOADING - u_char palette[256*3]; + u_char palette[256 * 3]; +#ifdef SC_PIXEL_MODE + u_char palette2[256 * 3]; +#endif #endif #ifndef SC_NO_FONT_LOADING @@ -616,6 +619,7 @@ int sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode, int sc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode); int sc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize, int fontsize, int font_width); +int sc_support_pixel_mode(void *arg); int sc_vid_ioctl(struct tty *tp, u_long cmd, caddr_t data, struct thread *td); -- cgit v1.3