promcon.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:12k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

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