我最近一直试图在NetBSD 5.1.2上使用wscons
和wsdisplay
(使用VESA帧缓冲实现),我遇到了一些问题:
我可以成功设置色彩映射并且它们看起来正确但 获取色彩映射似乎返回不正确的数据,这样当我尝试程序完成后,恢复原始颜色映射,所有颜色都不正确:
这是导致问题的简化程序(请注意,它必须以root
或用户登录第二个虚拟终端(/dev/ttyE1
)运行:
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <dev/wscons/wsconsio.h>
int main(int argc, char **argv) {
(void)argc, (void)argv;
int tty = open("/dev/ttyE1", O_RDWR | O_EXCL);
if(tty == -1) {
perror("error opening tty");
return EXIT_FAILURE;
}
struct wsdisplay_fbinfo fbinfo;
if(ioctl(tty, WSDISPLAYIO_GINFO, &fbinfo) == -1) {
perror("error retrieving framebuffer info");
close(tty);
return EXIT_FAILURE;
}
uint8_t *cmap_data = malloc(fbinfo.cmsize * 3);
if(cmap_data == NULL) {
perror("error allocating memory for color map data");
close(tty);
return EXIT_FAILURE;
}
struct wsdisplay_cmap cmap;
cmap.index = 0;
cmap.count = fbinfo.cmsize;
cmap.red = &cmap_data[fbinfo.cmsize * 0];
cmap.green = &cmap_data[fbinfo.cmsize * 1];
cmap.blue = &cmap_data[fbinfo.cmsize * 2];
if(ioctl(tty, WSDISPLAYIO_GETCMAP, &cmap) == -1) {
perror("error getting color map");
close(tty), free(cmap_data);
return EXIT_FAILURE;
}
if(ioctl(tty, WSDISPLAYIO_PUTCMAP, &cmap) == -1) {
perror("error putting color map");
close(tty), free(cmap_data);
return EXIT_FAILURE;
}
free(cmap_data);
close(tty);
return EXIT_SUCCESS;
}
我做错了什么,如何才能正确检索和恢复彩色地图?
答案 0 :(得分:0)
我更多地研究了这个问题,似乎某些内核内存未初始化或被破坏。具体而言,sc_cmap_red
的{{1}},sc_cmap_green
和sc_cmap_blue
(在第89到91行的vesafbvar.h
中)包含不正确的数据。这有点令人惊讶,因为vesafb.c
的第719行到第722行初始化它:
struct vesafb_softc
它包含不正确的数据,即使我将其移出/* Fill in the softc colourmap arrays */
sc->sc_cmap_red[i / 3] = rasops_cmap[i + 0];
sc->sc_cmap_green[i / 3] = rasops_cmap[i + 1];
sc->sc_cmap_blue[i / 3] = rasops_cmap[i + 2];
语句,因此它可能会被破坏而不是未初始化。
驱动程序 能够正确获取和设置颜色映射;它似乎无法在if
中获得最初的那个。
一个简单的解决方案是让程序重新设置默认的颜色映射。如上面的代码段所示,假设从struct vesafb_softc
获取其初始颜色,恰好在rasops.c
的第55到122行定义:
rasops_cmap
使用这些颜色,您可以创建一个程序,将其设置为当前颜色映射。我不得不进行一些更改,因此光标不会消失,但它大部分都有效。
当我四处寻找更多信息时,我找到了this blog post。当我用genfb(4)
而不是vesafb(4)
重新编译内核时,内核在启动时挂起。事实证明这是因为我使用的引导加载程序不够新,无法将所需的参数传递给内核。
我碰巧看了NetBSD 6.0 changelog并注意到了这个条目:
我下载了NetBSD 6.0_BETA并从启动提示符启动它,如下所示:
/* ANSI colormap (R,G,B). Upper 8 are high-intensity */
const u_char rasops_cmap[256*3] = {
/* ... */
};
......一切正常。
vesafb(4)
可以解决问题。