1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Miniature VGA driver for bootstrap. 29 */ 30 31 #include <sys/archsystm.h> 32 #include <sys/vgareg.h> 33 #include <sys/framebuffer.h> 34 35 #include "boot_console_impl.h" 36 #if defined(_BOOT) 37 #include "../dboot/dboot_asm.h" 38 #include "../dboot/dboot_xboot.h" 39 #endif 40 41 #if defined(__xpv) && defined(_BOOT) 42 43 /* 44 * Device memory address 45 * 46 * In dboot under the hypervisor we don't have any memory mappings 47 * for the first meg of low memory so we can't access devices there. 48 * Intead we've mapped the device memory that we need to access into 49 * a local variable within dboot so we can access the device memory 50 * there. 51 */ 52 extern unsigned short *video_fb; 53 #define VGA_SCREEN ((unsigned short *)video_fb) 54 55 #else /* __xpv && _BOOT */ 56 57 /* Device memory address */ 58 #define VGA_SCREEN ((uint16_t *)(VGA_MEM_ADDR + VGA_COLOR_BASE)) 59 60 #endif /* __xpv && _BOOT */ 61 62 63 static void vga_init(void); 64 static void vga_cursor_display(void); 65 static void vga_clear(int); 66 static void vga_set_crtc(int index, unsigned char val); 67 static unsigned char vga_get_crtc(int index); 68 static void vga_set_atr(int index, unsigned char val); 69 static unsigned char vga_get_atr(int index); 70 71 void 72 boot_vga_init(int cons_color) 73 { 74 fb_info.terminal.x = VGA_TEXT_COLS; 75 fb_info.terminal.y = VGA_TEXT_ROWS; 76 77 #if defined(_BOOT) 78 /* 79 * Note that we have to enable the cursor before clearing the 80 * screen since the cursor position is dependant upon the cursor 81 * skew, which is initialized by vga_cursor_display() 82 */ 83 vga_init(); 84 fb_info.cursor.visible = B_FALSE; 85 vga_cursor_display(); 86 87 /* 88 * In general we should avoid resetting the display during the boot, 89 * we may have valueable messages there, this why the "native" loader 90 * boot does pass the console state down to kernel and we do try to 91 * pick the state. However, the loader is not the only way to boot. 92 * The non-native boot loaders do not implement the smooth console. 93 * If we have no information about cursor location, we will get value 94 * (0, 0) and that means we better clear the screen. 95 */ 96 if (fb_info.cursor.pos.x == 0 && fb_info.cursor.pos.y == 0) 97 vga_clear(cons_color); 98 vga_setpos(fb_info.cursor.pos.y, fb_info.cursor.pos.x); 99 #endif /* _BOOT */ 100 } 101 102 static void 103 vga_init(void) 104 { 105 unsigned char val; 106 107 /* set 16bit colors */ 108 val = vga_get_atr(VGA_ATR_MODE); 109 val &= ~VGA_ATR_MODE_BLINK; 110 val &= ~VGA_ATR_MODE_9WIDE; 111 vga_set_atr(VGA_ATR_MODE, val); 112 } 113 114 static void 115 vga_cursor_display(void) 116 { 117 unsigned char val, msl; 118 119 /* 120 * Figure out the maximum scan line value. We need this to set the 121 * cursor size. 122 */ 123 msl = vga_get_crtc(VGA_CRTC_MAX_S_LN) & 0x1f; 124 125 /* 126 * Enable the cursor and set it's size. Preserve the upper two 127 * bits of the control register. 128 * - Bits 0-4 are the starting scan line of the cursor. 129 * Scanning is done from top-to-bottom. The top-most scan 130 * line is 0 and the bottom most scan line is the maximum scan 131 * line value. 132 * - Bit 5 is the cursor disable bit. 133 */ 134 val = vga_get_crtc(VGA_CRTC_CSSL) & 0xc0; 135 vga_set_crtc(VGA_CRTC_CSSL, val); 136 137 /* 138 * Continue setting the cursors size. 139 * - Bits 0-4 are the ending scan line of the cursor. 140 * Scanning is done from top-to-bottom. The top-most scan 141 * line is 0 and the bottom most scan line is the maximum scan 142 * line value. 143 * - Bits 5-6 are the cursor skew. 144 */ 145 vga_set_crtc(VGA_CRTC_CESL, msl); 146 } 147 148 149 static void 150 vga_clear(int color) 151 { 152 unsigned short val; 153 int i; 154 155 val = (color << 8) | ' '; 156 157 for (i = 0; i < VGA_TEXT_ROWS * VGA_TEXT_COLS; i++) { 158 VGA_SCREEN[i] = val; 159 } 160 } 161 162 void 163 vga_drawc(int c, int color) 164 { 165 int row; 166 int col; 167 168 vga_getpos(&row, &col); 169 VGA_SCREEN[row*VGA_TEXT_COLS + col] = (color << 8) | c; 170 } 171 172 void 173 vga_scroll(int color) 174 { 175 unsigned short val; 176 int i; 177 178 val = (color << 8) | ' '; 179 180 for (i = 0; i < (VGA_TEXT_ROWS-1)*VGA_TEXT_COLS; i++) { 181 VGA_SCREEN[i] = VGA_SCREEN[i + VGA_TEXT_COLS]; 182 } 183 for (; i < VGA_TEXT_ROWS * VGA_TEXT_COLS; i++) { 184 VGA_SCREEN[i] = val; 185 } 186 } 187 188 void 189 vga_setpos(int row, int col) 190 { 191 int off; 192 193 off = row * VGA_TEXT_COLS + col; 194 vga_set_crtc(VGA_CRTC_CLAH, off >> 8); 195 vga_set_crtc(VGA_CRTC_CLAL, off & 0xff); 196 197 fb_info.cursor.pos.y = row; 198 fb_info.cursor.pos.x = col; 199 } 200 201 void 202 vga_getpos(int *row, int *col) 203 { 204 int off; 205 206 off = (vga_get_crtc(VGA_CRTC_CLAH) << 8) + vga_get_crtc(VGA_CRTC_CLAL); 207 *row = off / VGA_TEXT_COLS; 208 *col = off % VGA_TEXT_COLS; 209 } 210 211 static void 212 vga_set_atr(int index, unsigned char val) 213 { 214 (void) inb(VGA_REG_ADDR + CGA_STAT); 215 outb(VGA_REG_ADDR + VGA_ATR_AD, index); 216 outb(VGA_REG_ADDR + VGA_ATR_AD, val); 217 218 (void) inb(VGA_REG_ADDR + CGA_STAT); 219 outb(VGA_REG_ADDR + VGA_ATR_AD, VGA_ATR_ENB_PLT); 220 } 221 222 static unsigned char 223 vga_get_atr(int index) 224 { 225 unsigned char val; 226 227 (void) inb(VGA_REG_ADDR + CGA_STAT); 228 outb(VGA_REG_ADDR + VGA_ATR_AD, index); 229 val = inb(VGA_REG_ADDR + VGA_ATR_DATA); 230 231 (void) inb(VGA_REG_ADDR + CGA_STAT); 232 outb(VGA_REG_ADDR + VGA_ATR_AD, VGA_ATR_ENB_PLT); 233 234 return (val); 235 } 236 237 static void 238 vga_set_crtc(int index, unsigned char val) 239 { 240 outb(VGA_REG_ADDR + VGA_CRTC_ADR, index); 241 outb(VGA_REG_ADDR + VGA_CRTC_DATA, val); 242 } 243 244 static unsigned char 245 vga_get_crtc(int index) 246 { 247 outb(VGA_REG_ADDR + VGA_CRTC_ADR, index); 248 return (inb(VGA_REG_ADDR + VGA_CRTC_DATA)); 249 } 250