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>
| 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#include <sys/boot_console.h> 35#include "boot_console_impl.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 */ 52extern unsigned short *video_fb;
| 36 37#include "boot_console_impl.h" 38#if defined(_BOOT) 39#include "../dboot/dboot_asm.h" 40#include "../dboot/dboot_xboot.h" 41#endif 42 43#if defined(__xpv) && defined(_BOOT) 44 45/* 46 * Device memory address 47 * 48 * In dboot under the hypervisor we don't have any memory mappings 49 * for the first meg of low memory so we can't access devices there. 50 * Intead we've mapped the device memory that we need to access into 51 * a local variable within dboot so we can access the device memory 52 * there. 53 */ 54extern unsigned short *video_fb;
|
53#define VGA_SCREEN ((unsigned short *)video_fb)
| 55#define VGA_SCREEN (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
| 56 57#else /* __xpv && _BOOT */ 58 59/* Device memory address */ 60#define VGA_SCREEN ((uint16_t *)(VGA_MEM_ADDR + VGA_COLOR_BASE)) 61 62#endif /* __xpv && _BOOT */ 63
|
| 64static int cons_color = CONS_COLOR;
|
62 63static void vga_init(void);
| 65 66static void vga_init(void);
|
64static void vga_cursor_display(void);
| 67static void vga_drawc(int); 68static void vga_setpos(int, int); 69static void vga_getpos(int *, int *); 70static void vga_scroll(int);
|
65static void vga_clear(int);
| 71static void vga_clear(int);
|
| 72static void vga_shiftline(int); 73static void vga_eraseline(void); 74static void vga_cursor_display(boolean_t); 75
|
66static void vga_set_crtc(int index, unsigned char val); 67static unsigned char vga_get_crtc(int index); 68static void vga_set_atr(int index, unsigned char val); 69static unsigned char vga_get_atr(int index); 70
| 76static void vga_set_crtc(int index, unsigned char val); 77static unsigned char vga_get_crtc(int index); 78static void vga_set_atr(int index, unsigned char val); 79static unsigned char vga_get_atr(int index); 80
|
| 81static int 82get_vga_color(void) 83{ 84 int color; 85 uint32_t fg, bg; 86 uint8_t solaris_color_to_pc_color[16] = { 87 15, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 88 }; 89 90 boot_get_color(&fg, &bg); 91 color = solaris_color_to_pc_color[bg] << 4; 92 color |= solaris_color_to_pc_color[fg]; 93 return (color); 94} 95
|
71void
| 96void
|
72boot_vga_init(int cons_color)
| 97boot_vga_init(bcons_dev_t *bcons_dev)
|
73{ 74 fb_info.terminal.x = VGA_TEXT_COLS; 75 fb_info.terminal.y = VGA_TEXT_ROWS;
| 98{ 99 fb_info.terminal.x = VGA_TEXT_COLS; 100 fb_info.terminal.y = VGA_TEXT_ROWS;
|
| 101 cons_color = get_vga_color();
|
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;
| 102 103#if defined(_BOOT) 104 /* 105 * Note that we have to enable the cursor before clearing the 106 * screen since the cursor position is dependant upon the cursor 107 * skew, which is initialized by vga_cursor_display() 108 */ 109 vga_init(); 110 fb_info.cursor.visible = B_FALSE;
|
85 vga_cursor_display();
| 111 vga_cursor_display(B_TRUE);
|
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 */
| 112 113 /* 114 * In general we should avoid resetting the display during the boot, 115 * we may have valueable messages there, this why the "native" loader 116 * boot does pass the console state down to kernel and we do try to 117 * pick the state. However, the loader is not the only way to boot. 118 * The non-native boot loaders do not implement the smooth console. 119 * If we have no information about cursor location, we will get value 120 * (0, 0) and that means we better clear the screen. 121 */ 122 if (fb_info.cursor.pos.x == 0 && fb_info.cursor.pos.y == 0) 123 vga_clear(cons_color); 124 vga_setpos(fb_info.cursor.pos.y, fb_info.cursor.pos.x); 125#endif /* _BOOT */
|
| 126 127 bcons_dev->bd_putchar = vga_drawc; 128 bcons_dev->bd_eraseline = vga_eraseline; 129 bcons_dev->bd_cursor = vga_cursor_display; 130 bcons_dev->bd_setpos = vga_setpos; 131 bcons_dev->bd_shift = vga_shiftline;
|
100} 101 102static void 103vga_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 114static void
| 132} 133 134static void 135vga_init(void) 136{ 137 unsigned char val; 138 139 /* set 16bit colors */ 140 val = vga_get_atr(VGA_ATR_MODE); 141 val &= ~VGA_ATR_MODE_BLINK; 142 val &= ~VGA_ATR_MODE_9WIDE; 143 vga_set_atr(VGA_ATR_MODE, val); 144} 145 146static void
|
115vga_cursor_display(void)
| 147vga_cursor_display(boolean_t visible)
|
116{ 117 unsigned char val, msl; 118
| 148{ 149 unsigned char val, msl; 150
|
| 151 if (fb_info.cursor.visible == visible) 152 return; 153
|
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;
| 154 /* 155 * Figure out the maximum scan line value. We need this to set the 156 * cursor size. 157 */ 158 msl = vga_get_crtc(VGA_CRTC_MAX_S_LN) & 0x1f; 159 160 /* 161 * Enable the cursor and set it's size. Preserve the upper two 162 * bits of the control register. 163 * - Bits 0-4 are the starting scan line of the cursor. 164 * Scanning is done from top-to-bottom. The top-most scan 165 * line is 0 and the bottom most scan line is the maximum scan 166 * line value. 167 * - Bit 5 is the cursor disable bit. 168 */ 169 val = vga_get_crtc(VGA_CRTC_CSSL) & 0xc0;
|
| 170 171 if (visible == B_FALSE) 172 val |= (1 << 5); 173
|
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
| 174 vga_set_crtc(VGA_CRTC_CSSL, val); 175 176 /* 177 * Continue setting the cursors size. 178 * - Bits 0-4 are the ending scan line of the cursor. 179 * Scanning is done from top-to-bottom. The top-most scan 180 * line is 0 and the bottom most scan line is the maximum scan 181 * line value. 182 * - Bits 5-6 are the cursor skew. 183 */ 184 vga_set_crtc(VGA_CRTC_CESL, msl); 185} 186
|
148
| |
149static void
| 187static void
|
150vga_clear(int color)
| 188vga_eraseline_impl(int x, int y, int color)
|
151{
| 189{
|
152 unsigned short val;
| 190 unsigned short val, *buf;
|
153 int i; 154
| 191 int i; 192
|
| 193 buf = VGA_SCREEN + x + y * VGA_TEXT_COLS;
|
155 val = (color << 8) | ' ';
| 194 val = (color << 8) | ' ';
|
| 195 for (i = x; i < VGA_TEXT_COLS; i++) 196 buf[i] = val; 197}
|
156
| 198
|
157 for (i = 0; i < VGA_TEXT_ROWS * VGA_TEXT_COLS; i++) { 158 VGA_SCREEN[i] = val;
| 199static void 200vga_eraseline(void) 201{ 202 int x, y; 203 204 x = fb_info.cursor.pos.x; 205 y = fb_info.cursor.pos.y; 206 vga_eraseline_impl(x, y, cons_color); 207} 208 209static void 210vga_shiftline(int chars) 211{ 212 unsigned short *src, *dst; 213 int x, y, len; 214 215 x = fb_info.cursor.pos.x; 216 y = fb_info.cursor.pos.y; 217 len = VGA_TEXT_COLS - x - chars; 218 if (len <= 0) 219 return; 220 221 src = VGA_SCREEN + x + y * VGA_TEXT_COLS; 222 dst = src + chars; 223 if (dst <= src) { 224 do { 225 *dst++ = *src++; 226 } while (--len != 0); 227 } else { 228 dst += len; 229 src += len; 230 do { 231 *--dst = *--src; 232 } while (--len != 0);
|
159 } 160} 161
| 233 } 234} 235
|
162void 163vga_drawc(int c, int color)
| 236static void 237vga_clear(int color)
|
164{
| 238{
|
| 239 int i; 240 241 for (i = 0; i < VGA_TEXT_ROWS; i++) 242 vga_eraseline_impl(0, i, color); 243} 244 245static void 246vga_drawc(int c) 247{
|
165 int row; 166 int col; 167 168 vga_getpos(&row, &col);
| 248 int row; 249 int col; 250 251 vga_getpos(&row, &col);
|
169 VGA_SCREEN[row*VGA_TEXT_COLS + col] = (color << 8) | c;
| 252 253 if (c == '\n') { 254 if (row < fb_info.terminal.y - 1) 255 vga_setpos(row + 1, col); 256 else 257 vga_scroll(cons_color); 258 return; 259 } 260 261 /* 262 * VGA_SCREEN is an array of 16-bit unsigned ints, we do let 263 * the compiler to take care of truncation here. 264 */ 265 VGA_SCREEN[row * VGA_TEXT_COLS + col] = (cons_color << 8) | c; 266 267 if (col < VGA_TEXT_COLS - 1) 268 vga_setpos(row, col + 1); 269 else if (row < VGA_TEXT_ROWS - 1) 270 vga_setpos(row + 1, 0); 271 else { 272 vga_setpos(row, 0); 273 vga_scroll(cons_color); 274 }
|
170} 171
| 275} 276
|
172void
| 277static void
|
173vga_scroll(int color) 174{
| 278vga_scroll(int color) 279{
|
175 unsigned short val;
| |
176 int i; 177
| 280 int i; 281
|
178 val = (color << 8) | ' '; 179 180 for (i = 0; i < (VGA_TEXT_ROWS-1)*VGA_TEXT_COLS; i++) {
| 282 for (i = 0; i < (VGA_TEXT_ROWS - 1) * VGA_TEXT_COLS; i++) {
|
181 VGA_SCREEN[i] = VGA_SCREEN[i + VGA_TEXT_COLS]; 182 }
| 283 VGA_SCREEN[i] = VGA_SCREEN[i + VGA_TEXT_COLS]; 284 }
|
183 for (; i < VGA_TEXT_ROWS * VGA_TEXT_COLS; i++) { 184 VGA_SCREEN[i] = val; 185 }
| 285 vga_eraseline_impl(0, VGA_TEXT_ROWS - 1, color);
|
186} 187
| 286} 287
|
188void
| 288static void
|
189vga_setpos(int row, int col) 190{ 191 int off; 192
| 289vga_setpos(int row, int col) 290{ 291 int off; 292
|
| 293 if (row < 0) 294 row = 0; 295 if (row >= fb_info.terminal.y) 296 row = fb_info.terminal.y - 1; 297 if (col < 0) 298 col = 0; 299 if (col >= fb_info.terminal.x) 300 col = fb_info.terminal.x - 1; 301
|
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
| 302 off = row * VGA_TEXT_COLS + col; 303 vga_set_crtc(VGA_CRTC_CLAH, off >> 8); 304 vga_set_crtc(VGA_CRTC_CLAL, off & 0xff); 305 306 fb_info.cursor.pos.y = row; 307 fb_info.cursor.pos.x = col; 308} 309
|
201void
| 310static void
|
202vga_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 211static void 212vga_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 222static unsigned char 223vga_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 237static void 238vga_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 244static unsigned char 245vga_get_crtc(int index) 246{ 247 outb(VGA_REG_ADDR + VGA_CRTC_ADR, index); 248 return (inb(VGA_REG_ADDR + VGA_CRTC_DATA)); 249}
| 311vga_getpos(int *row, int *col) 312{ 313 int off; 314 315 off = (vga_get_crtc(VGA_CRTC_CLAH) << 8) + vga_get_crtc(VGA_CRTC_CLAL); 316 *row = off / VGA_TEXT_COLS; 317 *col = off % VGA_TEXT_COLS; 318} 319 320static void 321vga_set_atr(int index, unsigned char val) 322{ 323 (void) inb(VGA_REG_ADDR + CGA_STAT); 324 outb(VGA_REG_ADDR + VGA_ATR_AD, index); 325 outb(VGA_REG_ADDR + VGA_ATR_AD, val); 326 327 (void) inb(VGA_REG_ADDR + CGA_STAT); 328 outb(VGA_REG_ADDR + VGA_ATR_AD, VGA_ATR_ENB_PLT); 329} 330 331static unsigned char 332vga_get_atr(int index) 333{ 334 unsigned char val; 335 336 (void) inb(VGA_REG_ADDR + CGA_STAT); 337 outb(VGA_REG_ADDR + VGA_ATR_AD, index); 338 val = inb(VGA_REG_ADDR + VGA_ATR_DATA); 339 340 (void) inb(VGA_REG_ADDR + CGA_STAT); 341 outb(VGA_REG_ADDR + VGA_ATR_AD, VGA_ATR_ENB_PLT); 342 343 return (val); 344} 345 346static void 347vga_set_crtc(int index, unsigned char val) 348{ 349 outb(VGA_REG_ADDR + VGA_CRTC_ADR, index); 350 outb(VGA_REG_ADDR + VGA_CRTC_DATA, val); 351} 352 353static unsigned char 354vga_get_crtc(int index) 355{ 356 outb(VGA_REG_ADDR + VGA_CRTC_ADR, index); 357 return (inb(VGA_REG_ADDR + VGA_CRTC_DATA)); 358}
|