| /* |
| * Copyright (C) 2007-2009 Luc Verhaegen <libv@skynet.be> |
| * |
| * This program is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License as published by the Free |
| * Software Foundation; either version 2 of the License, or (at your option) |
| * any later version. |
| * |
| * This program is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| * more details. |
| * |
| * You should have received a copy of the GNU General Public License along with |
| * this program; if not, write to the Free Software Foundation, Inc., 51 |
| * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
| */ |
| |
| #include <pc80/vga.h> |
| #include <pc80/vga_io.h> |
| |
| #include <string.h> |
| |
| /* |
| * pci io enable should've happened before |
| */ |
| void |
| vga_io_init(void) |
| { |
| vga_enable_mask(0x01, 0x01); |
| |
| /* cr io is at 0x3D4/0x3D5 */ |
| vga_misc_mask(0x01, 0x01); |
| |
| /* clear cr0-7 protection */ |
| vga_cr_mask(0x11, 0x00, 0x80); |
| } |
| |
| /* |
| * |
| */ |
| static void |
| vga_fb_init(void) |
| { |
| vga_sr_write(0x02, 0x03); |
| vga_sr_write(0x03, 0x00); |
| vga_sr_write(0x04, 0x02); /* access all 256kB */ |
| |
| vga_gr_write(0x00, 0x00); |
| vga_gr_write(0x01, 0x00); |
| vga_gr_write(0x02, 0x00); |
| vga_gr_write(0x03, 0x00); |
| vga_gr_write(0x04, 0x00); |
| vga_gr_write(0x05, 0x10); |
| vga_gr_write(0x06, 0x0E); /* map at 0xB8000 */ |
| vga_gr_write(0x07, 0x00); |
| vga_gr_write(0x08, 0xFF); |
| |
| /* o/e enable: ram enable */ |
| vga_misc_mask(0x22, 0x22); |
| } |
| |
| /* |
| * |
| */ |
| static void |
| vga_fb_clear(void) |
| { |
| memset((void *)VGA_FB, 0x00, 0x8000); |
| } |
| |
| #include "vga_palette.c" |
| |
| /* |
| * |
| */ |
| static void |
| vga_palette_init(void) |
| { |
| unsigned int i; |
| |
| /* set up attribute registers */ |
| for (i = 0; i < 0x10; i++) |
| vga_ar_write(i, i); |
| |
| vga_ar_write(0x10, 0x0c); |
| vga_ar_write(0x11, 0x00); |
| vga_ar_write(0x12, 0x0F); |
| vga_ar_write(0x13, 0x08); |
| vga_ar_write(0x14, 0x00); |
| |
| vga_palette_disable(); |
| |
| /* load actual palette */ |
| vga_dac_mask_write(0xFF); |
| |
| for (i = 0; i < 0x100; i++) { |
| vga_dac_write_address(i); |
| vga_dac_data_write(default_vga_palette[i].red); |
| vga_dac_data_write(default_vga_palette[i].green); |
| vga_dac_data_write(default_vga_palette[i].blue); |
| } |
| } |
| |
| /* |
| * |
| */ |
| static void |
| vga_mode_set(int hdisplay, int hblankstart, int hsyncstart, int hsyncend, |
| int hblankend, int htotal, int vdisplay, int vblankstart, |
| int vsyncstart, int vsyncend, int vblankend, int vtotal, |
| int stride) |
| { |
| /* htotal: 2080 */ |
| htotal /= 8; |
| htotal -= 5; |
| vga_cr_write(0x00, htotal); |
| |
| /* hdisplay: 2048 */ |
| hdisplay /= 8; |
| hdisplay -= 1; |
| vga_cr_write(0x01, hdisplay); |
| |
| /* hblankstart: 2048 */ |
| hblankstart /= 8; |
| hblankstart -= 1; |
| vga_cr_write(0x02, hblankstart); |
| |
| /* hblankend: hblankstart + 512 */ |
| hblankend /= 8; |
| hblankend -= 1; |
| vga_cr_mask(0x03, hblankend, 0x1F); |
| vga_cr_mask(0x05, hblankend << 2, 0x80); |
| |
| /* hsyncstart: 255 * 8: 2040 */ |
| vga_cr_write(0x04, hsyncstart / 8); |
| |
| /* hsyncend: hsyncstart + 255 */ |
| vga_cr_mask(0x05, hsyncend / 8, 0x1F); |
| |
| /* vtotal: 1025 */ |
| vtotal -= 2; |
| vga_cr_write(0x06, vtotal); |
| vga_cr_mask(0x07, vtotal >> 8, 0x01); |
| vga_cr_mask(0x07, vtotal >> 4, 0x20); |
| |
| /* vdisplay: 1024 */ |
| vdisplay -= 1; |
| vga_cr_write(0x12, vdisplay); |
| vga_cr_mask(0x07, vdisplay >> 7, 0x02); |
| vga_cr_mask(0x07, vdisplay >> 3, 0x40); |
| |
| /* vblankstart: 1024 */ |
| vblankstart -= 1; |
| vga_cr_write(0x15, vblankstart); |
| vga_cr_mask(0x07, vblankstart >> 5, 0x08); |
| vga_cr_mask(0x09, vblankstart >> 4, 0x20); |
| |
| /* vblankend: vblankstart + 256 */ |
| vblankend -= 1; |
| vga_cr_write(0x16, vblankend); |
| |
| /* vsyncstart: 1023 */ |
| vga_cr_write(0x10, vsyncstart); |
| vga_cr_mask(0x07, vsyncstart >> 6, 0x04); |
| vga_cr_mask(0x07, vsyncstart >> 2, 0x80); |
| |
| /* vsyncend: vsyncstart + 16 */ |
| vga_cr_mask(0x11, vsyncend, 0x0F); |
| |
| /* stride */ |
| vga_cr_write(0x13, stride / 8); |
| |
| /* line compare */ |
| vga_cr_write(0x18, 0xFF); |
| vga_cr_mask(0x07, 0x10, 0x10); |
| vga_cr_mask(0x09, 0x40, 0x40); |
| |
| vga_misc_mask(0x44, 0xCC); /* set up clock: 27mhz and h/vsync */ |
| |
| vga_cr_mask(0x09, 0x00, 0x80); /* disable doublescan */ |
| } |
| |
| #include "vga_font_8x16.c" |
| |
| static void |
| vga_font_8x16_load(void) |
| { |
| unsigned char *p; |
| int i, j; |
| unsigned char sr2, sr4, gr5, gr6; |
| |
| #define height 16 |
| #define count 256 |
| |
| sr2 = vga_sr_read(0x02); |
| sr4 = vga_sr_read(0x04); |
| gr5 = vga_gr_read(0x05); |
| gr6 = vga_gr_read(0x06); |
| |
| /* disable odd/even */ |
| vga_sr_mask(0x04, 0x04, 0x04); |
| vga_gr_mask(0x05, 0x00, 0x10); |
| vga_gr_mask(0x06, 0x00, 0x02); |
| |
| /* plane 2 */ |
| vga_sr_write(0x02, 0x04); |
| p = (unsigned char *) VGA_FB; |
| for (i = 0; i < count; i++) { |
| for (j = 0; j < 32; j++) { |
| if (j < height) |
| *p = vga_font_8x16[i][j]; |
| else |
| *p = 0x00; |
| p++; |
| } |
| } |
| |
| vga_gr_write(0x06, gr6); |
| vga_gr_write(0x05, gr5); |
| vga_sr_write(0x04, sr4); |
| vga_sr_write(0x02, sr2); |
| |
| /* set up font size */ |
| vga_cr_mask(0x09, 16 - 1, 0x1F); |
| } |
| |
| /* |
| * |
| */ |
| void |
| vga_cursor_enable(int enable) |
| { |
| if (enable) |
| vga_cr_mask(0x0A, 0x00, 0x20); |
| else |
| vga_cr_mask(0x0A, 0x20, 0x20); |
| } |
| |
| /* |
| * |
| */ |
| void |
| vga_cursor_reset(void) |
| { |
| vga_cr_write(0x0A, 0x2E); |
| vga_cr_write(0x0B, 0x0E); |
| vga_cr_write(0x0E, 0x00); |
| vga_cr_write(0x0F, 0x00); |
| } |
| |
| /* |
| * |
| */ |
| void |
| vga_cursor_set(unsigned int line, unsigned int character) |
| { |
| unsigned int offset = (80 * line + character) & 0xFFFF; |
| |
| vga_cr_write(0x0A, 0x0E); |
| vga_cr_write(0x0B, 0x0E); |
| vga_cr_write(0x0E, offset >> 8); |
| vga_cr_write(0x0F, offset & 0xFF); |
| } |
| |
| /* |
| * |
| */ |
| void |
| vga_frame_set(unsigned int line, unsigned int character) |
| { |
| unsigned int offset = (80 * line + character) & 0xFFFF; |
| |
| vga_cr_write(0x0C, offset >> 8); |
| vga_cr_write(0x0D, offset & 0xFF); |
| } |
| |
| /* |
| * simply fills a line with the given string. |
| */ |
| void |
| vga_line_write(unsigned int line, const char *string) |
| { |
| unsigned short *p = (unsigned short *) VGA_FB + (80 * line); |
| int i, len = strlen(string); |
| |
| for (i = 0; i < 80; i++) { |
| if (i < len) |
| p[i] = 0x0F00 | string[i]; |
| else |
| p[i] = 0x0F00; |
| } |
| } |
| |
| /* |
| * set up everything to get a basic 80x25 textmode. |
| */ |
| void |
| vga_textmode_init(void) |
| { |
| vga_sr_write(0x00, 0x01); /* clear reset */ |
| vga_sr_write(0x01, 0x00); |
| |
| /* set up cr */ |
| vga_cr_mask(0x03, 0x80, 0xE0); |
| vga_cr_mask(0x05, 0x00, 0x60); |
| |
| vga_cr_write(0x08, 0x00); |
| |
| vga_cr_write(0x14, 0x00); /* */ |
| |
| vga_cr_write(0x17, 0x23); |
| |
| vga_palette_init(); |
| |
| vga_mode_set(640, 648, 680, 776, 792, 800, |
| 400, 407, 412, 414, 442, 449, 320); |
| |
| vga_cursor_reset(); |
| vga_frame_set(0, 0); |
| |
| vga_fb_init(); |
| vga_fb_clear(); |
| vga_font_8x16_load(); |
| |
| vga_sr_mask(0x00, 0x02, 0x02); /* take us out of reset */ |
| vga_cr_mask(0x17, 0x80, 0x80); /* sync! */ |
| } |