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