diff --git a/elks/arch/i86/drivers/char/Makefile b/elks/arch/i86/drivers/char/Makefile index b40a38ce3..e3206c991 100644 --- a/elks/arch/i86/drivers/char/Makefile +++ b/elks/arch/i86/drivers/char/Makefile @@ -62,6 +62,9 @@ endif else ifdef CONFIG_CONSOLE_DIRECT OBJS += console-direct.o bell-8254.o +ifdef CONFIG_CONSOLE_DUAL +OBJS += crtc-6845.o +endif endif endif diff --git a/elks/arch/i86/drivers/char/config.in b/elks/arch/i86/drivers/char/config.in index bad145cc4..bcde5cb59 100644 --- a/elks/arch/i86/drivers/char/config.in +++ b/elks/arch/i86/drivers/char/config.in @@ -12,6 +12,7 @@ mainmenu_option next_comment Headless CONFIG_CONSOLE_HEADLESS" Direct if [ "$CONFIG_CONSOLE_DIRECT" = "y" ]; then bool ' Scancode keyboard driver' CONFIG_KEYBOARD_SCANCODE y + bool ' Dual-screen console support' CONFIG_CONSOLE_DUAL n fi bool 'Serial Console' CONFIG_CONSOLE_SERIAL n if [[ "$CONFIG_CONSOLE_DIRECT" = "y" || "$CONFIG_CONSOLE_BIOS" = "y" ]]; then diff --git a/elks/arch/i86/drivers/char/console-bios.c b/elks/arch/i86/drivers/char/console-bios.c index 849614c83..03a9e6ff6 100644 --- a/elks/arch/i86/drivers/char/console-bios.c +++ b/elks/arch/i86/drivers/char/console-bios.c @@ -41,16 +41,21 @@ #define MAXPARMS 28 +#define MAX_DISPLAYS 1 + struct console; typedef struct console Console; struct console { int cx, cy; /* cursor position */ void (*fsm)(Console *, int); + unsigned char display; unsigned char attr; /* current attribute */ unsigned char XN; /* delayed newline on column 80 */ unsigned char color; /* fg/bg attr */ int pageno; /* video ram page # */ + unsigned short Width; + unsigned short Height; #ifdef CONFIG_EMUL_ANSI int savex, savey; /* saved cursor position */ unsigned char *parmptr; /* ptr to params */ @@ -58,13 +63,13 @@ struct console { #endif }; +static Console *glock; static struct wait_queue glock_wait; -static Console Con[MAX_CONSOLES], *Visible; -static Console *glock; /* Which console owns the graphics hardware */ -static int Width, MaxCol, Height, MaxRow; +static Console *Visible[MAX_DISPLAYS]; +static Console Con[MAX_CONSOLES]; static int NumConsoles = MAX_CONSOLES; static int kraw; -static int Current_VCminor = 0; +static int Current_VCminor; #ifdef CONFIG_EMUL_ANSI #define TERM_TYPE " emulating ANSI " @@ -93,7 +98,7 @@ static void PositionCursorGet (int * x, int * y) *y = row; } -static void DisplayCursor(int onoff) +static void DisplayCursor(Console * C, int onoff) { } @@ -111,14 +116,14 @@ static void scroll(register Console * C, int n, int x, int y, int xx, int yy) int a; a = C->attr; - if (C != Visible) { + if (C != Visible[C->display]) { bios_setpage(C->pageno); } bios_scroll (a, n, x, y, xx, yy); - if (C != Visible) { - bios_setpage(Visible->pageno); + if (C != Visible[C->display]) { + bios_setpage(Visible[C->display]->pageno); } } @@ -129,13 +134,13 @@ static void ClearRange(register Console * C, int x, int y, int xx, int yy) static void ScrollUp(register Console * C, int y) { - scroll(C, 1, 0, y, MaxCol, MaxRow); + scroll(C, 1, 0, y, C->Width - 1, C->Height - 1); } #ifdef CONFIG_EMUL_ANSI static void ScrollDown(register Console * C, int y) { - scroll(C, -1, 0, y, MaxCol, MaxRow); + scroll(C, -1, 0, y, C->Width - 1, C->Height - 1); } #endif @@ -148,12 +153,13 @@ static void ScrollDown(register Console * C, int y) void Console_set_vc(int N) { - if ((N >= NumConsoles) || (Visible == &Con[N]) || glock) + Console *C = &Con[N]; + if ((N >= NumConsoles) || (Visible[C->display] == C) || glock) return; - Visible = &Con[N]; + Visible[C->display] = C; bios_setpage(N); - PositionCursor(Visible); + PositionCursor(Visible[C->display]); Current_VCminor = N; } @@ -171,23 +177,21 @@ void INITPROC console_init(void) Console *C; int i; - MaxCol = (Width = SETUP_VID_COLS) - 1; - - /* Trust this. Cga does not support peeking at 0x40:0x84. */ - MaxRow = (Height = SETUP_VID_LINES) - 1; + C = Con; + C->Width = SETUP_VID_COLS; + C->Height = SETUP_VID_LINES; if (peekb(0x49, 0x40) == 7) /* BIOS data segment */ NumConsoles = 1; - C = Con; - Visible = C; - for (i = 0; i < NumConsoles; i++) { + C->display = 0; C->cx = C->cy = 0; if (!i) { - // Get current cursor position - // to write after boot messages - PositionCursorGet (&C->cx, &C->cy); + Visible[C->display] = C; + // Get current cursor position + // to write after boot messages + PositionCursorGet (&C->cx, &C->cy); } C->fsm = std_char; C->pageno = i; @@ -201,7 +205,7 @@ void INITPROC console_init(void) #endif /* Do not erase early printk() */ - /* ClearRange(C, 0, C->cy, MaxCol, MaxRow); */ + /* ClearRange(C, 0, C->cy, C->MaxCol, C->MaxRow); */ C++; } @@ -209,5 +213,5 @@ void INITPROC console_init(void) kbd_init(); printk("BIOS console %ux%u"TERM_TYPE"(%d virtual consoles)\n", - Width, Height, NumConsoles); + Con[0].Width, Con[0].Height, NumConsoles); } diff --git a/elks/arch/i86/drivers/char/console-direct-pc98.c b/elks/arch/i86/drivers/char/console-direct-pc98.c index 96d38dccb..bd9f5fe45 100644 --- a/elks/arch/i86/drivers/char/console-direct-pc98.c +++ b/elks/arch/i86/drivers/char/console-direct-pc98.c @@ -48,16 +48,21 @@ #define MAXPARMS 28 +#define MAX_DISPLAYS 1 + struct console; typedef struct console Console; struct console { int cx, cy; /* cursor position */ void (*fsm)(Console *, int); + unsigned char display; unsigned char attr; /* current attribute */ unsigned char XN; /* delayed newline on column 80 */ - unsigned int vseg; /* video segment for page */ - int basepage; /* start of video ram */ + unsigned int vseg; /* vram for this console page */ + int vseg_offset; /* vram offset of vseg for this console page */ + unsigned short Width; + unsigned short Height; #ifdef CONFIG_EMUL_ANSI int savex, savey; /* saved cursor position */ unsigned char *parmptr; /* ptr to params */ @@ -65,14 +70,14 @@ struct console { #endif }; +static Console *glock; static struct wait_queue glock_wait; -static Console Con[MAX_CONSOLES], *Visible; -static Console *glock; /* Which console owns the graphics hardware */ -static int Width, MaxCol, Height, MaxRow; +static Console *Visible[MAX_DISPLAYS]; +static Console Con[MAX_CONSOLES]; static int NumConsoles = MAX_CONSOLES; -int Current_VCminor = 0; -int kraw = 0; +int Current_VCminor; +int kraw; unsigned VideoSeg; unsigned AttributeSeg; @@ -92,11 +97,11 @@ static void PositionCursor(register Console * C) { int Pos; - Pos = C->cx + Width * C->cy + C->basepage; + Pos = C->cx + C->Width * C->cy + C->vseg_offset; cursor_set(Pos * 2); } -static void DisplayCursor(int onoff) +static void DisplayCursor(Console * C, int onoff) { if (onoff) cursor_on(); @@ -130,7 +135,7 @@ static void VideoWrite(register Console * C, int c) word_t addr; word_t attr; - addr = (C->cx + C->cy * Width) << 1; + addr = (C->cx + C->cy * C->Width) << 1; attr = (C->attr == A_DEFAULT) ? A98_DEFAULT : conv_pcattr(C->attr); pokew(addr, (seg_t) AttributeSeg, attr); @@ -145,24 +150,26 @@ static void ClearRange(register Console * C, int x, int y, int xx, int yy) attr = (C->attr == A_DEFAULT) ? A98_DEFAULT : conv_pcattr(C->attr); xx = xx - x + 1; - vp = (__u16 *)((__u16)(x + y * Width) << 1); + vp = (__u16 *)((__u16)(x + y * C->Width) << 1); do { for (x = 0; x < xx; x++) { pokew((word_t) vp, AttributeSeg, attr); pokew((word_t) (vp++), (seg_t) C->vseg, (word_t) ' '); } - vp += (Width - xx); + vp += (C->Width - xx); } while (++y <= yy); } static void ScrollUp(register Console * C, int y) { - register __u16 *vp; + __u16 *vp; + unsigned short MaxRow = C->Height - 1; + unsigned short MaxCol = C->Width - 1; - vp = (__u16 *)((__u16)(y * Width) << 1); + vp = (__u16 *)((__u16)(y * C->Width) << 1); if ((unsigned int)y < MaxRow) { - fmemcpyb(vp, AttributeSeg, vp + Width, AttributeSeg, (MaxRow - y) * (Width << 1)); - fmemcpyb(vp, C->vseg, vp + Width, C->vseg, (MaxRow - y) * (Width << 1)); + fmemcpyb(vp, AttributeSeg, vp + C->Width, AttributeSeg, (MaxRow - y) * (C->Width << 1)); + fmemcpyb(vp, C->vseg, vp + C->Width, C->vseg, (MaxRow - y) * (C->Width << 1)); } ClearRange(C, 0, MaxRow, MaxCol, MaxRow); } @@ -170,14 +177,16 @@ static void ScrollUp(register Console * C, int y) #ifdef CONFIG_EMUL_ANSI static void ScrollDown(register Console * C, int y) { - register __u16 *vp; + __u16 *vp; + unsigned short MaxRow = C->Height - 1; + unsigned short MaxCol = C->Width - 1; int yy = MaxRow; - vp = (__u16 *)((__u16)(yy * Width) << 1); + vp = (__u16 *)((__u16)(yy * C->Width) << 1); while (--yy >= y) { - fmemcpyb(vp, AttributeSeg, vp - Width, AttributeSeg, Width << 1); - fmemcpyb(vp, C->vseg, vp - Width, C->vseg, Width << 1); - vp -= Width; + fmemcpyb(vp, AttributeSeg, vp - C->Width, AttributeSeg, C->Width << 1); + fmemcpyb(vp, C->vseg, vp - C->Width, C->vseg, C->Width << 1); + vp -= C->Width; } ClearRange(C, 0, y, MaxCol, y); } @@ -192,12 +201,12 @@ static void ScrollDown(register Console * C, int y) void Console_set_vc(int N) { - if ((N >= NumConsoles) || (Visible == &Con[N]) || glock) - return; - Visible = &Con[N]; - - SetDisplayPage(Visible); - PositionCursor(Visible); + Console *C = &Con[N]; + if ((N >= NumConsoles) || (Visible[C->display] == C) || glock) + return; + Visible[C->display] = C; + SetDisplayPage(Visible[C->display]); + PositionCursor(Visible[C->display]); Current_VCminor = N; } @@ -224,26 +233,25 @@ void INITPROC console_init(void) AttributeSeg = 0xE200; } - MaxCol = (Width = 80) - 1; - - MaxRow = (Height = 25) - 1; + C = Con; + C->Width = 80; + C->Height = 25; PageSizeW = 2000; NumConsoles = 1; - C = Con; - Visible = C; - for (i = 0; i < NumConsoles; i++) { + C->display = 0; C->cx = C->cy = 0; if (!i) { + Visible[C->display] = C; C->cx = read_tvram_x() % 160; C->cy = read_tvram_x() / 160; } C->fsm = std_char; - C->basepage = i * PageSizeW; - C->vseg = VideoSeg + (C->basepage >> 3); + C->vseg_offset = i * PageSizeW; + C->vseg = VideoSeg + (C->vseg_offset >> 3); C->attr = A_DEFAULT; #ifdef CONFIG_EMUL_ANSI @@ -261,5 +269,5 @@ void INITPROC console_init(void) kbd_init(); printk("Direct console, %s kbd %ux%u"TERM_TYPE"(du virtual consoles)\n", - kbd_name, Width, Height, NumConsoles); + kbd_name, Con[0].Width, Con[0].Height, NumConsoles); } diff --git a/elks/arch/i86/drivers/char/console-direct.c b/elks/arch/i86/drivers/char/console-direct.c index 32ab514ea..8b7459d46 100644 --- a/elks/arch/i86/drivers/char/console-direct.c +++ b/elks/arch/i86/drivers/char/console-direct.c @@ -11,6 +11,7 @@ */ #include +#include #include #include #include @@ -20,6 +21,7 @@ #include #include #include "console.h" +#include "crtc-6845.h" /* Assumes ASCII values. */ #define isalpha(c) (((unsigned char)(((c) | 0x20) - 'a')) < 26) @@ -41,16 +43,27 @@ #define MAXPARMS 28 +#ifdef CONFIG_CONSOLE_DUAL +#define MAX_DISPLAYS 2 +#else +#define MAX_DISPLAYS 1 +#endif + struct console; typedef struct console Console; struct console { int cx, cy; /* cursor position */ void (*fsm)(Console *, int); + unsigned char display; + unsigned char type; unsigned char attr; /* current attribute */ unsigned char XN; /* delayed newline on column 80 */ - unsigned int vseg; /* video segment for page */ - int basepage; /* start of video ram */ + unsigned int vseg; /* vram for this console page */ + int vseg_offset; /* vram offset of vseg for this console page */ + unsigned short Width; + unsigned short Height; + unsigned short crtc_base; /* 6845 CRTC base I/O address */ #ifdef CONFIG_EMUL_ANSI int savex, savey; /* saved cursor position */ unsigned char *parmptr; /* ptr to params */ @@ -58,17 +71,15 @@ struct console { #endif }; +static Console *glock; static struct wait_queue glock_wait; -static Console Con[MAX_CONSOLES], *Visible; -static Console *glock; /* Which console owns the graphics hardware */ -static unsigned short CCBase; /* 6845 CRTC base I/O address */ -static int Width, MaxCol, Height, MaxRow; -static int NumConsoles = MAX_CONSOLES; -static unsigned char isMDA, isCGA; +static Console *Visible[MAX_DISPLAYS]; +static Console Con[MAX_CONSOLES]; +static int NumConsoles; -int Current_VCminor = 0; -int kraw = 0; -unsigned VideoSeg = 0xB800; +int Current_VCminor; +unsigned VideoSeg; +int kraw; #ifdef CONFIG_EMUL_ANSI #define TERM_TYPE " emulating ANSI " @@ -80,38 +91,38 @@ static void std_char(register Console *, int); static void SetDisplayPage(register Console * C) { - outw((C->basepage & 0xff00) | 0x0c, CCBase); - outw((C->basepage << 8) | 0x0d, CCBase); + outw((C->vseg_offset & 0xff00) | 0x0c, C->crtc_base); + outw((C->vseg_offset << 8) | 0x0d, C->crtc_base); } static void PositionCursor(register Console * C) { - unsigned int Pos = C->cx + Width * C->cy + C->basepage; + unsigned int Pos = C->cx + C->Width * C->cy + C->vseg_offset; - outb(14, CCBase); - outb(Pos >> 8, CCBase + 1); - outb(15, CCBase); - outb(Pos, CCBase + 1); + outb(14, C->crtc_base); + outb(Pos >> 8, C->crtc_base + 1); + outb(15, C->crtc_base); + outb(Pos, C->crtc_base + 1); } -static void DisplayCursor(int onoff) +static void DisplayCursor(Console * C, int onoff) { /* unfortunately, the cursor start/end at BDA 0x0460 can't be relied on! */ unsigned int v; if (onoff) - v = isMDA? 0x0b0c: (isCGA? 0x0607: 0x0d0e); + v = C->type == OT_MDA ? 0x0b0c : (C->type == OT_CGA ? 0x0607: 0x0d0e); else v = 0x2000; - outb(10, CCBase); - outb(v >> 8, CCBase + 1); - outb(11, CCBase); - outb(v, CCBase + 1); + outb(10, C->crtc_base); + outb(v >> 8, C->crtc_base + 1); + outb(11, C->crtc_base); + outb(v, C->crtc_base + 1); } static void VideoWrite(register Console * C, int c) { - pokew((C->cx + C->cy * Width) << 1, (seg_t) C->vseg, + pokew((C->cx + C->cy * C->Width) << 1, (seg_t) C->vseg, (C->attr << 8) | (c & 255)); } @@ -120,24 +131,26 @@ static void ClearRange(register Console * C, int x, int y, int x2, int y2) register int vp; x2 = x2 - x + 1; - vp = (x + y * Width) << 1; + vp = (x + y * C->Width) << 1; do { for (x = 0; x < x2; x++) { pokew(vp, (seg_t) C->vseg, (C->attr << 8) | ' '); vp += 2; } - vp += (Width - x2) << 1; + vp += (C->Width - x2) << 1; } while (++y <= y2); } static void ScrollUp(register Console * C, int y) { register int vp; + unsigned short MaxRow = C->Height - 1; + unsigned short MaxCol = C->Width - 1; - vp = y * (Width << 1); + vp = y * (C->Width << 1); if ((unsigned int)y < MaxRow) fmemcpyw((void *)vp, C->vseg, - (void *)(vp + (Width << 1)), C->vseg, (MaxRow - y) * Width); + (void *)(vp + (C->Width << 1)), C->vseg, (MaxRow - y) * C->Width); ClearRange(C, 0, MaxRow, MaxCol, MaxRow); } @@ -145,14 +158,14 @@ static void ScrollUp(register Console * C, int y) static void ScrollDown(register Console * C, int y) { register int vp; - int yy = MaxRow; + int yy = C->Height - 1; - vp = yy * (Width << 1); + vp = yy * (C->Width << 1); while (--yy >= y) { - fmemcpyw((void *)vp, C->vseg, (void *)(vp - (Width << 1)), C->vseg, Width); - vp -= Width << 1; + fmemcpyw((void *)vp, C->vseg, (void *)(vp - (C->Width << 1)), C->vseg, C->Width); + vp -= C->Width << 1; } - ClearRange(C, 0, y, MaxCol, y); + ClearRange(C, 0, y, C->Width - 1, y); } #endif @@ -165,13 +178,16 @@ static void ScrollDown(register Console * C, int y) void Console_set_vc(int N) { - if ((N >= NumConsoles) || (Visible == &Con[N]) || glock) + Console *C = &Con[N]; + if ((N >= NumConsoles) || glock) return; - Visible = &Con[N]; - SetDisplayPage(Visible); - PositionCursor(Visible); + Visible[C->display] = C; + SetDisplayPage(C); + PositionCursor(C); + DisplayCursor(&Con[Current_VCminor], 0); Current_VCminor = N; + DisplayCursor(&Con[Current_VCminor], 1); } struct tty_ops dircon_ops = { @@ -183,41 +199,54 @@ struct tty_ops dircon_ops = { Console_conout }; +#ifndef CONFIG_CONSOLE_DUAL void INITPROC console_init(void) { Console *C; + unsigned char output_type; + unsigned short boot_crtc; int i; + int Width, Height; unsigned int PageSizeW; - MaxCol = (Width = peekb(0x4a, 0x40)) - 1; /* BIOS data segment */ + output_type = OT_EGA; + C = &Con[0]; + + Width = peekb(0x4a, 0x40); /* BIOS data segment */ /* Trust this. Cga does not support peeking at 0x40:0x84. */ - MaxRow = (Height = 25) - 1; - CCBase = peekw(0x63, 0x40); + Height = 25; + boot_crtc = peekw(0x63, 0x40); PageSizeW = ((unsigned int)peekw(0x4C, 0x40) >> 1); VideoSeg = 0xb800; + NumConsoles = MAX_CONSOLES - 1; if (peekb(0x49, 0x40) == 7) { VideoSeg = 0xB000; NumConsoles = 1; - isMDA = 1; + output_type = OT_MDA; } else { - isCGA = peekw(0xA8+2, 0x40) == 0; + if (peekw(0xA8+2, 0x40) == 0) + output_type = OT_CGA; } - C = Con; - Visible = C; + Visible[0] = C; for (i = 0; i < NumConsoles; i++) { C->cx = C->cy = 0; + C->display = 0; if (!i) { C->cx = peekb(0x50, 0x40); C->cy = peekb(0x51, 0x40); } C->fsm = std_char; - C->basepage = i * PageSizeW; - C->vseg = VideoSeg + (C->basepage >> 3); + C->vseg_offset = i * PageSizeW; + C->vseg = VideoSeg + (C->vseg_offset >> 3); C->attr = A_DEFAULT; + C->type = output_type; + C->Width = Width; + C->Height = Height; + C->crtc_base = boot_crtc; #ifdef CONFIG_EMUL_ANSI C->savex = C->savey = 0; @@ -234,3 +263,58 @@ void INITPROC console_init(void) printk("Direct console, %s kbd %ux%u"TERM_TYPE"(%d virtual consoles)\n", kbd_name, Width, Height, NumConsoles); } +#else +void INITPROC console_init(void) +{ + Console *C; + int i, j, dev; + unsigned short boot_crtc; + unsigned char boot_type; + unsigned char screens = 0; + unsigned char cur_display = 0; + boot_crtc = peekw(0x63, 0x40); + for (i = 0; i < N_DEVICETYPES; ++i) + if (crtc_params[i].crtc_base == boot_crtc) boot_type = i; + + C = &Con[0]; + for (i = 0; i < N_DEVICETYPES; ++i) { + dev = (i + boot_type) % N_DEVICETYPES; + if (!crtc_probe(crtc_params[dev].crtc_base)) continue; + screens++; + crtc_init(dev); + for (j = 0; j < crtc_params[dev].max_pages; ++j) { + C->cx = C->cy = 0; + C->display = cur_display; + if (!j) Visible[C->display] = C; + if (!j && !i) { + C->cx = peekb(0x50, 0x40); + C->cy = peekb(0x51, 0x40); + } + C->fsm = std_char; + C->vseg_offset = j * crtc_params[dev].page_words; + C->vseg = crtc_params[dev].vseg_base + (C->vseg_offset >> 3); + C->attr = A_DEFAULT; + C->type = dev; + C->Width = crtc_params[dev].w; + C->Height = crtc_params[dev].h; + C->crtc_base = crtc_params[dev].crtc_base; +#ifdef CONFIG_EMUL_ANSI + C->savex = C->savey = 0; +#endif + NumConsoles++; + if (i) DisplayCursor(C, 0); + C++; + } + cur_display++; + } + + /* For kernel/timer.c */ + VideoSeg = Visible[0]->vseg; + + kbd_init(); + printk("Direct console %s kbd"TERM_TYPE"(%d screens, %i consoles)\n", kbd_name, screens, NumConsoles); + for (i = 0; i < NumConsoles; ++i) { + debug("/dev/tty%i, %s, %ux%u\n", i + 1, type_string[Con[i].type], Con[i].Width, Con[i].Height); + } +} +#endif diff --git a/elks/arch/i86/drivers/char/console.c b/elks/arch/i86/drivers/char/console.c index def587669..cd20028c4 100644 --- a/elks/arch/i86/drivers/char/console.c +++ b/elks/arch/i86/drivers/char/console.c @@ -33,6 +33,8 @@ void Console_conin(unsigned char Key) static void Console_gotoxy(register Console * C, int x, int y) { register int xp = x; + unsigned short MaxRow = C->Height - 1; + unsigned short MaxCol = C->Width - 1; C->cx = (xp >= MaxCol) ? MaxCol : (xp < 0) ? 0 : xp; xp = y; @@ -80,6 +82,8 @@ static unsigned char ega_color[16] = { 0, 4, 2, 6, 1, 5, 3, 7, static void AnsiCmd(register Console * C, int c) { int n; + unsigned short MaxRow = C->Height - 1; + unsigned short MaxCol = C->Width - 1; /* ANSI param gathering and processing */ if (C->parmptr < &C->params[MAXPARMS - 1]) @@ -218,7 +222,7 @@ static void AnsiCmd(register Console * C, int c) case 'h': /* cursor on */ case 'l': /* cursor off */ if (C->params[0] == '?' && atoi((const char *)C->params+1) == 25) { - DisplayCursor(c == 'h'); + DisplayCursor(C, c == 'h'); } break; } @@ -250,6 +254,8 @@ static void esc_char(register Console * C, int c) /* Normal character processing */ static void std_char(register Console * C, int c) { + unsigned short MaxRow = C->Height - 1; + unsigned short MaxCol = C->Width - 1; switch(c) { case BEL: bell(); @@ -368,7 +374,7 @@ static int Console_write(register struct tty *tty) WriteChar(C, tty_outproc(tty)); cnt++; } - if (C == Visible) + if (C == Visible[C->display]) PositionCursor(C); return cnt; } diff --git a/elks/arch/i86/drivers/char/crtc-6845.c b/elks/arch/i86/drivers/char/crtc-6845.c new file mode 100644 index 000000000..abdd0cfe1 --- /dev/null +++ b/elks/arch/i86/drivers/char/crtc-6845.c @@ -0,0 +1,69 @@ +#include +#include +#include +#include +#include "crtc-6845.h" + +/* + * https://stanislavs.org/helppc/6845.html + * https://www.seasip.info/VintagePC/index.html + * + * I/O VidBase VidLen Notes + * MDA: 0x3B0-0x3BB 0xB0000 4k (0x1000) + * CGA: 0x3D0-0x3DC 0xB8000 16k (0x4000) note: Address not fully decoded, fb is also at 0xBC000 + * EGA: 0x3C0-0x3CF ??????? ????? + * VGA: ????? + */ + +#define CRTC_INDX 0x0 +#define CRTC_DATA 0x1 +#define CRTC_MODE 0x4 +#define CRTC_CSEL 0x5 +#define CRTC_STAT 0x6 + +/* Check to see if this CRTC is present */ +int INITPROC crtc_probe(unsigned short crtc_base) +{ + int i; + unsigned char test = 0x55; + /* We'll try writing a value to cursor address LSB reg (0x0F), then reading it back */ + outb(0x0F, crtc_base + CRTC_INDX); + unsigned char original = inb(crtc_base + CRTC_DATA); + if (original == test) test += 0x10; + outb(0x0F, crtc_base + CRTC_INDX); + outb(test, crtc_base + CRTC_DATA); + /* Now wait a bit */ + for (i = 0; i < 100; ++i) {} // TODO: Verify this doesn't get optimized out + outb(0x0F, crtc_base + CRTC_INDX); + unsigned char value = inb(crtc_base + CRTC_DATA); + if (value != test) return 0; + outb(0x0F, crtc_base + CRTC_INDX); + outb(original, crtc_base + CRTC_DATA); + return 1; +} + +int INITPROC crtc_init(unsigned int t) +{ + int i; + struct hw_params *p = &crtc_params[t]; + /* Set 80x25 mode, video off */ + outb(0x01, p->crtc_base + CRTC_MODE); + /* Program CRTC regs */ + for (i = 0; i < p->n_init_bytes; ++i) { + outb(i, p->crtc_base + CRTC_INDX); + outb(p->init_bytes[i], p->crtc_base + CRTC_DATA); + } + + /* Check & clear vram */ + for (i = 0; i < p->vseg_bytes; i += 2) + pokew(i, p->vseg_base, 0x5555); + for (i = 0; i < p->vseg_bytes; i += 2) + if (peekw(i, p->vseg_base) != 0x5555) return 1; + for (i = 0; i < p->vseg_bytes; i += 2) + pokew(i, p->vseg_base, 0x7 << 8 | ' '); + + /* Enable video */ + outb(0x09, p->crtc_base + CRTC_MODE); + return 0; +} + diff --git a/elks/arch/i86/drivers/char/crtc-6845.h b/elks/arch/i86/drivers/char/crtc-6845.h new file mode 100644 index 000000000..216c594f0 --- /dev/null +++ b/elks/arch/i86/drivers/char/crtc-6845.h @@ -0,0 +1,55 @@ +#define OT_MDA 0 +#define OT_CGA 1 +#define OT_EGA 2 +#define OT_VGA 3 + +#define N_DEVICETYPES 2 + +#ifdef DEBUG +static const char *type_string[] = { + "MDA", + "CGA", + "EGA", + "VGA", +}; +#endif + +struct hw_params { + unsigned short w; + unsigned short h; + unsigned short crtc_base; + unsigned vseg_base; + int vseg_bytes; + unsigned char max_pages; + unsigned short page_words; + unsigned char n_init_bytes; + unsigned char init_bytes[16]; +}; + +#ifdef CONFIG_CONSOLE_DUAL +static struct hw_params crtc_params[N_DEVICETYPES] = { + { 80, 25, 0x3B4, 0xB000, 0x1000, 1, 2000, 16, + { + 0x61, 0x50, 0x52, 0x0F, + 0x19, 0x06, 0x19, 0x19, + 0x02, 0x0D, 0x0B, 0x0C, + 0x00, 0x00, 0x00, 0x00, + } + }, /* MDA */ + { 80, 25, 0x3D4, 0xB800, 0x4000, 3, 2000, 16, + { + /* CO80 */ + 0x71, 0x50, 0x5A, 0x0A, + 0x1F, 0x06, 0x19, 0x1C, + 0x02, 0x07, 0x06, 0x07, + 0x00, 0x00, 0x00, 0x00, + } + }, /* CGA */ + // TODO + //{ 0 }, /* EGA */ + //{ 0 }, /* VGA */ +}; + +int INITPROC crtc_probe(unsigned short crtc_base); +int INITPROC crtc_init(unsigned int t); +#endif diff --git a/elks/arch/i86/drivers/char/kbd-poll.c b/elks/arch/i86/drivers/char/kbd-poll.c index be3e3ce17..6c8bcc1ae 100644 --- a/elks/arch/i86/drivers/char/kbd-poll.c +++ b/elks/arch/i86/drivers/char/kbd-poll.c @@ -28,11 +28,11 @@ static void kbd_timer(int data) else { dav = (dav >> 8) & 0xFF; #ifndef CONFIG_CONSOLE_HEADLESS - if (dav >= 0x3B && dav <= 0x3D) { /* temp console switch on F1-F3*/ + if (dav >= 0x3B && dav <= 0x3E) { /* temp console switch on F1-F4*/ Console_set_vc(dav - 0x3B); dav = 0; } - else if ((dav >= 0x68) && (dav < 0x6B)) { /* Change VC */ + else if ((dav >= 0x68) && (dav < 0x6C)) { /* Change VC */ Console_set_vc(dav - 0x68); dav = 0; } diff --git a/elks/arch/i86/drivers/char/kbd-scancode.c b/elks/arch/i86/drivers/char/kbd-scancode.c index 9a4d23096..4782be4e0 100644 --- a/elks/arch/i86/drivers/char/kbd-scancode.c +++ b/elks/arch/i86/drivers/char/kbd-scancode.c @@ -275,8 +275,8 @@ static void keyboard_irq(int irq, struct pt_regs *regs) /* F11 and F12 function keys need 89 byte table like keys-de.h */ /* function keys are not posix standard here */ - /* AltF1-F3 are console switch*/ - if ((ModeState & ALT) && code <= SCAN_F1+2) { + /* AltF1-F4 are console switch*/ + if ((ModeState & ALT) && code <= SCAN_F1+3) { Console_set_vc(code - SCAN_F1); return; } @@ -354,8 +354,8 @@ static void keyboard_irq(int irq, struct pt_regs *regs) /* Step 6: Modify keyboard character based on some special states*/ if ((ModeState & (CTRL|ALT)) == ALT) { - /* Alt-1 - Alt-3 are also console switch (for systems w/no fnkeys)*/ - if (key >= '1' && key <= '3') { + /* Alt-1 - Alt-4 are also console switch (for systems w/no fnkeys)*/ + if (key >= '1' && key <= '4') { Console_set_vc(key - '1'); return; } diff --git a/elks/fs/msdos/inode.c b/elks/fs/msdos/inode.c index 152184c77..9d621ea65 100644 --- a/elks/fs/msdos/inode.c +++ b/elks/fs/msdos/inode.c @@ -51,6 +51,7 @@ struct msdos_devdir_entry devnods[DEVDIR_SIZE] = { { "tty1", S_IFCHR | 0644, MKDEV(TTY_MAJOR, 0) }, { "tty2", S_IFCHR | 0644, MKDEV(TTY_MAJOR, 1) }, { "tty3", S_IFCHR | 0644, MKDEV(TTY_MAJOR, 2) }, + { "tty4", S_IFCHR | 0644, MKDEV(TTY_MAJOR, 3) }, { "ttyS0", S_IFCHR | 0644, MKDEV(TTY_MAJOR, 64) }, { "ttyS1", S_IFCHR | 0644, MKDEV(TTY_MAJOR, 65) }, { "console",S_IFCHR | 0600, MKDEV(TTY_MAJOR, 254) }, diff --git a/elks/include/linuxmt/devnum.h b/elks/include/linuxmt/devnum.h index 1fc116a80..927cc6a9f 100644 --- a/elks/include/linuxmt/devnum.h +++ b/elks/include/linuxmt/devnum.h @@ -27,6 +27,7 @@ #define DEV_TTY1 MKDEV(TTY_MAJOR, 0) #define DEV_TTY2 MKDEV(TTY_MAJOR, 1) #define DEV_TTY3 MKDEV(TTY_MAJOR, 2) +#define DEV_TTY4 MKDEV(TTY_MAJOR, 3) #define DEV_TTYS0 MKDEV(TTY_MAJOR, 64) #define DEV_TTYS1 MKDEV(TTY_MAJOR, 65) diff --git a/elks/include/linuxmt/msdos_fs_sb.h b/elks/include/linuxmt/msdos_fs_sb.h index dba509577..09876f40b 100644 --- a/elks/include/linuxmt/msdos_fs_sb.h +++ b/elks/include/linuxmt/msdos_fs_sb.h @@ -45,7 +45,7 @@ struct msdos_sb_info { /* space in struct super_block is 28 bytes */ #endif #ifdef CONFIG_FS_DEV -#define DEVDIR_SIZE 44 /* # entries in FAT device table */ +#define DEVDIR_SIZE 45 /* # entries in FAT device table */ #define DEVINO_BASE (MSDOS_DPB*2) /* (DEVDIR_SIZE+MSDOS_DBP-1) & ~(MSDOS_DBP-1) */ struct msdos_devdir_entry { diff --git a/elks/include/linuxmt/ntty.h b/elks/include/linuxmt/ntty.h index 3d7f40a02..c918d0a05 100644 --- a/elks/include/linuxmt/ntty.h +++ b/elks/include/linuxmt/ntty.h @@ -23,7 +23,7 @@ /* Predefined maximum number of tty character devices */ -#define MAX_CONSOLES 3 +#define MAX_CONSOLES 4 #define MAX_PTYS 4 #define TTY_MINOR_OFFSET 0 diff --git a/elks/init/main.c b/elks/init/main.c index 62aaa9131..4905a6857 100644 --- a/elks/init/main.c +++ b/elks/init/main.c @@ -314,6 +314,7 @@ static struct dev_name_struct { { "tty1", DEV_TTY1 }, { "tty2", DEV_TTY2 }, { "tty3", DEV_TTY3 }, + { "tty4", DEV_TTY4 }, { NULL, 0 } }; diff --git a/elkscmd/rootfs_template/bin/sys b/elkscmd/rootfs_template/bin/sys index 7f78d6af2..b13a0dbea 100755 --- a/elkscmd/rootfs_template/bin/sys +++ b/elkscmd/rootfs_template/bin/sys @@ -54,6 +54,7 @@ create_dev_dir() mknod $MNT/dev/rd1 b 1 1 mknod $MNT/dev/tty2 c 4 1 mknod $MNT/dev/tty3 c 4 2 + mknod $MNT/dev/tty4 c 4 3 mknod $MNT/dev/ttyS2 c 4 66 mknod $MNT/dev/ttyS3 c 4 67 mknod $MNT/dev/ttyp1 c 4 9 diff --git a/elkscmd/rootfs_template/etc/inittab b/elkscmd/rootfs_template/etc/inittab index 5ffffa1e4..355ea5c54 100644 --- a/elkscmd/rootfs_template/etc/inittab +++ b/elkscmd/rootfs_template/etc/inittab @@ -10,10 +10,11 @@ si::sysinit:/etc/rc.sys # 2 single user ttyS0 only # 3 multiuser tty1 and ttyS0 # 4 multiuser serial only (ttyS0,ttyS1) -# 5 multiuser console only (tty1,tty2,tty3) +# 5 multiuser console only (tty1,tty2,tty3,tty4) # 6 multiuser console and serial t1:1356:respawn:/bin/getty /dev/tty1 t2:56:respawn:/bin/getty /dev/tty2 t3:56:respawn:/bin/getty /dev/tty3 +t4:56:respawn:/bin/getty /dev/tty4 s0:2346:respawn:/bin/getty /dev/ttyS0 s1:46:respawn:/bin/getty /dev/ttyS1 9600 diff --git a/image/Make.devices b/image/Make.devices index 4146f3421..674f0f72a 100755 --- a/image/Make.devices +++ b/image/Make.devices @@ -86,6 +86,7 @@ devices: $(MKDEV) /dev/tty1 c 4 0 $(MKDEV) /dev/tty2 c 4 1 $(MKDEV) /dev/tty3 c 4 2 + $(MKDEV) /dev/tty4 c 4 3 # Pseudo-TTY slave devices. diff --git a/libc/misc/devname.c b/libc/misc/devname.c index 7c9c7988b..57507f636 100644 --- a/libc/misc/devname.c +++ b/libc/misc/devname.c @@ -38,6 +38,7 @@ static struct dev_name_struct { { "tty1", S_IFCHR, DEV_TTY1 }, { "tty2", S_IFCHR, DEV_TTY2 }, { "tty3", S_IFCHR, DEV_TTY3 }, + { "tty4", S_IFCHR, DEV_TTY4 }, }; static char *__fast_devname(dev_t dev, mode_t type)