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 #pragma ident   "%Z%%M% %I%     %E% SMI"
  28 
  29 /*
  30  * Miniature VGA driver for bootstrap.
  31  */
  32 
  33 #include <sys/archsystm.h>
  34 #include <sys/vgareg.h>
  35 
  36 #include "boot_vga.h"
  37 
  38 #if defined(_BOOT)
  39 #include "../dboot/dboot_asm.h"
  40 #include "../dboot/dboot_xboot.h"
  41 #endif
  42 
  43 #define VGA_COLOR_CRTC_INDEX    0x3d4
  44 #define VGA_COLOR_CRTC_DATA     0x3d5
  45 
  46 #if defined(__xpv) && defined(_BOOT)
  47 
  48 /*
  49  * Device memory address
  50  *
  51  * In dboot under the hypervisor we don't have any memory mappings
  52  * for the first meg of low memory so we can't access devices there.
  53  * Intead we've mapped the device memory that we need to access into
  54  * a local variable within dboot so we can access the device memory
  55  * there.
  56  */
  57 extern unsigned short *video_fb;
  58 #define VGA_SCREEN              ((unsigned short *)video_fb)
  59 
  60 #else /* __xpv && _BOOT */
  61 
  62 /* Device memory address */
  63 #define VGA_SCREEN              ((unsigned short *)0xb8000)
  64 
  65 #endif /* __xpv && _BOOT */
  66 
  67 
  68 static void vga_set_crtc(int index, unsigned char val);
  69 static unsigned char vga_get_crtc(int index);
  70 
  71 void
  72 vga_cursor_display(void)
  73 {
  74         unsigned char val, msl;
  75 
  76         /*
  77          * Figure out the maximum scan line value.  We need this to set the
  78          * cursor size.
  79          */
  80         msl = vga_get_crtc(VGA_CRTC_MAX_S_LN) & 0x1f;
  81 
  82         /*
  83          * Enable the cursor and set it's size.  Preserve the upper two
  84          * bits of the control register.
  85          * - Bits 0-4 are the starting scan line of the cursor.
  86          *   Scanning is done from top-to-bottom.  The top-most scan
  87          *   line is 0 and the bottom most scan line is the maximum scan
  88          *   line value.
  89          * - Bit 5 is the cursor disable bit.
  90          */
  91         val = vga_get_crtc(VGA_CRTC_CSSL);
  92         vga_set_crtc(VGA_CRTC_CSSL, (val & 0xc) | ((msl - 2) & 0x1f));
  93 
  94         /*
  95          * Continue setting the cursors size.
  96          * - Bits 0-4 are the ending scan line of the cursor.
  97          *   Scanning is done from top-to-bottom.  The top-most scan
  98          *   line is 0 and the bottom most scan line is the maximum scan
  99          *   line value.
 100          * - Bits 5-6 are the cursor skew.
 101          */
 102         vga_set_crtc(VGA_CRTC_CESL, msl);
 103 }
 104 
 105 
 106 void
 107 vga_clear(int color)
 108 {
 109         unsigned short val;
 110         int i;
 111 
 112         val = (color << 8) | ' ';
 113 
 114         for (i = 0; i < VGA_TEXT_ROWS * VGA_TEXT_COLS; i++) {
 115                 VGA_SCREEN[i] = val;
 116         }
 117 }
 118 
 119 void
 120 vga_drawc(int c, int color)
 121 {
 122         int row;
 123         int col;
 124 
 125         vga_getpos(&row, &col);
 126         VGA_SCREEN[row*VGA_TEXT_COLS + col] = (color << 8) | c;
 127 }
 128 
 129 void
 130 vga_scroll(int color)
 131 {
 132         unsigned short val;
 133         int i;
 134 
 135         val = (color << 8) | ' ';
 136 
 137         for (i = 0; i < (VGA_TEXT_ROWS-1)*VGA_TEXT_COLS; i++) {
 138                 VGA_SCREEN[i] = VGA_SCREEN[i + VGA_TEXT_COLS];
 139         }
 140         for (; i < VGA_TEXT_ROWS * VGA_TEXT_COLS; i++) {
 141                 VGA_SCREEN[i] = val;
 142         }
 143 }
 144 
 145 void
 146 vga_setpos(int row, int col)
 147 {
 148         int off;
 149 
 150         off = row * VGA_TEXT_COLS + col;
 151         vga_set_crtc(VGA_CRTC_CLAH, off >> 8);
 152         vga_set_crtc(VGA_CRTC_CLAL, off & 0xff);
 153 }
 154 
 155 void
 156 vga_getpos(int *row, int *col)
 157 {
 158         int off;
 159 
 160         off = (vga_get_crtc(VGA_CRTC_CLAH) << 8) + vga_get_crtc(VGA_CRTC_CLAL);
 161         *row = off / VGA_TEXT_COLS;
 162         *col = off % VGA_TEXT_COLS;
 163 }
 164 
 165 static void
 166 vga_set_crtc(int index, unsigned char val)
 167 {
 168         outb(VGA_COLOR_CRTC_INDEX, index);
 169         outb(VGA_COLOR_CRTC_DATA, val);
 170 }
 171 
 172 static unsigned char
 173 vga_get_crtc(int index)
 174 {
 175         outb(VGA_COLOR_CRTC_INDEX, index);
 176         return (inb(VGA_COLOR_CRTC_DATA));
 177 }