X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=kern%2Fsrc%2Fvid.c;fp=kern%2Fsrc%2Fvid.c;h=f4eb723b1f58be784538474dceb890d0e56512df;hb=4c01dc176867a3486bf2bc4287343a14b891650f;hp=0000000000000000000000000000000000000000;hpb=d67095d0b91873967843394eb090f13e847c1e2d;p=eightysix diff --git a/kern/src/vid.c b/kern/src/vid.c new file mode 100644 index 0000000..f4eb723 --- /dev/null +++ b/kern/src/vid.c @@ -0,0 +1,255 @@ +#include +#include "vid.h" +#include "asmutil.h" + +#define CRTC_ADDR_PORT (iobase | 4) +#define CRTC_DATA_PORT (iobase | 5) + +/* CRTC registers */ +#define CRTC_START_H 0x0c +#define CRTC_START_L 0x0d +#define CRTC_CURPOS_H 0x0e +#define CRTC_CURPOS_L 0x0f + +static void detect_video(void); +static int detect_vgainfo(void); +static int detect_egainfo(void); +static void detect_eqlist(void); +static void crtc_write(int reg, unsigned char val); + +//struct console con_vid = { con_clear, con_putc, 0 }; + +static uint16_t __far *vmem; +static int iobase; + +static uint16_t cur_attr; +static int cur_x, cur_y; +static int cur_scroll; +static int mono; + +void vid_init(void) +{ + detect_video(); + if(mono) { + vmem = MK_FP(0xb000, 0); + iobase = 0x3b0; + } else { + vmem = MK_FP(0xb800, 0); + iobase = 0x3d0; + } + + vid_reset(); +} + +static void detect_video(void) +{ + mono = 0; + vid_type = VID_UNK; + + if(detect_vgainfo() == 0) { + return; + } + if(detect_egainfo() == 0) { + return; + } + detect_eqlist(); +} + +static int detect_vgainfo(void) +{ + union regs regs; + + regs.w.ax = 0x1a00; + int86(0x10, ®s, ®s); + if(regs.h.al != 0x1a) { + return -1; + } + + switch(regs.h.bl) { + case 1: + vid_type = VID_MDA; + mono = 1; + break; + case 2: + vid_type = VID_CGA; + break; + case 4: + vid_type = VID_EGA; + break; + case 5: + vid_type = VID_EGA; + mono = 1; + break; + case 6: + vid_type = VID_PGA; + break; + case 7: + vid_type = VID_VGA; + mono = 1; + break; + case 8: + vid_type = VID_VGA; + break; + case 0xa: + case 0xc: + vid_type = VID_MCGA; + break; + case 0xb: + vid_type = VID_MCGA; + mono = 1; + break; + default: + return -1; + } + return 0; +} + +static int detect_egainfo(void) +{ + union regs regs; + + regs.w.ax = 0x1200; + regs.w.bx = 0xff10; + int86(0x10, ®s, ®s); + if(regs.h.bh == 0xff) { + return -1; + } + + vid_type = VID_EGA; + mono = regs.h.bh; + return 0; +} + +static void detect_eqlist(void) +{ + union regs regs; + + int86(0x11, ®s, ®s); + switch(regs.w.ax & 0x30) { + case 0: + vid_type = VID_EGA; + break; + + case 0x10: + case 0x20: + vid_type = VID_CGA; + break; + + case 0x30: + vid_type = VID_MDA; + mono = 1; + break; + } +} + +void vid_reset(void) +{ + vid_fgcolor(WHITE); + vid_bgcolor(BLACK); + vid_scroll(0); + vid_setcursor(0, 0); + fmemset(vmem, 0, 80 * 25 * 2); +} + +void vid_clearline(int row) +{ + int i; + uint16_t __far *ptr; + + row += cur_scroll; + + ptr = vmem + row * 80; + for(i=0; i<80; i++) { + ptr[i] = cur_attr; + } + + if(row - 32 >= 0) { + /* write a copy to wrap-around future scrolling */ + ptr -= 80 * 32; + for(i=0; i<80; i++) { + ptr[i] = cur_attr; + } + } +} + +void vid_clear(void) +{ + int i; + for(i=0; i<25; i++) { + vid_clearline(i); + } +} + +void vid_scroll(int line) +{ + int offs; + cur_scroll = line & 0x1f; + offs = cur_scroll * 80; + crtc_write(CRTC_START_H, offs >> 8); + crtc_write(CRTC_START_L, offs); +} + +void vid_setcursor(int x, int y) +{ + int loc = (y + cur_scroll) * 80 + x; + cur_x = x; + cur_y = y; + crtc_write(CRTC_CURPOS_H, loc >> 8); + crtc_write(CRTC_CURPOS_L, loc); +} + +void vid_fgcolor(int color) +{ + cur_attr = (cur_attr & 0xf0) | color; +} + +void vid_bgcolor(int color) +{ + cur_attr = (cur_attr & 0x0f) | (color << 4); +} + +void vid_glyph(int x, int y, int c, int attr) +{ + uint16_t __far *ptr; + uint16_t val = (c & 0xff) | attr; + + y += cur_scroll; + + ptr = vmem + y * 80 + x; + *ptr = val; + + if(y - 32 >= 0) { + /* write a copy to wrap-around future scrolling */ + ptr -= 80 * 32; + *ptr = val; + } +} + +void vid_text(int x, int y, const char *s, int attr) +{ + int len = 0; + uint16_t __far *ptr; + + y += cur_scroll; + + ptr = vmem + y * 80 + x; + while(*s) { + *ptr++ = (*s++ & 0xff) | attr; + len++; + } + + if(y - 32 >= 0) { + /* write a copy to wrap-around future scrolling */ + ptr -= 80 * 32 + len; + s -= len; + while(*s) { + *ptr++ = (*s++ & 0xff) | attr; + } + } +} + +static void crtc_write(int reg, unsigned char val) +{ + outp(CRTC_ADDR_PORT, reg); + outp(CRTC_DATA_PORT, val); +}