Pull acpi_device_handle_cleanup into release branch
[deliverable/linux.git] / drivers / video / console / promcon.c
1 /* $Id: promcon.c,v 1.17 2000/07/26 23:02:52 davem Exp $
2 * Console driver utilizing PROM sun terminal emulation
3 *
4 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
5 * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz)
6 */
7
8 #include <linux/module.h>
9 #include <linux/kernel.h>
10 #include <linux/errno.h>
11 #include <linux/string.h>
12 #include <linux/mm.h>
13 #include <linux/tty.h>
14 #include <linux/slab.h>
15 #include <linux/delay.h>
16 #include <linux/console.h>
17 #include <linux/vt_kern.h>
18 #include <linux/selection.h>
19 #include <linux/fb.h>
20 #include <linux/init.h>
21 #include <linux/kd.h>
22
23 #include <asm/oplib.h>
24 #include <asm/uaccess.h>
25
26 static short pw = 80 - 1, ph = 34 - 1;
27 static short px, py;
28 static unsigned long promcon_uni_pagedir[2];
29
30 extern u8 promfont_unicount[];
31 extern u16 promfont_unitable[];
32
33 #define PROMCON_COLOR 0
34
35 #if PROMCON_COLOR
36 #define inverted(s) ((((s) & 0x7700) == 0x0700) ? 0 : 1)
37 #else
38 #define inverted(s) (((s) & 0x0800) ? 1 : 0)
39 #endif
40
41 static __inline__ void
42 promcon_puts(char *buf, int cnt)
43 {
44 prom_printf("%*.*s", cnt, cnt, buf);
45 }
46
47 static int
48 promcon_start(struct vc_data *conp, char *b)
49 {
50 unsigned short *s = (unsigned short *)
51 (conp->vc_origin + py * conp->vc_size_row + (px << 1));
52 u16 cs;
53
54 cs = scr_readw(s);
55 if (px == pw) {
56 unsigned short *t = s - 1;
57 u16 ct = scr_readw(t);
58
59 if (inverted(cs) && inverted(ct))
60 return sprintf(b, "\b\033[7m%c\b\033[@%c\033[m", cs,
61 ct);
62 else if (inverted(cs))
63 return sprintf(b, "\b\033[7m%c\033[m\b\033[@%c", cs,
64 ct);
65 else if (inverted(ct))
66 return sprintf(b, "\b%c\b\033[@\033[7m%c\033[m", cs,
67 ct);
68 else
69 return sprintf(b, "\b%c\b\033[@%c", cs, ct);
70 }
71
72 if (inverted(cs))
73 return sprintf(b, "\033[7m%c\033[m\b", cs);
74 else
75 return sprintf(b, "%c\b", cs);
76 }
77
78 static int
79 promcon_end(struct vc_data *conp, char *b)
80 {
81 unsigned short *s = (unsigned short *)
82 (conp->vc_origin + py * conp->vc_size_row + (px << 1));
83 char *p = b;
84 u16 cs;
85
86 b += sprintf(b, "\033[%d;%dH", py + 1, px + 1);
87
88 cs = scr_readw(s);
89 if (px == pw) {
90 unsigned short *t = s - 1;
91 u16 ct = scr_readw(t);
92
93 if (inverted(cs) && inverted(ct))
94 b += sprintf(b, "\b%c\b\033[@\033[7m%c\033[m", cs, ct);
95 else if (inverted(cs))
96 b += sprintf(b, "\b%c\b\033[@%c", cs, ct);
97 else if (inverted(ct))
98 b += sprintf(b, "\b\033[7m%c\b\033[@%c\033[m", cs, ct);
99 else
100 b += sprintf(b, "\b\033[7m%c\033[m\b\033[@%c", cs, ct);
101 return b - p;
102 }
103
104 if (inverted(cs))
105 b += sprintf(b, "%c\b", cs);
106 else
107 b += sprintf(b, "\033[7m%c\033[m\b", cs);
108 return b - p;
109 }
110
111 const char *promcon_startup(void)
112 {
113 const char *display_desc = "PROM";
114 int node;
115 char buf[40];
116
117 node = prom_getchild(prom_root_node);
118 node = prom_searchsiblings(node, "options");
119 if (prom_getproperty(node, "screen-#columns", buf, 40) != -1) {
120 pw = simple_strtoul(buf, NULL, 0);
121 if (pw < 10 || pw > 256)
122 pw = 80;
123 pw--;
124 }
125 if (prom_getproperty(node, "screen-#rows", buf, 40) != -1) {
126 ph = simple_strtoul(buf, NULL, 0);
127 if (ph < 10 || ph > 256)
128 ph = 34;
129 ph--;
130 }
131 promcon_puts("\033[H\033[J", 6);
132 return display_desc;
133 }
134
135 static void
136 promcon_init_unimap(struct vc_data *conp)
137 {
138 mm_segment_t old_fs = get_fs();
139 struct unipair *p, *p1;
140 u16 *q;
141 int i, j, k;
142
143 p = kmalloc(256*sizeof(struct unipair), GFP_KERNEL);
144 if (!p) return;
145
146 q = promfont_unitable;
147 p1 = p;
148 k = 0;
149 for (i = 0; i < 256; i++)
150 for (j = promfont_unicount[i]; j; j--) {
151 p1->unicode = *q++;
152 p1->fontpos = i;
153 p1++;
154 k++;
155 }
156 set_fs(KERNEL_DS);
157 con_clear_unimap(conp, NULL);
158 con_set_unimap(conp, k, p);
159 con_protect_unimap(conp, 1);
160 set_fs(old_fs);
161 kfree(p);
162 }
163
164 static void
165 promcon_init(struct vc_data *conp, int init)
166 {
167 unsigned long p;
168
169 conp->vc_can_do_color = PROMCON_COLOR;
170 if (init) {
171 conp->vc_cols = pw + 1;
172 conp->vc_rows = ph + 1;
173 }
174 p = *conp->vc_uni_pagedir_loc;
175 if (conp->vc_uni_pagedir_loc == &conp->vc_uni_pagedir ||
176 !--conp->vc_uni_pagedir_loc[1])
177 con_free_unimap(conp);
178 conp->vc_uni_pagedir_loc = promcon_uni_pagedir;
179 promcon_uni_pagedir[1]++;
180 if (!promcon_uni_pagedir[0] && p) {
181 promcon_init_unimap(conp);
182 }
183 if (!init) {
184 if (conp->vc_cols != pw + 1 || conp->vc_rows != ph + 1)
185 vc_resize(conp, pw + 1, ph + 1);
186 }
187 }
188
189 static void
190 promcon_deinit(struct vc_data *conp)
191 {
192 /* When closing the last console, reset video origin */
193 if (!--promcon_uni_pagedir[1])
194 con_free_unimap(conp);
195 conp->vc_uni_pagedir_loc = &conp->vc_uni_pagedir;
196 con_set_default_unimap(conp);
197 }
198
199 static int
200 promcon_switch(struct vc_data *conp)
201 {
202 return 1;
203 }
204
205 static unsigned short *
206 promcon_repaint_line(unsigned short *s, unsigned char *buf, unsigned char **bp)
207 {
208 int cnt = pw + 1;
209 int attr = -1;
210 unsigned char *b = *bp;
211
212 while (cnt--) {
213 u16 c = scr_readw(s);
214 if (attr != inverted(c)) {
215 attr = inverted(c);
216 if (attr) {
217 strcpy (b, "\033[7m");
218 b += 4;
219 } else {
220 strcpy (b, "\033[m");
221 b += 3;
222 }
223 }
224 *b++ = c;
225 s++;
226 if (b - buf >= 224) {
227 promcon_puts(buf, b - buf);
228 b = buf;
229 }
230 }
231 *bp = b;
232 return s;
233 }
234
235 static void
236 promcon_putcs(struct vc_data *conp, const unsigned short *s,
237 int count, int y, int x)
238 {
239 unsigned char buf[256], *b = buf;
240 unsigned short attr = scr_readw(s);
241 unsigned char save;
242 int i, last = 0;
243
244 if (console_blanked)
245 return;
246
247 if (count <= 0)
248 return;
249
250 b += promcon_start(conp, b);
251
252 if (x + count >= pw + 1) {
253 if (count == 1) {
254 x -= 1;
255 save = scr_readw((unsigned short *)(conp->vc_origin
256 + y * conp->vc_size_row
257 + (x << 1)));
258
259 if (px != x || py != y) {
260 b += sprintf(b, "\033[%d;%dH", y + 1, x + 1);
261 px = x;
262 py = y;
263 }
264
265 if (inverted(attr))
266 b += sprintf(b, "\033[7m%c\033[m", scr_readw(s++));
267 else
268 b += sprintf(b, "%c", scr_readw(s++));
269
270 strcpy(b, "\b\033[@");
271 b += 4;
272
273 if (inverted(save))
274 b += sprintf(b, "\033[7m%c\033[m", save);
275 else
276 b += sprintf(b, "%c", save);
277
278 px++;
279
280 b += promcon_end(conp, b);
281 promcon_puts(buf, b - buf);
282 return;
283 } else {
284 last = 1;
285 count = pw - x - 1;
286 }
287 }
288
289 if (inverted(attr)) {
290 strcpy(b, "\033[7m");
291 b += 4;
292 }
293
294 if (px != x || py != y) {
295 b += sprintf(b, "\033[%d;%dH", y + 1, x + 1);
296 px = x;
297 py = y;
298 }
299
300 for (i = 0; i < count; i++) {
301 if (b - buf >= 224) {
302 promcon_puts(buf, b - buf);
303 b = buf;
304 }
305 *b++ = scr_readw(s++);
306 }
307
308 px += count;
309
310 if (last) {
311 save = scr_readw(s++);
312 b += sprintf(b, "%c\b\033[@%c", scr_readw(s++), save);
313 px++;
314 }
315
316 if (inverted(attr)) {
317 strcpy(b, "\033[m");
318 b += 3;
319 }
320
321 b += promcon_end(conp, b);
322 promcon_puts(buf, b - buf);
323 }
324
325 static void
326 promcon_putc(struct vc_data *conp, int c, int y, int x)
327 {
328 unsigned short s;
329
330 if (console_blanked)
331 return;
332
333 scr_writew(c, &s);
334 promcon_putcs(conp, &s, 1, y, x);
335 }
336
337 static void
338 promcon_clear(struct vc_data *conp, int sy, int sx, int height, int width)
339 {
340 unsigned char buf[256], *b = buf;
341 int i, j;
342
343 if (console_blanked)
344 return;
345
346 b += promcon_start(conp, b);
347
348 if (!sx && width == pw + 1) {
349
350 if (!sy && height == ph + 1) {
351 strcpy(b, "\033[H\033[J");
352 b += 6;
353 b += promcon_end(conp, b);
354 promcon_puts(buf, b - buf);
355 return;
356 } else if (sy + height == ph + 1) {
357 b += sprintf(b, "\033[%dH\033[J", sy + 1);
358 b += promcon_end(conp, b);
359 promcon_puts(buf, b - buf);
360 return;
361 }
362
363 b += sprintf(b, "\033[%dH", sy + 1);
364 for (i = 1; i < height; i++) {
365 strcpy(b, "\033[K\n");
366 b += 4;
367 }
368
369 strcpy(b, "\033[K");
370 b += 3;
371
372 b += promcon_end(conp, b);
373 promcon_puts(buf, b - buf);
374 return;
375
376 } else if (sx + width == pw + 1) {
377
378 b += sprintf(b, "\033[%d;%dH", sy + 1, sx + 1);
379 for (i = 1; i < height; i++) {
380 strcpy(b, "\033[K\n");
381 b += 4;
382 }
383
384 strcpy(b, "\033[K");
385 b += 3;
386
387 b += promcon_end(conp, b);
388 promcon_puts(buf, b - buf);
389 return;
390 }
391
392 for (i = sy + 1; i <= sy + height; i++) {
393 b += sprintf(b, "\033[%d;%dH", i, sx + 1);
394 for (j = 0; j < width; j++)
395 *b++ = ' ';
396 if (b - buf + width >= 224) {
397 promcon_puts(buf, b - buf);
398 b = buf;
399 }
400 }
401
402 b += promcon_end(conp, b);
403 promcon_puts(buf, b - buf);
404 }
405
406 static void
407 promcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
408 int height, int width)
409 {
410 char buf[256], *b = buf;
411
412 if (console_blanked)
413 return;
414
415 b += promcon_start(conp, b);
416 if (sy == dy && height == 1) {
417 if (dx > sx && dx + width == conp->vc_cols)
418 b += sprintf(b, "\033[%d;%dH\033[%d@\033[%d;%dH",
419 sy + 1, sx + 1, dx - sx, py + 1, px + 1);
420 else if (dx < sx && sx + width == conp->vc_cols)
421 b += sprintf(b, "\033[%d;%dH\033[%dP\033[%d;%dH",
422 dy + 1, dx + 1, sx - dx, py + 1, px + 1);
423
424 b += promcon_end(conp, b);
425 promcon_puts(buf, b - buf);
426 return;
427 }
428
429 /*
430 * FIXME: What to do here???
431 * Current console.c should not call it like that ever.
432 */
433 prom_printf("\033[7mFIXME: bmove not handled\033[m\n");
434 }
435
436 static void
437 promcon_cursor(struct vc_data *conp, int mode)
438 {
439 char buf[32], *b = buf;
440
441 switch (mode) {
442 case CM_ERASE:
443 break;
444
445 case CM_MOVE:
446 case CM_DRAW:
447 b += promcon_start(conp, b);
448 if (px != conp->vc_x || py != conp->vc_y) {
449 px = conp->vc_x;
450 py = conp->vc_y;
451 b += sprintf(b, "\033[%d;%dH", py + 1, px + 1);
452 }
453 promcon_puts(buf, b - buf);
454 break;
455 }
456 }
457
458 static int
459 promcon_blank(struct vc_data *conp, int blank, int mode_switch)
460 {
461 if (blank) {
462 promcon_puts("\033[H\033[J\033[7m \033[m\b", 15);
463 return 0;
464 } else {
465 /* Let console.c redraw */
466 return 1;
467 }
468 }
469
470 static int
471 promcon_scroll(struct vc_data *conp, int t, int b, int dir, int count)
472 {
473 unsigned char buf[256], *p = buf;
474 unsigned short *s;
475 int i;
476
477 if (console_blanked)
478 return 0;
479
480 p += promcon_start(conp, p);
481
482 switch (dir) {
483 case SM_UP:
484 if (b == ph + 1) {
485 p += sprintf(p, "\033[%dH\033[%dM", t + 1, count);
486 px = 0;
487 py = t;
488 p += promcon_end(conp, p);
489 promcon_puts(buf, p - buf);
490 break;
491 }
492
493 s = (unsigned short *)(conp->vc_origin
494 + (t + count) * conp->vc_size_row);
495
496 p += sprintf(p, "\033[%dH", t + 1);
497
498 for (i = t; i < b - count; i++)
499 s = promcon_repaint_line(s, buf, &p);
500
501 for (; i < b - 1; i++) {
502 strcpy(p, "\033[K\n");
503 p += 4;
504 if (p - buf >= 224) {
505 promcon_puts(buf, p - buf);
506 p = buf;
507 }
508 }
509
510 strcpy(p, "\033[K");
511 p += 3;
512
513 p += promcon_end(conp, p);
514 promcon_puts(buf, p - buf);
515 break;
516
517 case SM_DOWN:
518 if (b == ph + 1) {
519 p += sprintf(p, "\033[%dH\033[%dL", t + 1, count);
520 px = 0;
521 py = t;
522 p += promcon_end(conp, p);
523 promcon_puts(buf, p - buf);
524 break;
525 }
526
527 s = (unsigned short *)(conp->vc_origin + t * conp->vc_size_row);
528
529 p += sprintf(p, "\033[%dH", t + 1);
530
531 for (i = t; i < t + count; i++) {
532 strcpy(p, "\033[K\n");
533 p += 4;
534 if (p - buf >= 224) {
535 promcon_puts(buf, p - buf);
536 p = buf;
537 }
538 }
539
540 for (; i < b; i++)
541 s = promcon_repaint_line(s, buf, &p);
542
543 p += promcon_end(conp, p);
544 promcon_puts(buf, p - buf);
545 break;
546 }
547
548 return 0;
549 }
550
551 #if !(PROMCON_COLOR)
552 static u8 promcon_build_attr(struct vc_data *conp, u8 _color, u8 _intensity, u8 _blink, u8 _underline, u8 _reverse)
553 {
554 return (_reverse) ? 0xf : 0x7;
555 }
556 #endif
557
558 /*
559 * The console 'switch' structure for the VGA based console
560 */
561
562 static int promcon_dummy(void)
563 {
564 return 0;
565 }
566
567 #define DUMMY (void *) promcon_dummy
568
569 const struct consw prom_con = {
570 .owner = THIS_MODULE,
571 .con_startup = promcon_startup,
572 .con_init = promcon_init,
573 .con_deinit = promcon_deinit,
574 .con_clear = promcon_clear,
575 .con_putc = promcon_putc,
576 .con_putcs = promcon_putcs,
577 .con_cursor = promcon_cursor,
578 .con_scroll = promcon_scroll,
579 .con_bmove = promcon_bmove,
580 .con_switch = promcon_switch,
581 .con_blank = promcon_blank,
582 .con_set_palette = DUMMY,
583 .con_scrolldelta = DUMMY,
584 #if !(PROMCON_COLOR)
585 .con_build_attr = promcon_build_attr,
586 #endif
587 };
588
589 void __init prom_con_init(void)
590 {
591 #ifdef CONFIG_DUMMY_CONSOLE
592 if (conswitchp == &dummy_con)
593 take_over_console(&prom_con, 0, MAX_NR_CONSOLES-1, 1);
594 else
595 #endif
596 if (conswitchp == &prom_con)
597 promcon_init_unimap(vc_cons[fg_console].d);
598 }
This page took 0.046541 seconds and 6 git commands to generate.