|
|
1.1 ! root 1: /* ! 2: * Creation Date: <2002/10/23 20:26:40 samuel> ! 3: * Time-stamp: <2004/01/07 19:39:15 samuel> ! 4: * ! 5: * <video.c> ! 6: * ! 7: * Mac-on-Linux display node ! 8: * ! 9: * Copyright (C) 2002, 2003, 2004 Samuel Rydh ([email protected]) ! 10: * ! 11: * This program is free software; you can redistribute it and/or ! 12: * modify it under the terms of the GNU General Public License ! 13: * as published by the Free Software Foundation ! 14: * ! 15: */ ! 16: ! 17: #include "config.h" ! 18: #include "libopenbios/bindings.h" ! 19: #include "libc/diskio.h" ! 20: #include "libopenbios/ofmem.h" ! 21: #include "drivers/drivers.h" ! 22: #include "packages/video.h" ! 23: #include "libopenbios/console.h" ! 24: #include "drivers/vga.h" ! 25: ! 26: typedef struct osi_fb_info { ! 27: unsigned long mphys; ! 28: int rb, w, h, depth; ! 29: } osi_fb_info_t; ! 30: ! 31: static struct { ! 32: int has_video; ! 33: osi_fb_info_t fb; ! 34: unsigned long *pal; /* 256 elements */ ! 35: } video; ! 36: ! 37: ! 38: int ! 39: video_get_res( int *w, int *h ) ! 40: { ! 41: if( !video.has_video ) { ! 42: *w = *h = 0; ! 43: return -1; ! 44: } ! 45: *w = video.fb.w; ! 46: *h = video.fb.h; ! 47: return 0; ! 48: } ! 49: ! 50: static void ! 51: startup_splash( void ) ! 52: { ! 53: #ifdef CONFIG_MOL ! 54: int fd, s, i, y, x, dx, dy; ! 55: int width, height; ! 56: char *pp, *p; ! 57: char buf[64]; ! 58: #endif ! 59: ! 60: /* only draw logo in 24-bit mode (for now) */ ! 61: if( video.fb.depth < 15 ) ! 62: return; ! 63: #ifdef CONFIG_MOL ! 64: for( i=0; i<2; i++ ) { ! 65: if( !BootHGetStrResInd("bootlogo", buf, sizeof(buf), 0, i) ) ! 66: return; ! 67: *(!i ? &width : &height) = atol(buf); ! 68: } ! 69: ! 70: if( (s=width * height * 3) > 0x20000 ) ! 71: return; ! 72: ! 73: if( (fd=open_io("pseudo:,bootlogo")) >= 0 ) { ! 74: p = malloc( s ); ! 75: if( read_io(fd, p, s) != s ) ! 76: printk("bootlogo size error\n"); ! 77: close_io( fd ); ! 78: ! 79: dx = (video.fb.w - width)/2; ! 80: dy = (video.fb.h - height)/3; ! 81: ! 82: pp = (char*)video.fb.mphys + dy * video.fb.rb + dx * (video.fb.depth >= 24 ? 4 : 2); ! 83: ! 84: for( y=0 ; y<height; y++, pp += video.fb.rb ) { ! 85: if( video.fb.depth >= 24 ) { ! 86: unsigned long *d = (unsigned long*)pp; ! 87: for( x=0; x<width; x++, p+=3, d++ ) ! 88: *d = ((int)p[0] << 16) | ((int)p[1] << 8) | p[2]; ! 89: } else if( video.fb.depth == 15 ) { ! 90: unsigned short *d = (unsigned short*)pp; ! 91: for( x=0; x<width; x++, p+=3, d++ ) { ! 92: int col = ((int)p[0] << 16) | ((int)p[1] << 8) | p[2]; ! 93: *d = ((col>>9) & 0x7c00) | ((col>>6) & 0x03e0) | ((col>>3) & 0x1f); ! 94: } ! 95: } ! 96: } ! 97: free( p ); ! 98: } ! 99: #else ! 100: /* No bootlogo support yet on other platforms */ ! 101: return; ! 102: #endif ! 103: } ! 104: ! 105: static unsigned long ! 106: get_color( int col_ind ) ! 107: { ! 108: unsigned long col; ! 109: if( !video.has_video || col_ind < 0 || col_ind > 255 ) ! 110: return 0; ! 111: if( video.fb.depth == 8 ) ! 112: return col_ind; ! 113: col = video.pal[col_ind]; ! 114: if( video.fb.depth == 24 || video.fb.depth == 32 ) ! 115: return col; ! 116: if( video.fb.depth == 15 ) ! 117: return ((col>>9) & 0x7c00) | ((col>>6) & 0x03e0) | ((col>>3) & 0x1f); ! 118: return 0; ! 119: } ! 120: ! 121: void ! 122: draw_pixel( int x, int y, int colind ) ! 123: { ! 124: char *p = (char*)video.fb.mphys + video.fb.rb * y; ! 125: int color, d = video.fb.depth; ! 126: ! 127: if( x < 0 || y < 0 || x >= video.fb.w || y >=video.fb.h ) ! 128: return; ! 129: color = get_color( colind ); ! 130: ! 131: if( d >= 24 ) ! 132: *((unsigned long*)p + x) = color; ! 133: else if( d >= 15 ) ! 134: *((short*)p + x) = color; ! 135: else ! 136: *(p + x) = color; ! 137: } ! 138: ! 139: static void ! 140: fill_rect( int col_ind, int x, int y, int w, int h ) ! 141: { ! 142: char *pp; ! 143: unsigned long col = get_color(col_ind); ! 144: ! 145: if (!video.has_video || x < 0 || y < 0 || w <= 0 || h <= 0 || ! 146: x + w > video.fb.w || y + h > video.fb.h) ! 147: return; ! 148: ! 149: pp = (char*)video.fb.mphys + video.fb.rb * y; ! 150: for( ; h--; pp += video.fb.rb ) { ! 151: int ww = w; ! 152: if( video.fb.depth == 24 || video.fb.depth == 32 ) { ! 153: unsigned long *p = (unsigned long*)pp + x; ! 154: while( ww-- ) ! 155: *p++ = col; ! 156: } else if( video.fb.depth == 16 || video.fb.depth == 15 ) { ! 157: unsigned short *p = (unsigned short*)pp + x; ! 158: while( ww-- ) ! 159: *p++ = col; ! 160: } else { ! 161: char *p = (char *)((unsigned short*)pp + x); ! 162: ! 163: while( ww-- ) ! 164: *p++ = col; ! 165: } ! 166: } ! 167: } ! 168: ! 169: static void ! 170: refresh_palette( void ) ! 171: { ! 172: #ifdef CONFIG_MOL ! 173: if( video.fb.depth == 8 ) ! 174: OSI_RefreshPalette(); ! 175: #endif ! 176: } ! 177: ! 178: void ! 179: set_color( int ind, unsigned long color ) ! 180: { ! 181: if( !video.has_video || ind < 0 || ind > 255 ) ! 182: return; ! 183: video.pal[ind] = color; ! 184: ! 185: #ifdef CONFIG_MOL ! 186: if( video.fb.depth == 8 ) ! 187: OSI_SetColor( ind, color ); ! 188: #elif defined(CONFIG_SPARC32) ! 189: if( video.fb.depth == 8 ) { ! 190: dac[0] = ind << 24; ! 191: dac[1] = ((color >> 16) & 0xff) << 24; // Red ! 192: dac[1] = ((color >> 8) & 0xff) << 24; // Green ! 193: dac[1] = (color & 0xff) << 24; // Blue ! 194: } ! 195: #else ! 196: vga_set_color(ind, ((color >> 16) & 0xff), ! 197: ((color >> 8) & 0xff), ! 198: (color & 0xff)); ! 199: #endif ! 200: } ! 201: ! 202: void ! 203: video_scroll( int height ) ! 204: { ! 205: int i, offs, size, *dest, *src; ! 206: ! 207: if (height <= 0 || height >= video.fb.h) { ! 208: return; ! 209: } ! 210: offs = video.fb.rb * height; ! 211: size = (video.fb.h * video.fb.rb - offs)/16; ! 212: dest = (int*)video.fb.mphys; ! 213: src = (int*)(video.fb.mphys + offs); ! 214: ! 215: for( i=0; i<size; i++ ) { ! 216: dest[0] = src[0]; ! 217: dest[1] = src[1]; ! 218: dest[2] = src[2]; ! 219: dest[3] = src[3]; ! 220: dest += 4; ! 221: src += 4; ! 222: } ! 223: } ! 224: ! 225: /************************************************************************/ ! 226: /* OF methods */ ! 227: /************************************************************************/ ! 228: ! 229: DECLARE_NODE( video, INSTALL_OPEN, 0, "Tdisplay" ); ! 230: ! 231: /* ( -- width height ) (?) */ ! 232: static void ! 233: video_dimensions( void ) ! 234: { ! 235: int w, h; ! 236: (void) video_get_res( &w, &h ); ! 237: PUSH( w ); ! 238: PUSH( h ); ! 239: } ! 240: ! 241: /* ( table start count -- ) (?) */ ! 242: static void ! 243: video_set_colors( void ) ! 244: { ! 245: int count = POP(); ! 246: int start = POP(); ! 247: unsigned char *p = (unsigned char*)cell2pointer(POP()); ! 248: int i; ! 249: ! 250: for( i=0; i<count; i++, p+=3 ) { ! 251: unsigned long col = (p[0] << 16) | (p[1] << 8) | p[2]; ! 252: set_color( i + start, col ); ! 253: } ! 254: refresh_palette(); ! 255: } ! 256: ! 257: /* ( r g b index -- ) */ ! 258: static void ! 259: video_color_bang( void ) ! 260: { ! 261: int index = POP(); ! 262: int b = POP(); ! 263: int g = POP(); ! 264: int r = POP(); ! 265: unsigned long col = ((r << 16) & 0xff0000) | ((g << 8) & 0x00ff00) | (b & 0xff); ! 266: /* printk("color!: %08lx %08lx %08lx %08lx\n", r, g, b, index ); */ ! 267: set_color( index, col ); ! 268: refresh_palette(); ! 269: } ! 270: ! 271: /* ( color_ind x y width height -- ) (?) */ ! 272: static void ! 273: video_fill_rect( void ) ! 274: { ! 275: int h = POP(); ! 276: int w = POP(); ! 277: int y = POP(); ! 278: int x = POP(); ! 279: int color_ind = POP(); ! 280: ! 281: fill_rect( color_ind, x, y, w, h ); ! 282: } ! 283: ! 284: /* ( addr len -- actual ) */ ! 285: static void ! 286: video_write(void) ! 287: { ! 288: char *addr; ! 289: int len; ! 290: ! 291: len = POP(); ! 292: addr = (char *)cell2pointer(POP()); ! 293: ! 294: console_draw_fstr(addr, len); ! 295: PUSH(len); ! 296: } ! 297: ! 298: NODE_METHODS( video ) = { ! 299: {"dimensions", video_dimensions }, ! 300: {"set-colors", video_set_colors }, ! 301: {"fill-rectangle", video_fill_rect }, ! 302: {"color!", video_color_bang }, ! 303: {"write", video_write }, ! 304: }; ! 305: ! 306: ! 307: /************************************************************************/ ! 308: /* init */ ! 309: /************************************************************************/ ! 310: ! 311: void ! 312: init_video( unsigned long fb, int width, int height, int depth, int rb ) ! 313: { ! 314: int i; ! 315: #ifdef CONFIG_PPC ! 316: int s, size; ! 317: #endif ! 318: phandle_t ph=0; ! 319: ! 320: video.fb.mphys = fb; ! 321: video.fb.w = width; ! 322: video.fb.h = height; ! 323: video.fb.depth = depth; ! 324: video.fb.rb = rb; ! 325: while( (ph=dt_iterate_type(ph, "display")) ) { ! 326: set_int_property( ph, "width", video.fb.w ); ! 327: set_int_property( ph, "height", video.fb.h ); ! 328: set_int_property( ph, "depth", video.fb.depth ); ! 329: set_int_property( ph, "linebytes", video.fb.rb ); ! 330: set_int_property( ph, "address", video.fb.mphys ); ! 331: } ! 332: video.has_video = 1; ! 333: video.pal = malloc( 256 * sizeof(unsigned long) ); ! 334: ! 335: #ifdef CONFIG_PPC ! 336: s = (video.fb.mphys & 0xfff); ! 337: size = ((video.fb.h * video.fb.rb + s) + 0xfff) & ~0xfff; ! 338: ! 339: ofmem_claim_phys( video.fb.mphys, size, 0 ); ! 340: ofmem_claim_virt( video.fb.mphys, size, 0 ); ! 341: ofmem_map( video.fb.mphys, video.fb.mphys, size, -1 ); ! 342: #endif ! 343: ! 344: for( i=0; i<256; i++ ) ! 345: set_color( i, i * 0x010101 ); ! 346: ! 347: set_color( 254, 0xffffcc ); ! 348: fill_rect( 254, 0, 0, video.fb.w, video.fb.h ); ! 349: ! 350: refresh_palette(); ! 351: startup_splash(); ! 352: ! 353: REGISTER_NODE( video ); ! 354: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.