Hello, Damien Zammit, le dim. 27 oct. 2024 09:38:01 +0000, a ecrit: > When bootloader sets a linear framebuffer mode and passes > the required info to Hurd via multiboot info table, we > can use this framebuffer as is. > Otherwise, fall back to EGA text mode as before.
Great :) > +static void > +blit_glyph(bdf_font_t font, char *mem, int ch, uint32_t rgb, int width, int > bpp) > +{ > + int w, h; > + > + struct bdf_glyph *gl; > + > + gl = bdf_find_glyph (font, ch, 0); > + if (!gl) > + gl = bdf_find_glyph (font, -1, ch); > + if (!gl) > + gl = bdf_find_glyph (font, '?', 0); > + > + assert_backtrace(gl != 0); > + > + for (h = 0; h < vga_hc; h++) > + { > + for (w = 0; w < vga_wc; w++) > + { > + char *pixel = mem + bpp/8 * (w + width * h); > + uint32_t colour = (gl->bitmap[h] & (1 << (7-w))) ? rgb : 0; You don't want to hardcode 0 as background, otherwise various applications that use black on color will be unreadable. You want to pass to such functions both fg_rgb and bg_rgb (as gotten from attr.bgcol) > + pixel[0] = (colour >> 16) & 0xff; > + pixel[1] = (colour >> 8) & 0xff; > + pixel[2] = colour & 0xff; > + } > + } > +} > + > +static void > +blit_glyph_xor(bdf_font_t font, char *mem, int ch, uint32_t rgb, int width, > int bpp) > +{ > + int w, h; > + > + struct bdf_glyph *gl; > + gl = bdf_find_glyph (font, ch, 0); > + if (!gl) > + gl = bdf_find_glyph (font, -1, ch); > + if (!gl) > + gl = bdf_find_glyph (font, '?', 0); Rather create a function that looks for these alternatives, that we'll be able to use in all the existing places that are already trying -1 as alternative (and could then be using '?' as well like you did). > + assert_backtrace(gl != 0); That function could return a hardcoded fallback, see console-client/vga-dynafont.c:594 > + for (h = 0; h < vga_hc; h++) > + { > + for (w = 0; w < vga_wc; w++) > + { > + char *pixel = mem + bpp/8 * (w + width * h); > + uint32_t colour = (gl->bitmap[h] & (1 << (7-w))) ? rgb : 0; > + pixel[0] ^= (colour >> 16) & 0xff; > + pixel[1] ^= (colour >> 8) & 0xff; > + pixel[2] ^= colour & 0xff; > + } > + } > +} > + > +static error_t > +fb_init(void) > +{ > + error_t err; > + int fd; > + > + fd = open ("/dev/mem", O_RDWR); > + if (fd >= 0) Better invert that test, that'll avoid the indentation. > + { > + vga_videomem = mmap (0, vga_width * vga_height * vga_bpp/8, PROT_READ > | PROT_WRITE, > + MAP_SHARED, fd, vga_fb); > + err = errno; > + close (fd); > + if (vga_videomem == (void *) -1) Rather use MMAP_FAILED. > + return err; > + } > + else > + return errno; > + > + /* Clear screen */ > + memset (vga_videomem, 0, vga_width * vga_height * vga_bpp/8); > + return 0; > +} [...] > +/* First 8 colours of EGA palette */ > +uint32_t console_rgb[8] = { > + 0x000000, /* black */ > + 0x0000aa, /* blue */ > + 0x00aa00, /* green */ > + 0x00aaaa, /* cyan */ > + 0xaa0000, /* red */ > + 0xaa00aa, /* magenta */ > + 0xffff55, /* yellow */ That's rather aa5500. > + 0xaaaaaa /* white */ > +}; Also, we don't want to use the EGA palette, but the ANSI palette: \x1b[30m foreground black \x1b[31m foreground red \x1b[32m foreground green \x1b[33m foreground yellow \x1b[34m foreground blue \x1b[35m foreground magenta \x1b[36m foreground cyan \x1b[37m foreground white otherwise the colors will be wrong. And while at it, you can hardcode the 8 bright colors: 0x555555 bright black 0xff5555 bright red 0x55ff55 bright green 0xffff55 bright yellow 0x5555ff bright blue 0xff55ff bright magenta 0x55ffff bright cyan 0xffffff bright white to be used when attr.intensity == CONS_ATTR_INTENSITY_BOLD > +static void > +hide_mousecursor (struct fb_display *disp) > +{ > + char *oldpos = vga_videomem + vga_bpp/8 * ((int) disp->mousecursor.posy * > vga_hc * disp->width > + + (int) disp->mousecursor.posx * vga_wc); Make this computation a macro, you have a lot of such. > + if (!disp->mousecursor.visible) > + return; > + > + /* First remove the old cursor. */ > + blit_glyph_xor (disp->font, oldpos, 'X', 0x00ff00, disp->width, vga_bpp); > + disp->mousecursor.visible = 0; > +} > +static void > +hide_cursor(struct fb_display *disp) > +{ > + int x, y; > + char *curpos; > + > + if (cursor_hidden) > + return; > + > + /* Remove old cursor */ > + x = cursor_pos % (disp->width/vga_wc); > + y = cursor_pos / (disp->width/vga_wc); > + curpos = vga_videomem + vga_bpp/8 * (y * vga_hc * disp->width + x * > vga_wc); > + blit_glyph_xor (disp->font, curpos, '_', 0xffffff, disp->width, vga_bpp); > + cursor_hidden = 1; > +} Rather use 0x2581, otherwise the cursor will be invisible over '_'. > +/* Set the cursor's position on display HANDLE to column COL and row > + ROW. */ > +static error_t > +fb_display_set_cursor_pos (void *handle, uint32_t col, uint32_t row) > +{ > + struct fb_display *disp = handle; > + > + /* If the cursor did not move from the character position, don't > + bother about updating the cursor position. */ > + if (cursor_state && (col == (cursor_pos % (disp->width/vga_wc))) > + && (row == (cursor_pos / (disp->width/vga_wc)))) > + return 0; > + > + hide_cursor (disp); Since hide_cursor will xor, we'd want an if (cursor_state) here too. > + cursor_pos = col + disp->width/vga_wc * row; It doesn't seem useful to keep cursor_pos as just one number? Better have cursor_pos_x and _y. > + if (cursor_state) > + draw_cursor (disp); > + > + return 0; > +} > + > +/* Deallocate any scarce resources occupied by the LENGTH characters > + from column COL and row ROW. */ You don't have anything to do here. See the clear field comment: « If there are no scarce resources, the caller might do nothing. » > +static error_t > +fb_display_clear (void *handle, size_t length, uint32_t col, uint32_t row) > +{ > + int len; > + struct fb_display *disp = handle; > + struct fbchr *refpos = &disp->refmatrix[row][0]; > + char *pos = vga_videomem; > + > +/* Scroll the display by the desired number of lines. The area that becomes > + free will be filled in a subsequent write call. */ > +static error_t > +fb_display_scroll (void *handle, int delta) > +{ > + struct fb_display *disp = handle; > + int pixels, chars, nextdelta = 0; > + char *pos = vga_videomem; > + uint32_t r; > + > + if (delta > disp->height/vga_hc) > + { > + nextdelta = delta - disp->height/vga_hc; > + delta = disp->height/vga_hc; > + } > + else if (delta < -(disp->height/vga_hc)) > + { > + nextdelta = delta + disp->height/vga_hc; > + delta = -(disp->height/vga_hc); > + } There is no use trying to wrap around like this: if delta is larger than the height, we just don't copy anything, and the caller will actually write the whole screen. See the comment of the scroll field. > + pixels = abs(delta)*vga_hc * disp->width; > + chars = abs(delta) * disp->width/vga_wc; > + > + hide_mousecursor (disp); > + hide_cursor (disp); > + > + /* XXX: If the virtual console is bigger than the physical console it is > + impossible to scroll because the data to scroll is not in memory. */ > + if (current_height > disp->height/vga_hc) > + return ENOTSUP; > + > + if (delta > 0) > + { > + memmove (vga_videomem, vga_videomem + vga_bpp/8 * pixels, > + vga_bpp/8 * disp->width * (disp->height - delta*vga_hc)); > + } > + else > + { > + memmove (vga_videomem + vga_bpp/8 * pixels, vga_videomem, > + vga_bpp/8 * disp->width * (disp->height + delta*vga_hc)); > + } > + > + if (delta > 0) > + { > + r = disp->height/vga_hc - delta; > + memmove (&disp->refmatrix[0][0], &disp->refmatrix[0][0] + chars, > + sizeof (struct fbchr) * disp->width/vga_wc * r); > + pos += vga_bpp/8 * (r*vga_hc * disp->width); > + } > + else > + { > + r = 0; > + memmove (&disp->refmatrix[0][0] + chars, &disp->refmatrix[0][0], > + sizeof (struct fbchr) * disp->width/vga_wc * > (disp->height/vga_hc + delta)); > + } > + > + fb_display_clear (disp, chars, 0, r); We don't need to clear, we have nothing there to do. > + if (nextdelta) > + fb_display_scroll (handle, nextdelta); > + > + return 0; > +} > + > + > + > +/* Write the text STR with LENGTH characters to column COL and row > + ROW. */ > +static error_t > +fb_display_write (void *handle, conchar_t *str, size_t length, > + uint32_t col, uint32_t row) > +{ > + struct fb_display *disp = handle; > + char *pos; > + struct fbchr *refpos = &disp->refmatrix[row][col]; > + char *mouse_cursor_pos; > + > + hide_mousecursor (disp); > + hide_cursor (disp); > + > + /* The starting column is outside the physical screen. */ > + if (disp->width/vga_wc < current_width && col >= disp->width/vga_wc) > + { > + size_t skip = current_width - disp->width/vga_wc; > + str += skip; > + length -= skip; > + col = 0; > + row += skip / current_width + 1; Why skip/current_width? By construction, skip < current_width. We only ever go to the next line, we have no reason to skip several lines. > + } > + > + mouse_cursor_pos = vga_videomem + vga_bpp/8 > + * ((int) disp->mousecursor.posy*vga_hc > + * disp->width + (int) disp->mousecursor.posx*vga_wc); > + > + while (length--) > + { > + int charval = str->chr; You changed the col++ position. Better do the same in the vga driver, to avoid divergence between both. > + /* The virtual console is smaller than the physical screen. */ > + if (col >= current_width) > + { > + size_t skip = disp->width/vga_wc - current_width; > + refpos += skip; > + col = 0; > + row += skip / disp->width/vga_wc + 1; ditto > + } > + /* The virtual console is bigger than the physical console. */ > + else if (disp->width/vga_wc < current_width && col == > disp->width/vga_wc) > + { > + size_t skip = current_width - disp->width/vga_wc; > + str += skip; > + length -= skip; > + col = skip % current_width; > + row += skip / current_width; ditto > + } > + > + /* The screen is filled until the bottom of the screen. */ > + if (row >= disp->height/vga_hc) Why /vga_hc?? > + return 0; > + > + pos = vga_videomem + (col*vga_wc + (row*vga_hc * disp->width)) * > vga_bpp/8; > + > + /* blit glyph to screen */ > + blit_glyph(disp->font, pos, charval, console_rgb[str->attr.fgcol], > disp->width, vga_bpp); > + > + if (pos == mouse_cursor_pos) > + disp->mousecursor.visible = 0; > + > + /* Perform reference counting. */ That comment was for code that you removed. > + refpos->used = 1; > + refpos->chr = charval; > + refpos->fgcol = str->attr.fgcol; > + refpos++; > + col++; > + > + /* Go to next character. */ > + str++; > + } > + return 0; > +} > + > +static error_t > +fb_set_mousecursor_pos (void *handle, float x, float y) > +{ > + struct fb_display *disp = handle; > + > + /* If the mouse did not move from the character position, don't > + bother about updating the cursor position. */ > + if (disp->mousecursor.visible && x == (int) disp->mousecursor.posx > + && y == (int) disp->mousecursor.posy) > + return 0; > + > + hide_mousecursor (disp); Since hide_mousecursor will xor, we'd want an if (cursor_state) here too. > + disp->mousecursor.posx = x; > + disp->mousecursor.posy = y; > + > + if (disp->mousecursor.enabled) > + draw_mousecursor (disp); > + > + return 0; > +} > + > + > diff --git a/console-client/fb.h b/console-client/fb.h > new file mode 100644 > index 00000000..23e0a51a > --- /dev/null > +++ b/console-client/fb.h > @@ -0,0 +1,74 @@ > +struct fbchr > +{ > + unsigned int used : 1; > + unsigned int chr : 9; You want a whole wchar_t, we don't have the 512-glyph limitation > + unsigned int fgcol: 3; > +}; > + > +typedef struct fb_mousecursor > +{ > + float posx; > + float posy; > + int visible; > + int enabled; > +} fb_mousecursor_t; > + > +struct fb_display > +{ > + /* The font for this display. */ > + bdf_font_t font; > + > + int df_size; > + int df_width; > + > + /* The color palette. */ > + dynacolor_t dc; This is unused (no hardware palette) > + int width; > + int height; > + > + /* The state of the mouse cursor. */ > + fb_mousecursor_t mousecursor; > + > + /* The position of the cursor, x_pos + y_pos * width (in characters) */ > + int cursor_pos; > + > + /* Remember for each cell on the display the glyph written to it and > + the colours assigned. 0 means unassigned. */ > + > + struct fbchr refmatrix[VGA_VIDEO_MEM_MAX_H / > VGA_PIXELS_H][VGA_VIDEO_MEM_MAX_W / VGA_PIXELS_W]; > +}; > + > +#endif > diff --git a/console-client/vga-hw.h b/console-client/vga-hw.h > index b4212e62..71ffb721 100644 > --- a/console-client/vga-hw.h > +++ b/console-client/vga-hw.h > @@ -24,6 +24,13 @@ > #define VGA_VIDEO_MEM_BASE_ADDR 0x0b8000 > #define VGA_VIDEO_MEM_LENGTH 0x004000 > > +#define VGA_VIDEO_MEM_MAX_W 1920 > +#define VGA_VIDEO_MEM_MAX_H 1080 > +#define VGA_VIDEO_MEM_MAX_BPP 32 > + > +#define VGA_PIXELS_W 8 > +#define VGA_PIXELS_H 16 This is not related to hardware conditions, better put them fb.h. > #define VGA_FONT_BUFFER 8 > #define VGA_FONT_SIZE 256 > #define VGA_FONT_HEIGHT 32 > diff --git a/console-client/vga-support.c b/console-client/vga-support.c > index 32ede46d..0fa229d4 100644 > --- a/console-client/vga-support.c > +++ b/console-client/vga-support.c > @@ -25,6 +25,9 @@ > #include <sys/io.h> > #include <sys/mman.h> > #include <sys/types.h> > +#include <device/device.h> > +#include <hurd.h> > +#include <mach.h> > #include <string.h> > #include <stdlib.h> > > @@ -32,8 +35,15 @@ > #include "vga-support.h" > > > -/* The base of the video memory mapping. */ > +/* The parameters of the video memory mapping. */ > char *vga_videomem; > +size_t vga_fb; That should rather be an off_t > +int vga_pitch; > +int vga_width; > +int vga_height; > +int vga_bpp; > +int vga_wc; > +int vga_hc; > > /* The saved state of the VGA card. */ > struct vga_state > @@ -56,14 +66,65 @@ struct vga_state > unsigned char attr_mode; > > /* Alignment is required by some "hardware", and optimizes transfers. */ > - char videomem[2 * 80 * 25] > + char videomem[VGA_VIDEO_MEM_MAX_W * VGA_VIDEO_MEM_MAX_H * > VGA_VIDEO_MEM_MAX_BPP / 8] ? No need to tinker with the vga driver videomem, and it's text cells there, not pixels. > __attribute__ ((aligned (__BIGGEST_ALIGNMENT__))); > - unsigned char fontmem[2 * VGA_FONT_SIZE * VGA_FONT_HEIGHT] > + unsigned char fontmem[VGA_VIDEO_MEM_MAX_BPP / 8 * VGA_FONT_SIZE * > VGA_FONT_HEIGHT] > __attribute__ ((aligned (__BIGGEST_ALIGNMENT__))); Even more so: VGA fonts is really always 2*256 glyphs. > }; > > static struct vga_state *vga_state; > > +error_t > +vga_get_multiboot_params (void) > +{ > + error_t ret = 0; > + mach_port_t master_device, mbinfo_dev; > + struct multiboot_raw_info mbi; > + char buf[sizeof(struct multiboot_raw_info)] = {0}; ? No need to initialize the array. > + char *bufptr = &buf[0]; > + uint32_t bytes = sizeof(struct multiboot_raw_info); > + uint32_t bytes_read = 0; > + > + ret = get_privileged_ports (NULL, &master_device); > + if (ret) > + goto fail; > + > + ret = device_open (master_device, D_READ, "mbinfo", &mbinfo_dev); > + mach_port_deallocate (mach_task_self (), master_device); > + if (ret) > + goto fail; > + > + ret = device_read (mbinfo_dev, D_READ, 0, bytes, &bufptr, &bytes_read); > + mach_port_deallocate (mach_task_self (), mbinfo_dev); > + if (ret) > + goto fail; > + > + if (bytes_read != bytes) > + goto fail; > + > + memcpy((void *)&mbi, (void *)bufptr, sizeof(struct multiboot_raw_info)); > + > + vga_fb = mbi.fb_info.framebuffer_addr; > + vga_pitch = mbi.fb_info.framebuffer_pitch; > + vga_width = mbi.fb_info.framebuffer_width; > + vga_height = mbi.fb_info.framebuffer_height; > + vga_bpp = mbi.fb_info.framebuffer_bpp; > + vga_wc = VGA_PIXELS_W; > + vga_hc = VGA_PIXELS_H; These two should be taken from the font. The bdf format unfortunately doesn't really provide the information (glyphs 0-31 are 16x16 in vga-system.bdf for instance). As a workaround you can take the bbox of the glyph for U+0020. > + return ret; > + > +fail: > + /* Fall back to EGA text mode */ > + vga_fb = VGA_VIDEO_MEM_BASE_ADDR; > + vga_pitch = 160; > + vga_width = 80; > + vga_height = 25; > + vga_bpp = 16; > + vga_wc = 1; > + vga_hc = 1; I don't think you need to initialize anything, provided you do not change the vga driver. And you can then call these fb_*, that'll mean something for non-vga hardware. > + return ret; > +} > + > > error_t > vga_init (void) > @@ -87,8 +148,8 @@ vga_init (void) > fd = open ("/dev/mem", O_RDWR); > if (fd >= 0) > { > - vga_videomem = mmap (0, VGA_VIDEO_MEM_LENGTH, PROT_READ | PROT_WRITE, > - MAP_SHARED, fd, VGA_VIDEO_MEM_BASE_ADDR); > + vga_videomem = mmap (0, vga_width * vga_height * vga_bpp, PROT_READ | > PROT_WRITE, > + MAP_SHARED, fd, vga_fb); In vga, bpp is always 2, and the video memory is always VGA_VIDEO_MEM_LENGTH (which allows to have some scrollback history actually). I don't think it's useful to mess with the vga driver, this is unrelated work. > err = errno; > close (fd); > if (vga_videomem == (void *) -1) > @@ -147,13 +208,13 @@ vga_init (void) > outb (VGA_GFX_MODE_ADDR, VGA_GFX_ADDR_REG); > outb (VGA_GFX_MODE_HOSTOE, VGA_GFX_DATA_REG); > > - memcpy (vga_state->videomem, vga_videomem, 2 * 80 * 25); > + memcpy (vga_state->videomem, vga_videomem, vga_width * vga_height * > vga_bpp / 8); > vga_read_font_buffer (0, 0, vga_state->fontmem, > - 2 * VGA_FONT_SIZE * VGA_FONT_HEIGHT); > + vga_bpp/8 * VGA_FONT_SIZE * VGA_FONT_HEIGHT); > > - /* 80 cols, 25 rows, two bytes per cell and twice because with lower > + /* X cols, Y rows, bpp/8 bytes per cell and twice because with lower > max scan line we get more lines on the screen. */ > - memset (vga_videomem, 0, 80 * 25 * 2 * 2); > + memset (vga_videomem, 0, vga_width * vga_height * vga_bpp / 4); > > return 0; > } > @@ -166,8 +227,8 @@ vga_fini (void) > { > /* Recover the saved state. */ > vga_write_font_buffer (0, 0, vga_state->fontmem, > - 2 * VGA_FONT_SIZE * VGA_FONT_HEIGHT); > - memcpy (vga_videomem, vga_state->videomem, 2 * 80 * 25); > + vga_bpp/8 * VGA_FONT_SIZE * VGA_FONT_HEIGHT); > + memcpy (vga_videomem, vga_state->videomem, vga_width * vga_height * > vga_bpp / 8); > > /* Restore the registers. */ > outb (VGA_SEQ_CLOCK_MODE_ADDR, VGA_SEQ_ADDR_REG); > @@ -207,7 +268,7 @@ vga_fini (void) > outb (0x00, VGA_ATTR_ADDR_DATA_REG); > > ioperm (VGA_MIN_REG, VGA_MAX_REG - VGA_MIN_REG + 1, 0); > - munmap (vga_videomem, VGA_VIDEO_MEM_LENGTH); > + munmap (vga_videomem, vga_width * vga_height * vga_bpp); > } > > > @@ -225,7 +286,7 @@ vga_read_write_font_buffer (int write, int buffer, int > index, > char saved_gfx_misc; > > int offset = buffer * VGA_FONT_SIZE + index * VGA_FONT_HEIGHT; > - assert_backtrace (offset >= 0 && offset + datalen <= VGA_VIDEO_MEM_LENGTH); > + assert_backtrace (offset >= 0 && offset + datalen <= vga_width * > vga_height * vga_bpp); > > /* Select plane 2 for sequential writing. You might think it is not > necessary for reading, but it is. Likewise for read settings > diff --git a/console-client/vga-support.h b/console-client/vga-support.h > index 17c0b5fd..a3de5aea 100644 > --- a/console-client/vga-support.h > +++ b/console-client/vga-support.h > @@ -23,6 +23,57 @@ > > #include <errno.h> > #include <sys/types.h> > +#include <stdint.h> > + > +struct multiboot_framebuffer_info { > + uint64_t framebuffer_addr; > + uint32_t framebuffer_pitch; > + uint32_t framebuffer_width; > + uint32_t framebuffer_height; > + uint8_t framebuffer_bpp; > +#define MULTIBOOT_FRAMEBUFFER_TYPE_INDEXED 0 > +#define MULTIBOOT_FRAMEBUFFER_TYPE_RGB 1 > +#define MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT 2 > + uint8_t framebuffer_type; > + union > + { > + struct > + { > + uint32_t framebuffer_palette_addr; > + uint16_t framebuffer_palette_num_colors; > + }; > + struct > + { > + uint8_t framebuffer_red_field_position; > + uint8_t framebuffer_red_mask_size; > + uint8_t framebuffer_green_field_position; > + uint8_t framebuffer_green_mask_size; > + uint8_t framebuffer_blue_field_position; > + uint8_t framebuffer_blue_mask_size; > + }; > + }; > +} __attribute__((packed)); > + > +/* > + * Multiboot information structure as passed by the boot loader. > + */ > +struct multiboot_raw_info { > + uint32_t flags; > + uint32_t mem_lower; > + uint32_t mem_upper; > + uint32_t unused0; > + uint32_t cmdline; > + uint32_t mods_count; > + uint32_t mods_addr; > + uint32_t shdr_num; > + uint32_t shdr_size; > + uint32_t shdr_addr; > + uint32_t shdr_strndx; > + uint32_t mmap_length; > + uint32_t mmap_addr; > + uint32_t unused1[9]; > + struct multiboot_framebuffer_info fb_info; > +} __attribute__((packed)); Rather put them in a separate header, it's unrelated to vga. > @@ -32,6 +83,15 @@ > > /* The mapped video memory. */ > extern char *vga_videomem; > +extern size_t vga_fb; > +extern int vga_width; > +extern int vga_height; > +extern int vga_bpp; > +extern int vga_wc; > +extern int vga_hc; > + > +/* Get the multiboot video parameters */ > +error_t vga_get_multiboot_params (void); > > /* Initialize the VGA hardware and set up the permissions and memory > mappings. */ > diff --git a/console-client/vga.c b/console-client/vga.c > index e954013d..67e7e3f2 100644 > --- a/console-client/vga.c > +++ b/console-client/vga.c > @@ -37,6 +37,7 @@ > #include "driver.h" > #include "timer.h" > > +#include "fb.h" > #include "vga-hw.h" > #include "vga-support.h" > #include "bdf.h" > @@ -45,8 +46,6 @@ > #include "unicode.h" > > > -#define VGA_DISP_WIDTH 80 > -#define VGA_DISP_HEIGHT 25 > > /* The font file. */ > #define DEFAULT_VGA_FONT DEFAULT_VGA_FONT_DIR "vga-system.bdf" > @@ -87,15 +86,19 @@ static int cursor_state; > /* Is set to 1 if the cursor moved out of the physical screen and the > cursor state should be hidden. */ > static int cursor_hidden; > + > +/* Forward declaration */ > +struct driver_ops driver_vga_ops; > + > > + > struct refchr > { > unsigned int used : 1; > unsigned int chr : 9; > - unsigned int attr : 8; > + unsigned int attr: 8; Avoid unrelated changes. > }; > > - > typedef struct vga_mousecursor > { > float posx; > @@ -129,7 +132,7 @@ struct vga_display > /* Remember for each cell on the display the glyph written to it and > the colors (in the upper byte) assigned. 0 means unassigned. */ > > - struct refchr refmatrix[VGA_DISP_HEIGHT][VGA_DISP_WIDTH]; > + struct refchr refmatrix[VGA_VIDEO_MEM_MAX_H / > VGA_PIXELS_H][VGA_VIDEO_MEM_MAX_W / VGA_PIXELS_W]; You don't need to change this, the vga driver is really stuck with hardware vga constraints, which are completely beneath fb capabilities. > }; > > > @@ -279,9 +282,12 @@ vga_display_init (void **handle, int no_exit, int argc, > char *argv[], > int *next) > { > error_t err; > - struct vga_display *disp; > + struct vga_display *vgadisp; > + struct fb_display *fbdisp; > int pos = 1; > > + vga_get_multiboot_params(); > + > /* XXX Assert that we are called only once. */ > pthread_mutex_init (&vga_display_lock, NULL); > timer_clear (&vga_display_timer); > @@ -294,22 +300,43 @@ vga_display_init (void **handle, int no_exit, int argc, > char *argv[], > if (err && err != EINVAL) > return err; > > - /* Create and initialize the display structure as much as > - possible. */ > - disp = calloc (1, sizeof *disp); > - if (!disp) > - return ENOMEM; > + if (vga_fb == VGA_VIDEO_MEM_BASE_ADDR) Should we not rather use framebuffer_type == MULTIBOOT_FRAMEBUFFER_TYPE_EGA_TEXT? in theory a framebuffer could be at VGA_VIDEO_MEM_BASE_ADDR > + { > + /* EGA text mode */ > + vgadisp = calloc (1, sizeof *vgadisp); > + if (!vgadisp) > + return ENOMEM; > + > + vgadisp->df_size = vga_display_max_glyphs ? 512 : 256; > + vgadisp->df_width = vga_display_font_width; > + vgadisp->width = vga_width; > + vgadisp->height = vga_height; > > - disp->df_size = vga_display_max_glyphs ? 512 : 256; > - disp->df_width = vga_display_font_width; > - disp->width = VGA_DISP_WIDTH; > - disp->height = VGA_DISP_HEIGHT; > + *handle = vgadisp; > + } > + else > + { > + /* Linear framebuffer! */ > + fbdisp = calloc (1, sizeof *fbdisp); > + if (!fbdisp) > + return ENOMEM; > + > + fbdisp->df_size = vga_display_max_glyphs ? 512 : 256; > + fbdisp->df_width = vga_display_font_width; > + fbdisp->width = vga_width; > + fbdisp->height = vga_height; > + > + /* dynamically switch drivers */ > + driver_vga_ops.start = fb_display_start; > + driver_vga_ops.fini = fb_display_fini; > + driver_vga_ops.restore_status = NULL; > + > + *handle = fbdisp; > + } > > - *handle = disp; > return 0; > } > > - > /* Start the driver. */ > static error_t > vga_display_start (void *handle) > -- > 2.45.2 > > >