ppc64: Don't set Kp bit on SLB
[openbios.git] / libopenbios / console_common.c
blob22ec230ffa1369c8ab0a4175dba762ded8f30508
1 /*
2 * <console.c>
4 * Simple text console
6 * Copyright (C) 2002, 2003 Samuel Rydh (samuel@ibrium.se)
7 * Copyright (C) 2005 Stefan Reinauer <stepan@openbios.org>
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation
15 #include "config.h"
16 #include "libopenbios/bindings.h"
17 #include "libopenbios/fontdata.h"
18 #include "libopenbios/console.h"
19 #include "packages/video.h"
21 #define FONT_ADJ_HEIGHT (FONT_HEIGHT + 2)
23 // Warning: will hang on purpose when encountering unknown codes
24 //#define DEBUG_CONSOLE
25 #ifdef DEBUG_CONSOLE
26 #define DPRINTF(fmt, args...) \
27 do { \
28 printk(fmt , ##args); \
29 for (;;); \
30 } while (0)
31 #else
32 #define DPRINTF(fmt, args...) do {} while(0)
33 #endif
35 typedef enum {
36 ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey,
37 EShash, ESsetG0, ESsetG1, ESpercent, ESignore, ESnonstd,
38 ESpalette
39 } vc_state_t;
41 #define NPAR 16
42 static struct {
43 int inited;
44 int physw, physh;
45 int w,h;
47 int x,y;
48 char *buf;
50 int cursor_on;
51 vc_state_t vc_state;
52 unsigned int vc_npar,vc_par[NPAR]; /* Parameters of current
53 escape sequence */
54 } cons;
56 static int
57 get_conschar( int x, int y )
59 if( (unsigned int)x < cons.w && (unsigned int)y < cons.h )
60 return cons.buf[y*cons.w + x];
61 return ' ';
64 static void
65 draw_char( unsigned int h, unsigned int v )
67 const unsigned char *c = fontdata;
68 int x, y, xx, rskip, m;
69 int invert = (h==cons.x && v==cons.y && cons.cursor_on);
70 int ch = get_conschar( h, v );
72 while( h >= cons.w || v >= cons.h )
73 return;
75 h *= FONT_WIDTH;
76 v *= FONT_ADJ_HEIGHT;
78 rskip = (FONT_WIDTH > 8)? 2 : 1;
79 c += rskip * (unsigned int)(ch & 0xff) * FONT_HEIGHT;
81 for( x=0; x<FONT_WIDTH; x++ ) {
82 xx = x % 8;
83 if( x && !xx )
84 c++;
85 m = (1<<(7-xx));
86 for( y=0; y<FONT_HEIGHT; y++ ){
87 int col = ((!(c[rskip*y] & m)) != invert) ? 254 : 0;
88 draw_pixel( h+x, v+y+1, col );
90 draw_pixel( h+x, v, 254 );
91 draw_pixel( h+x, v+FONT_HEIGHT+1, 254 );
95 static void
96 show_cursor( int show )
98 if( cons.cursor_on == show )
99 return;
100 cons.cursor_on = show;
101 draw_char( cons.x, cons.y );
105 static void
106 draw_line( int n )
108 int i;
110 if( n >= cons.h || n < 0 )
111 return;
112 for( i=0; i<cons.w; i++ )
113 draw_char( i, n );
116 #if 0
117 static void
118 refresh( void )
120 int i;
121 for( i=0; i<cons.h; i++ )
122 draw_line(i);
124 #endif
127 console_init( void )
129 if( video_get_res(&cons.physw,&cons.physh) < 0 )
130 return -1;
132 set_color( 0, 0 );
134 cons.w = cons.physw/FONT_WIDTH;
135 cons.h = cons.physh/FONT_ADJ_HEIGHT;
136 cons.buf = malloc( cons.w * cons.h );
137 cons.inited = 1;
138 cons.x = cons.y = 0;
139 cons.vc_state = ESnormal;
140 return 0;
143 void
144 console_close( void )
146 if( !cons.inited )
147 return;
148 free( cons.buf );
149 cons.inited = 0;
152 static void
153 rec_char( int ch, int x, int y )
155 if( (unsigned int)x < cons.w && (unsigned int)y < cons.h ) {
156 cons.buf[y*cons.w + x] = ch;
157 draw_char( x, y );
161 static void
162 scroll1( void )
164 int x, y;
166 video_scroll(FONT_ADJ_HEIGHT);
168 for (y = 1; y < cons.h - 1; y++) {
169 for (x = 0; x < cons.w; x++)
170 cons.buf[(y - 1) * cons.w + x] = cons.buf[y * cons.w + x];
172 for (x = 0; x < cons.w; x++)
173 cons.buf[(cons.h - 1) * cons.w + x] = ' ';
174 draw_line(cons.h - 1);
177 // Insert char
178 static void csi_at(unsigned int nr)
180 unsigned int x;
182 if (nr > cons.w - cons.x)
183 nr = cons.w - cons.x;
184 else if (!nr)
185 return;
187 for (x = cons.x + nr; x < cons.w - 1; x++)
188 cons.buf[cons.y * cons.w + x - nr] = cons.buf[cons.y * cons.w + x];
189 for (x = cons.x; x < cons.x + nr; x++)
190 cons.buf[cons.y * cons.w + x] = ' ';
191 draw_line(cons.y);
194 static void
195 do_con_trol(unsigned char ch)
197 unsigned int i, j;
199 switch (ch) {
200 case 7:
201 // BEL
202 return;
203 case 8:
204 // BS
205 if (cons.x)
206 cons.x--;
207 return;
208 case 9:
209 // HT
210 cons.x = (cons.x + 8) & ~7;
211 return;
212 case 10:
213 // LF
214 cons.x = 0;
215 cons.y++;
216 return;
217 case 12:
218 // FF
219 for (i = 0; i < cons.h; i++) {
220 for (j = 0; j < cons.w; j++)
221 cons.buf[i * cons.w + j] = ' ';
222 draw_line(i);
224 cons.x = cons.y = 0;
225 return;
226 case 13:
227 // CR
228 cons.x = 0;
229 return;
230 case 25:
231 // EM
232 return;
233 case 24: // CAN
234 case 26: // SUB
235 cons.vc_state = ESnormal;
236 return;
237 case 27:
238 // ESC
239 cons.vc_state = ESesc;
240 return;
242 if (ch < 32)
243 DPRINTF("Unhandled control char %d\n", ch);
245 switch (cons.vc_state) {
246 case ESesc:
247 cons.vc_state = ESnormal;
248 switch (ch) {
249 case '[':
250 cons.vc_state = ESsquare;
251 return;
252 case 'M':
253 scroll1();
254 return;
255 default:
256 DPRINTF("Unhandled basic escape code '%c'\n", ch);
257 return;
259 return;
260 case ESsquare:
261 for(cons.vc_npar = 0; cons.vc_npar < NPAR ; cons.vc_npar++)
262 cons.vc_par[cons.vc_npar] = 0;
263 cons.vc_npar = 0;
264 cons.vc_state = ESgetpars;
265 // Fall through
266 case ESgetpars:
267 if (ch == ';' && cons.vc_npar < NPAR - 1) {
268 cons.vc_npar++;
269 return;
270 } else if (ch >= '0' && ch <= '9') {
271 cons.vc_par[cons.vc_npar] *= 10;
272 cons.vc_par[cons.vc_npar] += ch - '0';
273 return;
274 } else
275 cons.vc_state=ESgotpars;
276 // Fall through
277 case ESgotpars:
278 cons.vc_state = ESnormal;
279 switch(ch) {
280 case 'A':
281 // Cursor up
282 if (cons.vc_par[0] == 0)
283 cons.vc_par[0] = 1;
284 if (cons.y - cons.vc_par[0] > 0)
285 cons.y -= cons.vc_par[0];
286 return;
287 case 'B':
288 // Cursor down
289 if (cons.vc_par[0] == 0)
290 cons.vc_par[0] = 1;
291 if (cons.y + cons.vc_par[0] < cons.h - 1)
292 cons.y += cons.vc_par[0];
293 return;
294 case 'C':
295 // Cursor right
296 if (cons.vc_par[0] == 0)
297 cons.vc_par[0] = 1;
298 if (cons.x + cons.vc_par[0] < cons.w - 1)
299 cons.x += cons.vc_par[0];
300 return;
301 case 'D':
302 // Cursor left
303 if (cons.vc_par[0] == 0)
304 cons.vc_par[0] = 1;
305 if (cons.x - cons.vc_par[0] > 0)
306 cons.x -= cons.vc_par[0];
307 return;
308 case 'H':
309 case 'f':
310 // Set cursor position
311 if (cons.vc_par[0])
312 cons.vc_par[0]--;
314 if (cons.vc_par[1])
315 cons.vc_par[1]--;
317 cons.x = cons.vc_par[1];
318 cons.y = cons.vc_par[0];
319 return;
320 case 'J':
321 if (cons.vc_par[0] == 0 && (unsigned int)cons.y < (unsigned int)cons.h &&
322 (unsigned int)cons.x < (unsigned int)cons.w) {
323 // erase from cursor to end of display
324 for (i = cons.x; i < cons.w; i++)
325 cons.buf[cons.y * cons.w + i] = ' ';
326 draw_line(cons.y);
327 for (j = cons.y + 1; j < cons.h; j++) {
328 for (i = 0; i < cons.w; i++)
329 cons.buf[j * cons.w + i] = ' ';
330 draw_line(j);
332 } else {
333 DPRINTF("Unhandled CSI J code '%c'\n", cons.vc_par[0]);
335 return;
336 case 'K':
337 switch (cons.vc_par[0]) {
338 case 0: /* erase from cursor to end of line */
339 for (i = cons.x; i < cons.w; i++)
340 cons.buf[cons.y * cons.w + i] = ' ';
341 draw_line(cons.y);
342 return;
343 case 1: /* erase from start of line to cursor */
344 for (i = 0; i <= cons.x; i++)
345 cons.buf[cons.y * cons.w + i] = ' ';
346 draw_line(cons.y);
347 return;
348 case 2: /* erase whole line */
349 for (i = 0; i < cons.w; i++)
350 cons.buf[cons.y * cons.w + i] = ' ';
351 draw_line(cons.y);
352 return;
353 default:
354 DPRINTF("Unhandled CSI K code '%c'\n", cons.vc_par[0]);
355 return;
357 return;
358 case 'M':
359 if (cons.vc_par[0] == 1)
360 scroll1();
361 else
362 DPRINTF("Unhandled CSI M %d\n", cons.vc_par[0]);
363 return;
364 case 'm':
365 // Attributes are ignored
366 return;
367 case '@':
368 csi_at(cons.vc_par[0]);
369 return;
370 default:
371 DPRINTF("Unhandled escape code '%c', par[%d, %d, %d, %d, %d]\n",
372 ch, cons.vc_par[0], cons.vc_par[1], cons.vc_par[2],
373 cons.vc_par[3], cons.vc_par[4]);
374 return;
376 return;
377 default:
378 cons.vc_state = ESnormal;
379 rec_char(ch, cons.x++, cons.y);
380 return;
385 console_draw_fstr(const char *str, int len)
387 unsigned int y, x;
388 unsigned char ch;
390 if (!str || len <= 0) {
391 return 0;
394 if( !cons.inited && console_init() )
395 return -1;
397 show_cursor(0);
398 while((ch = *str++) && len--) {
399 do_con_trol(ch);
401 if( cons.x >= cons.w ) {
402 cons.x=0, cons.y++;
404 if( cons.y >= cons.h ) {
405 for( y=0; y<cons.h-1; y++ )
406 for( x=0; x<cons.w; x++ )
407 cons.buf[y*cons.w + x] = cons.buf[(y+1)*cons.w + x];
408 cons.y = cons.h-1;
409 cons.x = 0;
410 scroll1();
413 show_cursor(1);
414 return 0;