terminal-vga: recover vga text mode operation

This commit is contained in:
K. Lange 2021-06-10 09:35:48 +09:00
parent 72968ed85c
commit 8531fe709e
4 changed files with 81 additions and 9 deletions

View File

@ -11,9 +11,20 @@
* try to move the hardware cursor off screen so it doesn't
* interfere with the rest of the terminal and look weird.
*/
#include <unistd.h>
#include <fcntl.h>
#include <sys/sysfunc.h>
int main(int argc, char * argv[]) {
int x[] = {0xFF,0xFF};
return sysfunc(TOARU_SYS_FUNC_SETVGACURSOR, (char **)x);
int fd = open("/dev/port", O_RDWR);
if (fd < 0) return 1;
lseek(fd, 0x3D4, SEEK_SET);
write(fd, (unsigned char[]){14}, 1);
lseek(fd, 0x3D5, SEEK_SET);
write(fd, (unsigned char[]){0xFF}, 1);
lseek(fd, 0x3D4, SEEK_SET);
write(fd, (unsigned char[]){15}, 1);
lseek(fd, 0x3D5, SEEK_SET);
write(fd, (unsigned char[]){0xFF}, 1);
return 0;
}

View File

@ -26,6 +26,8 @@
#include <wchar.h>
#include <kernel/video.h>
#include <toaru/decodeutf8.h>
#include <toaru/kbd.h>
#include <toaru/graphics.h>
@ -42,8 +44,8 @@
static int fd_master, fd_slave;
static FILE * terminal;
static uint16_t term_width = 80; /* Width of the terminal (in cells) */
static uint16_t term_height = 25; /* Height of the terminal (in cells) */
static ssize_t term_width = 80; /* Width of the terminal (in cells) */
static ssize_t term_height = 25; /* Height of the terminal (in cells) */
static uint16_t csr_x = 0; /* Cursor X */
static uint16_t csr_y = 0; /* Cursor Y */
static term_cell_t * term_buffer = NULL; /* The terminal cell buffer */
@ -481,7 +483,7 @@ void handle_input_s(char * c) {
write_input_buffer(c, len);
}
unsigned short * textmemptr = (unsigned short *)0xB8000;
unsigned short * textmemptr = NULL;
unsigned short * mirrorcopy = NULL;
void placech(unsigned char c, int x, int y, int attr) {
unsigned int where = y * term_width + x;
@ -1225,6 +1227,12 @@ int main(int argc, char ** argv) {
}
}
int vga_text_fd = open("/dev/vga0", 0, 0);
if (vga_text_fd < 0) return 1;
ioctl(vga_text_fd, IO_VID_WIDTH, &term_width);
ioctl(vga_text_fd, IO_VID_HEIGHT, &term_height);
ioctl(vga_text_fd, IO_VID_ADDR, &textmemptr);
putenv("TERM=toaru-vga");
openpty(&fd_master, &fd_slave, NULL, NULL, NULL);
@ -1247,7 +1255,7 @@ int main(int argc, char ** argv) {
fflush(stdin);
system("cursor-off"); /* Might GPF */
system("cursor-off");
signal(SIGUSR2, sig_suspend_input);
@ -1328,7 +1336,7 @@ int main(int argc, char ** argv) {
}
}
if (res[1]) {
int r = read(kfd, buf, BUF_SIZE);
int r = read(kfd, buf, 1);
for (int i = 0; i < r; ++i) {
int ret = kbd_scancode(&kbd_state, buf[i], &event);
key_event(ret, &event);

View File

@ -241,6 +241,8 @@ size_t fbterm_write(size_t size, uint8_t *buffer) {
}
void fbterm_initialize(void) {
if (!lfb_resolution_x) return;
if (args_present("fbterm-scroll")) {
fbterm_scroll = 1;
}

View File

@ -189,7 +189,9 @@ static struct procfs_entry framebuffer_entry = {
/* Install framebuffer device */
static void finalize_graphics(const char * driver) {
lfb_driver_name = driver;
lfb_device = lfb_video_device_create();
lfb_device->length = lfb_resolution_s * lfb_resolution_y; /* Size is framebuffer size in bytes */
vfs_mount("/dev/fb0", lfb_device);
procfs_install(&framebuffer_entry);
}
@ -447,6 +449,53 @@ static void auto_scan_pci(uint32_t device, uint16_t v, uint16_t d, void * extra)
}
}
static fs_node_t * vga_text_device = NULL;
static int ioctl_vga(fs_node_t * node, unsigned long request, void * argp) {
switch (request) {
case IO_VID_WIDTH:
/* Get framebuffer width */
validate(argp);
*((size_t *)argp) = 80;
return 0;
case IO_VID_HEIGHT:
/* Get framebuffer height */
validate(argp);
*((size_t *)argp) = 25;
return 0;
case IO_VID_ADDR:
/* Map framebuffer into userspace process */
validate(argp);
{
uintptr_t vga_user_offset;
if (*(uintptr_t*)argp == 0) {
vga_user_offset = 0x100000000;
} else {
validate((void*)(*(uintptr_t*)argp));
vga_user_offset = *(uintptr_t*)argp;
}
for (uintptr_t i = 0; i < 0x1000; i += 0x1000) {
union PML * page = mmu_get_page(vga_user_offset + i, MMU_GET_MAKE);
mmu_frame_map_address(page,MMU_FLAG_WRITABLE|MMU_FLAG_WC,((uintptr_t)(0xB8000) & 0xFFFFFFFF) + i);
}
*((uintptr_t *)argp) = vga_user_offset;
}
return 0;
default:
return -EINVAL;
}
}
static void vga_text_init(void) {
vga_text_device = calloc(sizeof(fs_node_t), 1);
snprintf(vga_text_device->name, 100, "vga0");
vga_text_device->length = 0;
vga_text_device->flags = FS_BLOCKDEVICE;
vga_text_device->mask = 0660;
vga_text_device->ioctl = ioctl_vga;
vfs_mount("/dev/vga0", vga_text_device);
}
static int lfb_init(const char * c) {
char * arg = strdup(c);
char * argv[10];
@ -479,6 +528,10 @@ static int lfb_init(const char * c) {
} else if (!strcmp(argv[0],"preset")) {
/* Set by bootloader (UEFI) */
graphics_install_preset(x,y);
} else if (!strcmp(argv[0],"text")) {
/* VGA text mode? TODO: We should try to detect this,
* or limit it to things that are likely to have it... */
vga_text_init();
} else {
ret_val = 1;
}
@ -488,9 +541,7 @@ static int lfb_init(const char * c) {
}
int framebuffer_initialize(void) {
lfb_device = lfb_video_device_create();
lfb_init(args_present("vid") ? args_value("vid") : "auto");
vfs_mount("/dev/fb0", lfb_device);
return 0;
}