wdenk | 858b1a6 | 2002-09-30 16:12:23 +0000 | [diff] [blame] | 1 | /* |
| 2 | * (C) Copyright 2001 |
| 3 | * Denis Peter, MPL AG Switzerland |
| 4 | * |
| 5 | * See file CREDITS for list of people who contributed to this |
| 6 | * project. |
| 7 | * |
| 8 | * This program is free software; you can redistribute it and/or |
| 9 | * modify it under the terms of the GNU General Public License as |
| 10 | * published by the Free Software Foundation; either version 2 of |
| 11 | * the License, or (at your option) any later version. |
| 12 | * |
| 13 | * This program is distributed in the hope that it will be useful, |
| 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 16 | * GNU General Public License for more details. |
| 17 | * |
| 18 | * You should have received a copy of the GNU General Public License |
| 19 | * along with this program; if not, write to the Free Software |
| 20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, |
| 21 | * MA 02111-1307 USA |
| 22 | * |
| 23 | * Note: Parts of these software are imported from |
| 24 | * - UBL, The Universal Talkware Boot Loader |
| 25 | * Copyright (C) 2000 Universal Talkware Inc. |
| 26 | * - Linux |
| 27 | * |
| 28 | * |
| 29 | */ |
| 30 | |
| 31 | #include <common.h> |
| 32 | |
| 33 | #ifdef CONFIG_VIDEO |
| 34 | |
| 35 | #include <command.h> |
| 36 | #include <asm/processor.h> |
| 37 | #include <devices.h> |
| 38 | #include "video.h" |
| 39 | #include <pci.h> |
| 40 | #include "vga_table.h" |
| 41 | |
| 42 | |
| 43 | |
| 44 | #ifdef CONFIG_VIDEO_CT69000 |
| 45 | #define VIDEO_VEND_ID 0x102C |
| 46 | #define VIDEO_DEV_ID 0x00C0 |
| 47 | #else |
| 48 | #error CONFIG_VIDEO_CT69000 must be defined |
| 49 | #endif |
| 50 | |
| 51 | /* |
| 52 | * Routine for resent board info to video |
| 53 | * resides in pip405.c |
| 54 | */ |
| 55 | extern void video_write_board_info(void); |
| 56 | |
| 57 | #undef VGA_DEBUG |
| 58 | |
| 59 | #ifdef VGA_DEBUG |
| 60 | #define PRINTF(fmt,args...) printf (fmt ,##args) |
| 61 | #else |
| 62 | #define PRINTF(fmt,args...) |
| 63 | #endif |
| 64 | |
| 65 | #define VGA_MAXROWS 25 |
| 66 | #define VGA_MAXCOLS 80 |
| 67 | |
| 68 | #define CRTC_CURSH 14 /* cursor high pos */ |
| 69 | #define CRTC_CURSL 15 /* cursor low pos */ |
| 70 | |
| 71 | /* description of the hardware layout */ |
| 72 | |
| 73 | #define ATTRI_INDEX CFG_ISA_IO_BASE_ADDRESS | 0x3c0 /* Index and Data write port of the attribute Registers */ |
| 74 | #define ATTRI_DATA CFG_ISA_IO_BASE_ADDRESS | 0x3c1 /* Data port of the attribute Registers */ |
| 75 | #define STATUS_REG0 CFG_ISA_IO_BASE_ADDRESS | 0x3c2 /* Status Register 0 (read only) */ |
| 76 | #define MSR_REG_W CFG_ISA_IO_BASE_ADDRESS | 0x3c2 /* Misc. Output Register (write only) */ |
| 77 | #define SEQ_INDEX CFG_ISA_IO_BASE_ADDRESS | 0x3c4 /* Index port of the Sequencer Controller */ |
| 78 | #define SEQ_DATA CFG_ISA_IO_BASE_ADDRESS | 0x3c5 /* Data port of the Sequencer Controller */ |
| 79 | #define COL_PAL_MASK CFG_ISA_IO_BASE_ADDRESS | 0x3c6 /* Color Palette Mask */ |
| 80 | #define COL_PAL_STAT CFG_ISA_IO_BASE_ADDRESS | 0x3c7 /* Color Palette Status (read only) */ |
| 81 | #define COL_PAL_IND_R CFG_ISA_IO_BASE_ADDRESS | 0x3c7 /* Color Palette Read Mode Index (write only) */ |
| 82 | #define COL_PAL_IND_W CFG_ISA_IO_BASE_ADDRESS | 0x3c8 /* Color Palette Write Mode Index */ |
| 83 | #define COL_PAL_DATA CFG_ISA_IO_BASE_ADDRESS | 0x3c9 /* Color Palette Data Port */ |
| 84 | #define FCR_REG_R CFG_ISA_IO_BASE_ADDRESS | 0x3ca /* Feature Control Register (read only) */ |
| 85 | #define MSR_REG_R CFG_ISA_IO_BASE_ADDRESS | 0x3cc /* Misc. Output Register (read only) */ |
| 86 | #define GR_INDEX CFG_ISA_IO_BASE_ADDRESS | 0x3ce /* Index port of the Graphic Controller Registers */ |
| 87 | #define GR_DATA CFG_ISA_IO_BASE_ADDRESS | 0x3cf /* Data port of the Graphic Controller Registers */ |
| 88 | #define FP_INDEX CFG_ISA_IO_BASE_ADDRESS | 0x3d0 /* Index port of the Flat panel Registers */ |
| 89 | #define FP_DATA CFG_ISA_IO_BASE_ADDRESS | 0x3d1 /* Data port of the Flat panel Registers */ |
| 90 | #define MR_INDEX CFG_ISA_IO_BASE_ADDRESS | 0x3d2 /* Index Port of the Multimedia Extension */ |
| 91 | #define MR_DATA CFG_ISA_IO_BASE_ADDRESS | 0x3d3 /* Data Port of the Multimedia Extension */ |
| 92 | #define CRT_INDEX CFG_ISA_IO_BASE_ADDRESS | 0x3d4 /* Index port of the CRT Controller */ |
| 93 | #define CRT_DATA CFG_ISA_IO_BASE_ADDRESS | 0x3d5 /* Data port of the CRT Controller */ |
| 94 | #define XREG_INDEX CFG_ISA_IO_BASE_ADDRESS | 0x3d6 /* Extended Register index */ |
| 95 | #define XREG_DATA CFG_ISA_IO_BASE_ADDRESS | 0x3d7 /* Extended Register data */ |
| 96 | #define STATUS_REG1 CFG_ISA_IO_BASE_ADDRESS | 0x3da /* Input Status Register 1 (read only) */ |
| 97 | #define FCR_REG_W CFG_ISA_IO_BASE_ADDRESS | 0x3da /* Feature Control Register (write only) */ |
| 98 | |
| 99 | |
| 100 | static unsigned char * video_fb; /* Frame buffer */ |
| 101 | |
| 102 | /* current hardware state */ |
| 103 | |
| 104 | static int video_row; |
| 105 | static int video_col; |
| 106 | static unsigned char video_attr; |
| 107 | |
| 108 | static unsigned int font_base_addr; |
| 109 | /********************************************************************** |
| 110 | * some forward declerations... |
| 111 | */ |
| 112 | int video_init(int busdevfunc); |
| 113 | void vga_set_attrib(void); |
| 114 | void vga_set_crt(void); |
| 115 | void vga_set_dac(void); |
| 116 | void vga_set_gr(void); |
| 117 | void vga_set_seq(void); |
| 118 | void vga_set_xreg(void); |
| 119 | void vga_write_sr(unsigned char reg,unsigned char val); |
| 120 | void vga_write_gr(unsigned char reg,unsigned char val); |
| 121 | void vga_write_cr(unsigned char reg,unsigned char val); |
| 122 | void vga_set_font(void); |
| 123 | |
| 124 | /*************************************************************************** |
| 125 | * Init VGA Device |
| 126 | */ |
| 127 | |
| 128 | int drv_video_init (void) |
| 129 | { |
| 130 | int error, devices = 1 ; |
| 131 | device_t vgadev ; |
| 132 | int busdevfunc; |
| 133 | |
| 134 | busdevfunc=pci_find_device(VIDEO_VEND_ID,VIDEO_DEV_ID,0); /* get PCI Device ID */ |
| 135 | if(busdevfunc==-1) { |
| 136 | #ifdef CONFIG_VIDEO_ONBOARD |
| 137 | printf("Error VGA Controller (%04X,%04X) not found\n",VIDEO_VEND_ID,VIDEO_DEV_ID); |
| 138 | #endif |
| 139 | return -1; |
| 140 | } |
| 141 | video_init(busdevfunc); |
| 142 | video_write_board_info(); |
| 143 | memset (&vgadev, 0, sizeof(vgadev)); |
| 144 | |
| 145 | strcpy(vgadev.name, "vga"); |
| 146 | vgadev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_SYSTEM; |
| 147 | vgadev.putc = video_putc; |
| 148 | vgadev.puts = video_puts; |
| 149 | vgadev.getc = NULL; |
| 150 | vgadev.tstc = NULL; |
| 151 | error = device_register (&vgadev); |
| 152 | |
| 153 | return (error == 0) ? devices : error ; |
| 154 | } |
| 155 | |
| 156 | |
| 157 | /*********************************************************** |
| 158 | * VGA Initializing |
| 159 | */ |
| 160 | |
| 161 | int video_init(int busdevfunc) |
| 162 | { |
| 163 | pci_read_config_dword(busdevfunc, PCI_BASE_ADDRESS_0, &font_base_addr); |
| 164 | |
| 165 | video_fb = (char*)font_base_addr; /* we look into the big linaer memory area */ |
| 166 | |
| 167 | /* set the extended Registers */ |
| 168 | vga_set_xreg(); |
| 169 | |
| 170 | /* set IO Addresses to 0x3Dx (color mode ) */ |
| 171 | out8(MSR_REG_W,0x01); |
| 172 | |
| 173 | /* Feature Control Register: |
| 174 | Bits 7-4 Reserved = 0 |
| 175 | Bit 3 Vertical Sync select = 1 = Enabled |
| 176 | Bits 2-0 Reserved = 010 = as read from memory. |
| 177 | */ |
| 178 | out8(FCR_REG_W,0x02); |
| 179 | |
| 180 | |
| 181 | /* Miscelaneous output Register: |
| 182 | Bits 7-6 (num lines) = 01 = VGA 400 lines, |
| 183 | Bit 5 (Odd/Even Page) = 1 = Sleect high page of memory, |
| 184 | Bit 4 reserved = 0, |
| 185 | Bits 3-2 (Clocl Select) = 01 = 28.322Mhz |
| 186 | Bit 1 = Display Ram Enable = 1 = Enable processor access. |
| 187 | Bit 0 = Io Address Select = 1 = Color Graphics Enulation. |
| 188 | */ |
| 189 | out8(MSR_REG_W,0x67); |
| 190 | /* set the palette */ |
| 191 | vga_set_dac(); |
| 192 | /* set the attributes (before we bring up the engine |
| 193 | then we dont have to wait for refresh). |
| 194 | */ |
| 195 | vga_set_attrib(); |
| 196 | |
| 197 | /* set the crontroller register. */ |
| 198 | vga_set_crt(); |
| 199 | |
| 200 | vga_write_sr(0x00,0x01); /* synchronous reset */ |
| 201 | vga_write_sr(0x01,0x00); /* clocking mode */ |
| 202 | vga_write_sr(0x02,0x03); /* write to map 0, 1 */ |
| 203 | vga_write_sr(0x03,0x00); /* select character map 0 */ |
| 204 | vga_write_sr(0x04,0x03); /* even-odd addressing */ |
| 205 | vga_write_sr(0x00,0x03); /* clear synchronous reset */ |
| 206 | |
| 207 | vga_set_seq(); /* Set the extended sr's. */ |
| 208 | |
| 209 | vga_set_gr(); /* Set the graphic registers. */ |
| 210 | |
| 211 | /* load the font */ |
| 212 | vga_set_font(); |
| 213 | |
| 214 | /* initialize the rol/col counts and the text attribute. */ |
| 215 | video_row=0; |
| 216 | video_col=0; |
| 217 | video_attr = VGA_ATTR_CLR_WHT; |
| 218 | |
| 219 | /* Clear the video ram */ |
| 220 | video_clear(); |
| 221 | |
| 222 | return 1; |
| 223 | } |
| 224 | |
| 225 | void vga_set_font(void) |
| 226 | { |
| 227 | int i,j; |
| 228 | char *fontmap; |
| 229 | fontmap = (char *)font_base_addr; |
| 230 | |
| 231 | vga_write_sr(0x00,0x01); /* synchronous reset */ |
| 232 | vga_write_sr(0x04,0x06); /* sequential addressing */ |
| 233 | vga_write_sr(0x02,0x04); /* write to map 2 */ |
| 234 | vga_write_sr(0x00,0x03); /* clear synchronous reset */ |
| 235 | |
| 236 | vga_write_gr(0x04,0x02); /* select map 2 */ |
| 237 | vga_write_gr(0x05,0x00); /* disable odd-even addressing */ |
| 238 | vga_write_gr(0x06,0x00); /* map start at 0xa0000 */ |
| 239 | |
| 240 | for(i=0;i<0x100;i++) { |
| 241 | for(j=0;j<0x10;j++) { |
| 242 | *((char *)fontmap+i*32+j)=(char)fontdata_8x16[i*16+j]; |
| 243 | } |
| 244 | } |
| 245 | vga_write_sr(0x00,0x01); /* synchronous reset */ |
| 246 | vga_write_sr(0x02,0x03); /* write to map 0 and 1 */ |
| 247 | vga_write_sr(0x04,0x03); /* odd-even addressing */ |
| 248 | vga_write_sr(0x03,0x00); /* Character map 0 & 1 */ |
| 249 | vga_write_sr(0x00,0x03); /* clear synchronous reset */ |
| 250 | |
| 251 | vga_write_gr(0x04,0x00); /* select map 0 for CPU */ |
| 252 | vga_write_gr(0x05,0x10); /* enable odd-even addressing */ |
| 253 | vga_write_gr(0x06,0x0E); /* map start at 0xb8000 */ |
| 254 | } |
| 255 | |
| 256 | |
| 257 | /* since we are BIG endian, swap attributes and char */ |
| 258 | unsigned short vga_swap_short(unsigned short val) |
| 259 | { |
| 260 | unsigned short swapped; |
| 261 | swapped = ((val & 0xff)<<8) | ((val & 0xff00)>>8); |
| 262 | return swapped; |
| 263 | } |
| 264 | |
| 265 | /**************************************************** |
| 266 | * Routines usable Outside world |
| 267 | */ |
| 268 | |
| 269 | /* scolls the text up row rows */ |
| 270 | void video_scroll(int row) |
| 271 | { |
| 272 | unsigned short clear = ((unsigned short)video_attr << 8) | (' '); |
| 273 | unsigned short* addr16 = &((unsigned short *)video_fb)[(VGA_MAXROWS-row)*VGA_MAXCOLS]; |
| 274 | int i; |
| 275 | |
| 276 | clear=vga_swap_short(clear); |
| 277 | memcpy(video_fb, video_fb+row*(VGA_MAXCOLS*2), (VGA_MAXROWS-row)*(VGA_MAXCOLS*2)); |
| 278 | for (i = 0 ; i < row * VGA_MAXCOLS ; i++) |
| 279 | addr16[i] = clear; |
| 280 | video_row-=row; |
| 281 | video_col=0; |
| 282 | } |
| 283 | |
| 284 | |
| 285 | unsigned long video_cursor(int col, int row) |
| 286 | { |
| 287 | unsigned short off = row * VGA_MAXCOLS + col ; |
| 288 | unsigned long saved = (video_col << 16) | (video_row & 0xFFFF); |
| 289 | video_col = col; |
| 290 | video_row = row; |
| 291 | |
| 292 | vga_write_cr(CRTC_CURSH,(unsigned char)((off & 0xff00)>>8)); /* Cursor pos. high */ |
| 293 | vga_write_cr(CRTC_CURSL,(unsigned char)(off & 0xff)); /* Cursor pos. low */ |
| 294 | return saved; |
| 295 | } |
| 296 | |
| 297 | void video_set_lxy(unsigned long lxy) |
| 298 | { |
| 299 | int col = (lxy >> 16) & 0xFFFF; |
| 300 | int row = lxy & 0xFFFF; |
| 301 | video_cursor(col,row); |
| 302 | } |
| 303 | |
| 304 | unsigned long video_get_lxy(void) |
| 305 | { |
| 306 | return (video_col << 16) | (video_row & 0xFFFF); |
| 307 | } |
| 308 | |
| 309 | void video_clear(void) |
| 310 | { |
| 311 | int i; |
| 312 | unsigned short clear = ((unsigned short)video_attr << 8) | (' '); |
| 313 | unsigned short * addr16 = (unsigned short * )video_fb; |
| 314 | clear=vga_swap_short(clear); |
| 315 | video_row = video_col = 0; |
| 316 | for (i = 0 ; i < 2000 ; i++) { |
| 317 | addr16[i] = clear; |
| 318 | } |
| 319 | } |
| 320 | |
| 321 | void video_copy(unsigned short *buffer) |
| 322 | { |
| 323 | int i; |
| 324 | unsigned short * addr16 = (unsigned short * )video_fb; |
| 325 | for (i = 0 ; i < 2000 ; i++) { |
| 326 | buffer[i] = addr16[i]; |
| 327 | } |
| 328 | } |
| 329 | |
| 330 | void video_write(unsigned short *buffer) |
| 331 | { |
| 332 | int i; |
| 333 | unsigned short * addr16 = (unsigned short *)video_fb; |
| 334 | for (i = 0 ; i < 2000 ; i++) { |
| 335 | addr16[i] = buffer[i]; |
| 336 | } |
| 337 | } |
| 338 | |
| 339 | void video_putc(char ch) |
| 340 | { |
| 341 | char* addr; |
| 342 | #if 0 |
| 343 | char buf[48]; |
| 344 | char buf1[16]; |
| 345 | static int i=0; |
| 346 | |
| 347 | sprintf(buf1,"%02X ",ch); |
| 348 | serial_puts(buf1); |
| 349 | buf[i++]=((ch>=0x20)&&(ch<=0x7f)) ? ch : '.'; |
| 350 | if(i>=16) { |
| 351 | buf[i++]='\n'; |
| 352 | buf[i]='\0'; |
| 353 | i=0; |
| 354 | serial_puts(" "); |
| 355 | serial_puts(buf); |
| 356 | } |
| 357 | #endif |
| 358 | switch (ch) { |
| 359 | case '\n': |
| 360 | video_col=0; |
| 361 | video_row++; |
| 362 | break; |
| 363 | case '\r': |
| 364 | video_col=0; |
| 365 | break; |
| 366 | case '\t': |
| 367 | video_col += 8 - video_col % 8; |
| 368 | break; |
| 369 | case '\a': |
| 370 | /* beep(); */ |
| 371 | break; |
| 372 | case '\b': |
| 373 | if(video_col) |
| 374 | video_col--; |
| 375 | else |
| 376 | return; |
| 377 | break; |
| 378 | default: |
| 379 | addr = video_fb + 2 * video_row * 80 + 2 * video_col; |
| 380 | |
| 381 | *((char *)addr+1) = (char) video_attr; |
| 382 | *((char *)addr) = (char) ch; |
| 383 | video_col++; |
| 384 | if (video_col > (VGA_MAXCOLS-1)) { |
| 385 | video_row++; |
| 386 | video_col=0; |
| 387 | } |
| 388 | } |
| 389 | |
| 390 | /* If we're on the bottom of the secreen, wrap one row */ |
| 391 | if (video_row > (VGA_MAXROWS-1)) |
| 392 | video_scroll(1); |
| 393 | video_cursor(video_col, video_row); |
| 394 | } |
| 395 | |
| 396 | |
| 397 | unsigned char video_set_attr(unsigned char attr) |
| 398 | { |
| 399 | unsigned char saved_attr = video_attr; |
| 400 | video_attr = attr; |
| 401 | return saved_attr; |
| 402 | } |
| 403 | |
| 404 | unsigned char video_set_attr_xy(unsigned char attr, int x, int y) |
| 405 | { |
| 406 | unsigned char *addr = video_fb + (x * 80 + y) * 2 + 1; |
| 407 | unsigned char saved_attr = *addr; |
| 408 | *addr = attr; |
| 409 | return saved_attr; |
| 410 | } |
| 411 | |
| 412 | /* put char at xy */ |
| 413 | void video_putc_xy(char ch, int x, int y) |
| 414 | { |
| 415 | video_col = x; |
| 416 | video_row = y; |
| 417 | video_putc(ch); |
| 418 | } |
| 419 | |
| 420 | /* put char at xy relative to the position */ |
| 421 | void video_putc_rxy(char ch, int x, int y) |
| 422 | { |
| 423 | video_col += x; |
| 424 | video_row += y; |
| 425 | video_putc(ch); |
| 426 | } |
| 427 | |
| 428 | /* put char with attribute at xy */ |
| 429 | void video_putc_axy(char ch, char attr, int x, int y) |
| 430 | { |
| 431 | unsigned char saved_attr = video_set_attr(attr); |
| 432 | video_col = x; |
| 433 | video_row = y; |
| 434 | video_putc(ch); |
| 435 | video_set_attr(saved_attr); |
| 436 | } |
| 437 | |
| 438 | void video_puts(const char *s) |
| 439 | { |
| 440 | while(*s) { |
| 441 | video_putc(*s); |
| 442 | s++; |
| 443 | } |
| 444 | } |
| 445 | |
| 446 | void video_puts_a(const char *s, char attr) |
| 447 | { |
| 448 | unsigned char saved_attr = video_set_attr(attr); |
| 449 | video_puts(s); |
| 450 | video_set_attr(saved_attr); |
| 451 | } |
| 452 | |
| 453 | void video_puts_xy(const char *s, int x, int y) |
| 454 | { |
| 455 | video_cursor(x,y); |
| 456 | video_puts(s); |
| 457 | } |
| 458 | |
| 459 | void video_puts_axy(const char *s, char attr, int x, int y) |
| 460 | { |
| 461 | unsigned char saved_attr = video_set_attr(attr); |
| 462 | video_puts_xy(s, x, y); |
| 463 | video_set_attr(saved_attr); |
| 464 | } |
| 465 | |
| 466 | void video_wipe_ca_area(unsigned char ch, char attr, int x, int y, int w, int h) |
| 467 | { |
| 468 | int r, c; |
| 469 | /* better to do this as word writes */ |
| 470 | unsigned short * addr16 = (unsigned short *)video_fb + (y * 80 + x); |
| 471 | unsigned short charattr = (unsigned short)ch << 8 | attr; |
| 472 | charattr=vga_swap_short(charattr); |
| 473 | for (r = 0 ; r < h ; r++, addr16 += 80) { |
| 474 | for (c = 0 ; c < w ; c++) { |
| 475 | addr16[c] = charattr; |
| 476 | } |
| 477 | } |
| 478 | } |
| 479 | |
| 480 | void video_wipe_a_area(unsigned char attr, int x, int y, int w, int h) |
| 481 | { |
| 482 | int r, c; |
| 483 | /* better to do this as word writes */ |
| 484 | unsigned short * addr16 = (unsigned short *)video_fb + (y * 80 + x); |
| 485 | for (r = 0 ; r < h ; r++, addr16 += 80) { |
| 486 | for (c = 0 ; c < w ; c++) { |
| 487 | ((char*)addr16)[c*2+1] = attr; |
| 488 | } |
| 489 | } |
| 490 | } |
| 491 | |
| 492 | void video_wipe_c_area(unsigned char ch, int x, int y, int w, int h) |
| 493 | { |
| 494 | int r, c; |
| 495 | /* better to do this as word writes */ |
| 496 | unsigned short * addr16 = (unsigned short *)video_fb + (y * 80 + x); |
| 497 | for (r = 0 ; r < h ; r++, addr16 += 80) { |
| 498 | for (c = 0 ; c < w ; c++) { |
| 499 | ((char*)addr16)[c*2] = ch; |
| 500 | } |
| 501 | } |
| 502 | } |
| 503 | |
| 504 | |
| 505 | /* |
| 506 | tl t tr |
| 507 | l l |
| 508 | bl b br |
| 509 | */ |
| 510 | typedef struct { |
| 511 | unsigned char tl; /* top left corner */ |
| 512 | unsigned char t; /* top edge */ |
| 513 | unsigned char tr; /* top right corner */ |
| 514 | unsigned char l; /* left edge */ |
| 515 | unsigned char r; /* right edge */ |
| 516 | unsigned char bl; /* bottom left corner */ |
| 517 | unsigned char b; /* bottom edge */ |
| 518 | unsigned char br; /* bottom right corner */ |
| 519 | } box_chars_t; |
| 520 | |
| 521 | box_chars_t sbox_chars = { |
| 522 | 0xDA, 0xC4, 0xBF, |
| 523 | 0xB3, 0xB3, |
| 524 | 0xC0, 0xC4, 0xD9 |
| 525 | }; |
| 526 | |
| 527 | box_chars_t dbox_chars = { |
| 528 | 0xC9, 0xCD, 0xBB, |
| 529 | 0xBA, 0xBA, |
| 530 | 0xC8, 0xCD, 0xBC |
| 531 | }; |
| 532 | |
| 533 | static char cmap[] = "0123456789ABCDEF"; |
| 534 | void video_putchex(char c) |
| 535 | { |
| 536 | video_putc(cmap[(c >> 4 ) & 0xF]); |
| 537 | video_putc(cmap[c & 0xF]); |
| 538 | } |
| 539 | |
| 540 | void video_putchexl(char c) |
| 541 | { |
| 542 | video_putc(cmap[c & 0xF]); |
| 543 | } |
| 544 | |
| 545 | void video_putchexh(char c) |
| 546 | { |
| 547 | video_putc(cmap[(c >> 4) & 0xF]); |
| 548 | } |
| 549 | |
| 550 | #define VGA_CELL_CA(a,c) (((unsigned short)c<<8)|a) /* for BIG endians */ |
| 551 | |
| 552 | void video_gbox_area(box_chars_t *box_chars_p, int x, int y, int w, int h) |
| 553 | { |
| 554 | int r, c; |
| 555 | /* better to do this as word writes */ |
| 556 | unsigned short* addr16 = (unsigned short *)video_fb + (y * VGA_MAXCOLS + x); |
| 557 | for (r = 0 ; r < h ; r++, addr16 += VGA_MAXCOLS) { |
| 558 | if (r == 0) { |
| 559 | addr16[0] = VGA_CELL_CA(video_attr, box_chars_p->tl); |
| 560 | addr16[w-1] = VGA_CELL_CA(video_attr, box_chars_p->tr); |
| 561 | for (c = 1 ; c < w - 1 ; c++) |
| 562 | addr16[c] = VGA_CELL_CA(video_attr, box_chars_p->t); |
| 563 | } else if (r == h - 1) { |
| 564 | addr16[0] = VGA_CELL_CA(video_attr, box_chars_p->bl); |
| 565 | addr16[w-1] = VGA_CELL_CA(video_attr, box_chars_p->br); |
| 566 | for (c = 1 ; c < w - 1 ; c++) |
| 567 | addr16[c] = VGA_CELL_CA(video_attr, box_chars_p->b); |
| 568 | } else { |
| 569 | addr16[0] = VGA_CELL_CA(video_attr, box_chars_p->l); |
| 570 | addr16[w-1] = VGA_CELL_CA(video_attr, box_chars_p->r); |
| 571 | } |
| 572 | } |
| 573 | } |
| 574 | |
| 575 | /* Writes a box on the screen */ |
| 576 | void video_box_area(int x, int y, int w, int h) { |
| 577 | video_gbox_area(&sbox_chars, x, y, w, h); |
| 578 | } |
| 579 | /*writes a box with double lines on the screen */ |
| 580 | void video_dbox_area(int x, int y, int w, int h) { |
| 581 | video_gbox_area(&dbox_chars, x, y, w, h); |
| 582 | } |
| 583 | |
| 584 | /* routines to set the VGA registers */ |
| 585 | |
| 586 | /* set attributes */ |
| 587 | void vga_set_attrib(void) |
| 588 | { |
| 589 | int i; |
| 590 | unsigned char status; |
| 591 | |
| 592 | status=in8(STATUS_REG1); |
| 593 | i=0; |
| 594 | |
| 595 | while(attr[i].reg!=0xFF) { |
| 596 | out8(ATTRI_INDEX,attr[i].reg); |
| 597 | out8(ATTRI_INDEX,attr[i].val); /* Attribute uses index for index and data */ |
| 598 | i++; |
| 599 | } |
| 600 | out8(ATTRI_INDEX,0x20); /* unblank the screen */ |
| 601 | } |
| 602 | |
| 603 | /* set CRT Controller Registers */ |
| 604 | void vga_set_crt(void) |
| 605 | { |
| 606 | int i; |
| 607 | i=0; |
| 608 | while(crtc[i].reg!=0xFF) { |
| 609 | out8(CRT_INDEX,crtc[i].reg); |
| 610 | out8(CRT_DATA,crtc[i].val); |
| 611 | i++; |
| 612 | } |
| 613 | } |
| 614 | /* Set Palette Registers (DAC) */ |
| 615 | void vga_set_dac(void) |
| 616 | { |
| 617 | int i; |
| 618 | for(i=0;i<256;i++) { |
| 619 | out8(COL_PAL_IND_W,(unsigned char)i); |
| 620 | out8(COL_PAL_DATA,dac[i][0]); /* red */ |
| 621 | out8(COL_PAL_DATA,dac[i][1]); /* green */ |
| 622 | out8(COL_PAL_DATA,dac[i][2]); /* blue */ |
| 623 | } |
| 624 | out8(COL_PAL_MASK,0xff); /* set mask */ |
| 625 | } |
| 626 | /* set Graphic Controller Register */ |
| 627 | void vga_set_gr(void) |
| 628 | { |
| 629 | int i; |
| 630 | i=0; |
| 631 | while(grmr[i].reg!=0xFF) { |
| 632 | out8(GR_INDEX,grmr[i].reg); |
| 633 | out8(GR_DATA,grmr[i].val); |
| 634 | i++; |
| 635 | } |
| 636 | } |
| 637 | |
| 638 | /* Set Sequencer Registers */ |
| 639 | void vga_set_seq(void) |
| 640 | { |
| 641 | int i; |
| 642 | i=0; |
| 643 | while(seq[i].reg!=0xFF) { |
| 644 | out8(SEQ_INDEX,seq[i].reg); |
| 645 | out8(SEQ_DATA,seq[i].val); |
| 646 | i++; |
| 647 | } |
| 648 | } |
| 649 | |
| 650 | |
| 651 | /* Set Extension Registers */ |
| 652 | void vga_set_xreg(void) |
| 653 | { |
| 654 | int i; |
| 655 | i=0; |
| 656 | while(xreg[i].reg!=0xFF) { |
| 657 | out8(XREG_INDEX,xreg[i].reg); |
| 658 | out8(XREG_DATA,xreg[i].val); |
| 659 | i++; |
| 660 | } |
| 661 | } |
| 662 | |
| 663 | /************************************************************ |
| 664 | * some helping routines |
| 665 | */ |
| 666 | |
| 667 | void vga_write_sr(unsigned char reg,unsigned char val) |
| 668 | { |
| 669 | out8(SEQ_INDEX,reg); |
| 670 | out8(SEQ_DATA,val); |
| 671 | } |
| 672 | |
| 673 | |
| 674 | void vga_write_gr(unsigned char reg,unsigned char val) |
| 675 | { |
| 676 | out8(GR_INDEX,reg); |
| 677 | out8(GR_DATA,val); |
| 678 | } |
| 679 | |
| 680 | void vga_write_cr(unsigned char reg,unsigned char val) |
| 681 | { |
| 682 | out8(CRT_INDEX,reg); |
| 683 | out8(CRT_DATA,val); |
| 684 | } |
| 685 | |
| 686 | |
| 687 | #if 0 |
| 688 | void video_dump_reg(void) |
| 689 | { |
| 690 | /* first dump attributes */ |
| 691 | int i; |
| 692 | unsigned char status; |
| 693 | |
| 694 | |
| 695 | printf("Extended Regs:\n"); |
| 696 | i=0; |
| 697 | while(xreg[i].reg!=0xFF) { |
| 698 | out8(XREG_INDEX,xreg[i].reg); |
| 699 | status=in8(XREG_DATA); |
| 700 | printf("XR%02X is %02X, should be %02X\n",xreg[i].reg,status,xreg[i].val); |
| 701 | i++; |
| 702 | } |
| 703 | printf("Sequencer Regs:\n"); |
| 704 | i=0; |
| 705 | while(seq[i].reg!=0xFF) { |
| 706 | out8(SEQ_INDEX,seq[i].reg); |
| 707 | status=in8(SEQ_DATA); |
| 708 | printf("SR%02X is %02X, should be %02X\n",seq[i].reg,status,seq[i].val); |
| 709 | i++; |
| 710 | } |
| 711 | printf("Graphic Regs:\n"); |
| 712 | i=0; |
| 713 | while(grmr[i].reg!=0xFF) { |
| 714 | out8(GR_INDEX,grmr[i].reg); |
| 715 | status=in8(GR_DATA); |
| 716 | printf("GR%02X is %02X, should be %02X\n",grmr[i].reg,status,grmr[i].val); |
| 717 | i++; |
| 718 | } |
| 719 | printf("CRT Regs:\n"); |
| 720 | i=0; |
| 721 | while(crtc[i].reg!=0xFF) { |
| 722 | out8(CRT_INDEX,crtc[i].reg); |
| 723 | status=in8(CRT_DATA); |
| 724 | printf("CR%02X is %02X, should be %02X\n",crtc[i].reg,status,crtc[i].val); |
| 725 | i++; |
| 726 | } |
| 727 | printf("Attributes:\n"); |
| 728 | status=in8(STATUS_REG1); |
| 729 | i=0; |
| 730 | while(attr[i].reg!=0xFF) { |
| 731 | out8(ATTRI_INDEX,attr[i].reg); |
| 732 | status=in8(ATTRI_DATA); |
| 733 | out8(ATTRI_INDEX,attr[i].val); /* Attribute uses index for index and data */ |
| 734 | printf("AR%02X is %02X, should be %02X\n",attr[i].reg,status,attr[i].val); |
| 735 | i++; |
| 736 | } |
| 737 | } |
| 738 | #endif |
| 739 | |
| 740 | #endif /* CONFIG_VIDEO */ |
| 741 | |
| 742 | |
| 743 | |
| 744 | |
| 745 | |
| 746 | |
| 747 | |
| 748 | |
| 749 | |
| 750 | |
| 751 | |
| 752 | |
| 753 | |
| 754 | |
| 755 | |
| 756 | |
| 757 | |
| 758 | |
| 759 | |
| 760 | |