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

嵌入式Linux

开发平台:

Unix_Linux

  1. /*
  2.  *  linux/drivers/char/console.c
  3.  *
  4.  *  Copyright (C) 1991, 1992  Linus Torvalds
  5.  */
  6. /*
  7.  * Hopefully this will be a rather complete VT102 implementation.
  8.  *
  9.  * Beeping thanks to John T Kohl.
  10.  *
  11.  * Virtual Consoles, Screen Blanking, Screen Dumping, Color, Graphics
  12.  *   Chars, and VT100 enhancements by Peter MacDonald.
  13.  *
  14.  * Copy and paste function by Andrew Haylett,
  15.  *   some enhancements by Alessandro Rubini.
  16.  *
  17.  * Code to check for different video-cards mostly by Galen Hunt,
  18.  * <g-hunt@ee.utah.edu>
  19.  *
  20.  * Rudimentary ISO 10646/Unicode/UTF-8 character set support by
  21.  * Markus Kuhn, <mskuhn@immd4.informatik.uni-erlangen.de>.
  22.  *
  23.  * Dynamic allocation of consoles, aeb@cwi.nl, May 1994
  24.  * Resizing of consoles, aeb, 940926
  25.  *
  26.  * Code for xterm like mouse click reporting by Peter Orbaek 20-Jul-94
  27.  * <poe@daimi.aau.dk>
  28.  *
  29.  * User-defined bell sound, new setterm control sequences and printk
  30.  * redirection by Martin Mares <mj@k332.feld.cvut.cz> 19-Nov-95
  31.  *
  32.  * APM screenblank bug fixed Takashi Manabe <manabe@roy.dsl.tutics.tut.jp>
  33.  *
  34.  * Merge with the abstract console driver by Geert Uytterhoeven
  35.  * <geert@linux-m68k.org>, Jan 1997.
  36.  *
  37.  *   Original m68k console driver modifications by
  38.  *
  39.  *     - Arno Griffioen <arno@usn.nl>
  40.  *     - David Carter <carter@cs.bris.ac.uk>
  41.  * 
  42.  *   Note that the abstract console driver allows all consoles to be of
  43.  *   potentially different sizes, so the following variables depend on the
  44.  *   current console (currcons):
  45.  *
  46.  *     - video_num_columns
  47.  *     - video_num_lines
  48.  *     - video_size_row
  49.  *     - can_do_color
  50.  *
  51.  *   The abstract console driver provides a generic interface for a text
  52.  *   console. It supports VGA text mode, frame buffer based graphical consoles
  53.  *   and special graphics processors that are only accessible through some
  54.  *   registers (e.g. a TMS340x0 GSP).
  55.  *
  56.  *   The interface to the hardware is specified using a special structure
  57.  *   (struct consw) which contains function pointers to console operations
  58.  *   (see <linux/console.h> for more information).
  59.  *
  60.  * Support for changeable cursor shape
  61.  * by Pavel Machek <pavel@atrey.karlin.mff.cuni.cz>, August 1997
  62.  *
  63.  * Ported to i386 and con_scrolldelta fixed
  64.  * by Emmanuel Marty <core@ggi-project.org>, April 1998
  65.  *
  66.  * Resurrected character buffers in videoram plus lots of other trickery
  67.  * by Martin Mares <mj@atrey.karlin.mff.cuni.cz>, July 1998
  68.  *
  69.  * Removed old-style timers, introduced console_timer, made timer
  70.  * deletion SMP-safe.  17Jun00, Andrew Morton <andrewm@uow.edu.au>
  71.  *
  72.  * Removed console_lock, enabled interrupts across all console operations
  73.  * 13 March 2001, Andrew Morton
  74.  *
  75.  * Split out con_write_ctrl_* functions from do_con_write & changed
  76.  * vc_state to function pointer
  77.  * by Russell King <rmk@arm.linux.org.uk>, July 1998
  78.  */
  79. #define CONSOLE_WIP
  80. #include <linux/module.h>
  81. #include <linux/sched.h>
  82. #include <linux/tty.h>
  83. #include <linux/tty_flip.h>
  84. #include <linux/kernel.h>
  85. #include <linux/string.h>
  86. #include <linux/errno.h>
  87. #include <linux/kd.h>
  88. #include <linux/slab.h>
  89. #include <linux/major.h>
  90. #include <linux/mm.h>
  91. #include <linux/console.h>
  92. #include <linux/init.h>
  93. #include <linux/devfs_fs_kernel.h>
  94. #include <linux/vt_kern.h>
  95. #include <linux/selection.h>
  96. #include <linux/console_struct.h>
  97. #include <linux/kbd_kern.h>
  98. #include <linux/consolemap.h>
  99. #include <linux/timer.h>
  100. #include <linux/interrupt.h>
  101. #include <linux/config.h>
  102. #include <linux/version.h>
  103. #include <linux/tqueue.h>
  104. #include <linux/bootmem.h>
  105. #ifdef CONFIG_CONSOLE_PM // bushi
  106. #include <linux/pm.h>
  107. #endif
  108. #include <linux/smp_lock.h>
  109. #include <asm/io.h>
  110. #include <asm/system.h>
  111. #include <asm/uaccess.h>
  112. #include <asm/bitops.h>
  113. #include "console_macros.h"
  114. const struct consw *conswitchp;
  115. /* A bitmap for codes <32. A bit of 1 indicates that the code
  116.  * corresponding to that bit number invokes some special action
  117.  * (such as cursor movement) and should not be displayed as a
  118.  * glyph unless the disp_ctrl mode is explicitly enabled.
  119.  */
  120. #define CTRL_ACTION 0x0d00ff81
  121. #define CTRL_ALWAYS 0x0800f501 /* Cannot be overridden by disp_ctrl */
  122. /*
  123.  * Here is the default bell parameters: 750HZ, 1/8th of a second
  124.  */
  125. #define DEFAULT_BELL_PITCH 750
  126. #define DEFAULT_BELL_DURATION (HZ/8)
  127. extern void vcs_make_devfs (unsigned int index, int unregister);
  128. #ifndef MIN
  129. #define MIN(a,b) ((a) < (b) ? (a) : (b))
  130. #endif
  131. static struct tty_struct *console_table[MAX_NR_CONSOLES];
  132. static struct termios *console_termios[MAX_NR_CONSOLES];
  133. static struct termios *console_termios_locked[MAX_NR_CONSOLES];
  134. struct vc vc_cons [MAX_NR_CONSOLES];
  135. #ifndef VT_SINGLE_DRIVER
  136. static const struct consw *con_driver_map[MAX_NR_CONSOLES];
  137. #endif
  138. static int con_open(struct tty_struct *, struct file *);
  139. static void vc_init(unsigned int console, unsigned int rows,
  140.     unsigned int cols, int do_clear);
  141. static void gotoxy(int currcons, int new_x, int new_y);
  142. static void save_cur(int currcons);
  143. static void reset_terminal(int currcons, int do_clear);
  144. static void con_flush_chars(struct tty_struct *tty);
  145. #ifdef CONFIG_CONSOLE_PM // bushi
  146. static void blank_screen(unsigned long dummy);
  147. static void set_vesa_blanking(unsigned long arg);
  148. static void unblank_screen_t(unsigned long dummy);
  149. #endif
  150. static void set_cursor(int currcons);
  151. static void hide_cursor(int currcons);
  152. static void console_callback(void *ignored);
  153. static int printable; /* Is console ready for printing? */
  154. #ifdef CONFIG_CONSOLE_PM // bushi
  155. int do_poke_blanked_console;
  156. int console_blanked;
  157. static int vesa_blank_mode; /* 0:none 1:suspendV 2:suspendH 3:powerdown */
  158. static int blankinterval = 10*60*HZ;
  159. static int vesa_off_interval;
  160. #endif
  161. static struct tq_struct console_callback_tq = {
  162. routine: console_callback,
  163. };
  164. /*
  165.  * fg_console is the current virtual console,
  166.  * last_console is the last used one,
  167.  * want_console is the console we want to switch to,
  168.  * kmsg_redirect is the console for kernel messages,
  169.  */
  170. int fg_console;
  171. int last_console;
  172. int want_console = -1;
  173. int kmsg_redirect;
  174. /*
  175.  * For each existing display, we have a pointer to console currently visible
  176.  * on that display, allowing consoles other than fg_console to be refreshed
  177.  * appropriately. Unless the low-level driver supplies its own display_fg
  178.  * variable, we use this one for the "master display".
  179.  */
  180. static struct vc_data *master_display_fg;
  181. /*
  182.  * Unfortunately, we need to delay tty echo when we're currently writing to the
  183.  * console since the code is (and always was) not re-entrant, so we schedule
  184.  * all flip requests to process context with schedule-task() and run it from
  185.  * console_callback().
  186.  */
  187. /*
  188.  * For the same reason, we defer scrollback to the console callback.
  189.  */
  190. static int scrollback_delta;
  191. #ifdef CONFIG_CONSOLE_PM // bushi
  192. /*
  193.  * Hook so that the power management routines can (un)blank
  194.  * the console on our behalf.
  195.  */
  196. int (*console_blank_hook)(int);
  197. static struct timer_list console_timer;
  198. #endif
  199. /*
  200.  * Low-Level Functions
  201.  */
  202. #define IS_FG (currcons == fg_console)
  203. #define IS_VISIBLE CON_IS_VISIBLE(vc_cons[currcons].d)
  204. #ifdef VT_BUF_VRAM_ONLY
  205. #define DO_UPDATE 0
  206. #else
  207. #define DO_UPDATE IS_VISIBLE
  208. #endif
  209. #ifdef CONFIG_CONSOLE_PM // bushi
  210. static int pm_con_request(struct pm_dev *dev, pm_request_t rqst, void *data);
  211. static struct pm_dev *pm_con;
  212. #endif
  213. static inline unsigned short *screenpos(int currcons, int offset, int viewed)
  214. {
  215. unsigned short *p;
  216. if (!viewed)
  217. p = (unsigned short *)(origin + offset);
  218. else if (!sw->con_screen_pos)
  219. p = (unsigned short *)(visible_origin + offset);
  220. else
  221. p = sw->con_screen_pos(vc_cons[currcons].d, offset);
  222. return p;
  223. }
  224. static inline void scrolldelta(int lines)
  225. {
  226. scrollback_delta += lines;
  227. schedule_console_callback();
  228. }
  229. void schedule_console_callback(void)
  230. {
  231. schedule_task(&console_callback_tq);
  232. }
  233. static void scrup(int currcons, unsigned int t, unsigned int b, int nr)
  234. {
  235. unsigned short *d, *s;
  236. if (t+nr >= b)
  237. nr = b - t - 1;
  238. if (b > video_num_lines || t >= b || nr < 1)
  239. return;
  240. if (IS_VISIBLE && sw->con_scroll(vc_cons[currcons].d, t, b, SM_UP, nr))
  241. return;
  242. d = (unsigned short *) (origin+video_size_row*t);
  243. s = (unsigned short *) (origin+video_size_row*(t+nr));
  244. scr_memcpyw(d, s, (b-t-nr) * video_size_row);
  245. scr_memsetw(d + (b-t-nr) * video_num_columns, video_erase_char, video_size_row*nr);
  246. }
  247. static void
  248. scrdown(int currcons, unsigned int t, unsigned int b, int nr)
  249. {
  250. unsigned short *s;
  251. unsigned int step;
  252. if (t+nr >= b)
  253. nr = b - t - 1;
  254. if (b > video_num_lines || t >= b || nr < 1)
  255. return;
  256. if (IS_VISIBLE && sw->con_scroll(vc_cons[currcons].d, t, b, SM_DOWN, nr))
  257. return;
  258. s = (unsigned short *) (origin+video_size_row*t);
  259. step = video_num_columns * nr;
  260. scr_memmovew(s + step, s, (b-t-nr)*video_size_row);
  261. scr_memsetw(s, video_erase_char, 2*step);
  262. }
  263. static void do_update_region(int currcons, unsigned long start, int count)
  264. {
  265. #ifndef VT_BUF_VRAM_ONLY
  266. unsigned int xx, yy, offset;
  267. u16 *p;
  268. p = (u16 *) start;
  269. if (!sw->con_getxy) {
  270. offset = (start - origin) / 2;
  271. xx = offset % video_num_columns;
  272. yy = offset / video_num_columns;
  273. } else {
  274. int nxx, nyy;
  275. start = sw->con_getxy(vc_cons[currcons].d, start, &nxx, &nyy);
  276. xx = nxx; yy = nyy;
  277. }
  278. for(;;) {
  279. u16 attrib = scr_readw(p) & 0xff00;
  280. int startx = xx;
  281. u16 *q = p;
  282. while (xx < video_num_columns && count) {
  283. if (attrib != (scr_readw(p) & 0xff00)) {
  284. if (p > q)
  285. sw->con_putcs(vc_cons[currcons].d, q, p-q, yy, startx);
  286. startx = xx;
  287. q = p;
  288. attrib = scr_readw(p) & 0xff00;
  289. }
  290. p++;
  291. xx++;
  292. count--;
  293. }
  294. if (p > q)
  295. sw->con_putcs(vc_cons[currcons].d, q, p-q, yy, startx);
  296. if (!count)
  297. break;
  298. xx = 0;
  299. yy++;
  300. if (sw->con_getxy) {
  301. p = (u16 *)start;
  302. start = sw->con_getxy(vc_cons[currcons].d, start, NULL, NULL);
  303. }
  304. }
  305. #endif
  306. }
  307. void update_region(int currcons, unsigned long start, int count)
  308. {
  309. if (DO_UPDATE) {
  310. hide_cursor(currcons);
  311. do_update_region(currcons, start, count);
  312. set_cursor(currcons);
  313. }
  314. }
  315. /* Structure of attributes is hardware-dependent */
  316. static u8 build_attr(int currcons, u8 _color, u8 _intensity, u8 _blink, u8 _underline, u8 _reverse)
  317. {
  318. if (sw->con_build_attr)
  319. return sw->con_build_attr(vc_cons[currcons].d, _color, _intensity, _blink, _underline, _reverse);
  320. #ifndef VT_BUF_VRAM_ONLY
  321. /*
  322.  * ++roman: I completely changed the attribute format for monochrome
  323.  * mode (!can_do_color). The formerly used MDA (monochrome display
  324.  * adapter) format didn't allow the combination of certain effects.
  325.  * Now the attribute is just a bit vector:
  326.  *  Bit 0..1: intensity (0..2)
  327.  *  Bit 2   : underline
  328.  *  Bit 3   : reverse
  329.  *  Bit 7   : blink
  330.  */
  331. {
  332. u8 a = color;
  333. if (!can_do_color)
  334. return _intensity |
  335.        (_underline ? 4 : 0) |
  336.        (_reverse ? 8 : 0) |
  337.        (_blink ? 0x80 : 0);
  338. if (_underline)
  339. a = (a & 0xf0) | ulcolor;
  340. else if (_intensity == 0)
  341. a = (a & 0xf0) | halfcolor;
  342. if (_reverse)
  343. a = ((a) & 0x88) | ((((a) >> 4) | ((a) << 4)) & 0x77);
  344. if (_blink)
  345. a ^= 0x80;
  346. if (_intensity == 2)
  347. a ^= 0x08;
  348. if (hi_font_mask == 0x100)
  349. a <<= 1;
  350. return a;
  351. }
  352. #else
  353. return 0;
  354. #endif
  355. }
  356. static void update_attr(int currcons)
  357. {
  358. attr = build_attr(currcons, color, intensity, blink, underline, reverse ^ decscnm);
  359. video_erase_char = (build_attr(currcons, color, 1, blink, 0, decscnm) << 8) | ' ';
  360. }
  361. /* Note: inverting the screen twice should revert to the original state */
  362. void invert_screen(int currcons, int offset, int count, int viewed)
  363. {
  364. unsigned short *p;
  365. count /= 2;
  366. p = screenpos(currcons, offset, viewed);
  367. if (sw->con_invert_region)
  368. sw->con_invert_region(vc_cons[currcons].d, p, count);
  369. #ifndef VT_BUF_VRAM_ONLY
  370. else {
  371. u16 *q = p;
  372. int cnt = count;
  373. u16 a;
  374. if (!can_do_color) {
  375. while (cnt--) {
  376.     a = scr_readw(q);
  377.     a ^= 0x0800;
  378.     scr_writew(a, q);
  379.     q++;
  380. }
  381. } else if (hi_font_mask == 0x100) {
  382. while (cnt--) {
  383. a = scr_readw(q);
  384. a = ((a) & 0x11ff) | (((a) & 0xe000) >> 4) | (((a) & 0x0e00) << 4);
  385. scr_writew(a, q);
  386. q++;
  387. }
  388. } else {
  389. while (cnt--) {
  390. a = scr_readw(q);
  391. a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) | (((a) & 0x0700) << 4);
  392. scr_writew(a, q);
  393. q++;
  394. }
  395. }
  396. }
  397. #endif
  398. if (DO_UPDATE)
  399. do_update_region(currcons, (unsigned long) p, count);
  400. }
  401. /* used by selection: complement pointer position */
  402. void complement_pos(int currcons, int offset)
  403. {
  404. static unsigned short *p;
  405. static unsigned short old;
  406. static unsigned short oldx, oldy;
  407. if (p) {
  408. scr_writew(old, p);
  409. if (DO_UPDATE)
  410. sw->con_putc(vc_cons[currcons].d, old, oldy, oldx);
  411. }
  412. if (offset == -1)
  413. p = NULL;
  414. else {
  415. unsigned short new;
  416. p = screenpos(currcons, offset, 1);
  417. old = scr_readw(p);
  418. new = old ^ complement_mask;
  419. scr_writew(new, p);
  420. if (DO_UPDATE) {
  421. oldx = (offset >> 1) % video_num_columns;
  422. oldy = (offset >> 1) / video_num_columns;
  423. sw->con_putc(vc_cons[currcons].d, new, oldy, oldx);
  424. }
  425. }
  426. }
  427. static void insert_char(int currcons, unsigned int nr)
  428. {
  429. unsigned short *p, *q = (unsigned short *) pos;
  430. p = q + video_num_columns - nr - x;
  431. while (--p >= q)
  432. scr_writew(scr_readw(p), p + nr);
  433. scr_memsetw(q, video_erase_char, nr*2);
  434. need_wrap = 0;
  435. if (DO_UPDATE) {
  436. unsigned short oldattr = attr;
  437. sw->con_bmove(vc_cons[currcons].d,y,x,y,x+nr,1,
  438.       video_num_columns-x-nr);
  439. attr = video_erase_char >> 8;
  440. while (nr--)
  441. sw->con_putc(vc_cons[currcons].d,
  442.      video_erase_char,y,x+nr);
  443. attr = oldattr;
  444. }
  445. }
  446. static void delete_char(int currcons, unsigned int nr)
  447. {
  448. unsigned int i = x;
  449. unsigned short *p = (unsigned short *) pos;
  450. while (++i <= video_num_columns - nr) {
  451. scr_writew(scr_readw(p+nr), p);
  452. p++;
  453. }
  454. scr_memsetw(p, video_erase_char, nr*2);
  455. need_wrap = 0;
  456. if (DO_UPDATE) {
  457. unsigned short oldattr = attr;
  458. sw->con_bmove(vc_cons[currcons].d, y, x+nr, y, x, 1,
  459.       video_num_columns-x-nr);
  460. attr = video_erase_char >> 8;
  461. while (nr--)
  462. sw->con_putc(vc_cons[currcons].d,
  463.      video_erase_char, y,
  464.      video_num_columns-1-nr);
  465. attr = oldattr;
  466. }
  467. }
  468. #ifdef CONFIG_CONSOLE_PM // bushi
  469. static int softcursor_original;
  470. static void add_softcursor(int currcons)
  471. {
  472. int i = scr_readw((u16 *) pos);
  473. u32 type = cursor_type;
  474. if (! (type & 0x10)) return;
  475. if (softcursor_original != -1) return;
  476. softcursor_original = i;
  477. i |= ((type >> 8) & 0xff00 );
  478. i ^= ((type) & 0xff00 );
  479. if ((type & 0x20) && ((softcursor_original & 0x7000) == (i & 0x7000))) i ^= 0x7000;
  480. if ((type & 0x40) && ((i & 0x700) == ((i & 0x7000) >> 4))) i ^= 0x0700;
  481. scr_writew(i, (u16 *) pos);
  482. if (DO_UPDATE)
  483. sw->con_putc(vc_cons[currcons].d, i, y, x);
  484. }
  485. #endif
  486. static void hide_cursor(int currcons)
  487. {
  488. if (currcons == sel_cons)
  489. clear_selection();
  490. #ifdef CONFIG_CONSOLE_PM // bushi
  491. if (softcursor_original != -1) {
  492. scr_writew(softcursor_original,(u16 *) pos);
  493. if (DO_UPDATE)
  494. sw->con_putc(vc_cons[currcons].d, softcursor_original, y, x);
  495. softcursor_original = -1;
  496. }
  497. sw->con_cursor(vc_cons[currcons].d,CM_ERASE);
  498. #endif
  499. }
  500. static void set_cursor(int currcons)
  501. {
  502. #ifdef CONFIG_CONSOLE_PM // bushi
  503.     if (!IS_FG || console_blanked || vcmode == KD_GRAPHICS)
  504. return;
  505.     if (deccm) {
  506. if (currcons == sel_cons)
  507. clear_selection();
  508. add_softcursor(currcons);
  509. if ((cursor_type & 0x0f) != 1)
  510.     sw->con_cursor(vc_cons[currcons].d,CM_DRAW);
  511.     } else
  512. hide_cursor(currcons);
  513. #else
  514. if (!IS_FG || vcmode == KD_GRAPHICS)
  515. return;
  516. hide_cursor(currcons);
  517. #endif
  518. }
  519. static void set_origin(int currcons)
  520. {
  521. if (!IS_VISIBLE ||
  522.     !sw->con_set_origin ||
  523.     !sw->con_set_origin(vc_cons[currcons].d))
  524. origin = (unsigned long) screenbuf;
  525. visible_origin = origin;
  526. scr_end = origin + screenbuf_size;
  527. pos = origin + video_size_row*y + 2*x;
  528. }
  529. static inline void save_screen(int currcons)
  530. {
  531. if (sw->con_save_screen)
  532. sw->con_save_screen(vc_cons[currcons].d);
  533. }
  534. /*
  535.  * Redrawing of screen
  536.  */
  537. void redraw_screen(int new_console, int is_switch)
  538. {
  539. int redraw = 1;
  540. int currcons, old_console;
  541. if (!vc_cons_allocated(new_console)) {
  542. /* strange ... */
  543. /* printk("redraw_screen: tty %d not allocated ??n", new_console+1); */
  544. return;
  545. }
  546. if (is_switch) {
  547. currcons = fg_console;
  548. hide_cursor(currcons);
  549. if (fg_console != new_console) {
  550. struct vc_data **display = vc_cons[new_console].d->vc_display_fg;
  551. old_console = (*display) ? (*display)->vc_num : fg_console;
  552. *display = vc_cons[new_console].d;
  553. fg_console = new_console;
  554. currcons = old_console;
  555. if (!IS_VISIBLE) {
  556. save_screen(currcons);
  557. set_origin(currcons);
  558. }
  559. currcons = new_console;
  560. if (old_console == new_console)
  561. redraw = 0;
  562. }
  563. } else {
  564. currcons = new_console;
  565. hide_cursor(currcons);
  566. }
  567. if (redraw) {
  568. int update;
  569. set_origin(currcons);
  570. update = sw->con_switch(vc_cons[currcons].d);
  571. set_palette(currcons);
  572. if (update && vcmode != KD_GRAPHICS)
  573. do_update_region(currcons, origin, screenbuf_size/2);
  574. }
  575. set_cursor(currcons);
  576. if (is_switch) {
  577. set_leds();
  578. compute_shiftstate();
  579. }
  580. }
  581. /*
  582.  * Allocation, freeing and resizing of VTs.
  583.  */
  584. int vc_cons_allocated(unsigned int i)
  585. {
  586. return (i < MAX_NR_CONSOLES && vc_cons[i].d);
  587. }
  588. static void visual_init(int currcons, int init)
  589. {
  590.     /* ++Geert: sw->con_init determines console size */
  591.     sw = conswitchp;
  592. #ifndef VT_SINGLE_DRIVER
  593.     if (con_driver_map[currcons])
  594. sw = con_driver_map[currcons];
  595. #endif
  596.     cons_num = currcons;
  597.     display_fg = &master_display_fg;
  598.     vc_cons[currcons].d->vc_uni_pagedir_loc = &vc_cons[currcons].d->vc_uni_pagedir;
  599.     vc_cons[currcons].d->vc_uni_pagedir = 0;
  600.     hi_font_mask = 0;
  601.     complement_mask = 0;
  602.     can_do_color = 0;
  603.     sw->con_init(vc_cons[currcons].d, init);
  604.     if (!complement_mask)
  605.         complement_mask = can_do_color ? 0x7700 : 0x0800;
  606.     s_complement_mask = complement_mask;
  607.     video_size_row = video_num_columns<<1;
  608.     screenbuf_size = video_num_lines*video_size_row;
  609. }
  610. int vc_allocate(unsigned int currcons) /* return 0 on success */
  611. {
  612. if (currcons >= MAX_NR_CONSOLES)
  613. return -ENXIO;
  614. if (!vc_cons[currcons].d) {
  615.     long p, q;
  616.     /* prevent users from taking too much memory */
  617.     if (currcons >= MAX_NR_USER_CONSOLES && !capable(CAP_SYS_RESOURCE))
  618.       return -EPERM;
  619.     /* due to the granularity of kmalloc, we waste some memory here */
  620.     /* the alloc is done in two steps, to optimize the common situation
  621.        of a 25x80 console (structsize=216, screenbuf_size=4000) */
  622.     /* although the numbers above are not valid since long ago, the
  623.        point is still up-to-date and the comment still has its value
  624.        even if only as a historical artifact.  --mj, July 1998 */
  625.     p = (long) kmalloc(structsize, GFP_KERNEL);
  626.     if (!p)
  627. return -ENOMEM;
  628.     memset((void *)p, 0, structsize);
  629.     vc_cons[currcons].d = (struct vc_data *)p;
  630.     vt_cons[currcons] = (struct vt_struct *)(p+sizeof(struct vc_data));
  631.     visual_init(currcons, 1);
  632.     if (!*vc_cons[currcons].d->vc_uni_pagedir_loc)
  633. con_set_default_unimap(currcons);
  634.     q = (long)kmalloc(screenbuf_size, GFP_KERNEL);
  635.     if (!q) {
  636. kfree((char *) p);
  637. vc_cons[currcons].d = NULL;
  638. vt_cons[currcons] = NULL;
  639. return -ENOMEM;
  640.     }
  641.     screenbuf = (unsigned short *) q;
  642.     kmalloced = 1;
  643.     vc_init(currcons, video_num_lines, video_num_columns, 1);
  644. #ifdef CONFIG_CONSOLE_PM //bushi
  645.     if (!pm_con) {
  646.     pm_con = pm_register(PM_SYS_DEV,
  647.  PM_SYS_VGA,
  648.  pm_con_request);
  649.     }
  650. #endif
  651. }
  652. return 0;
  653. }
  654. /*
  655.  * Change # of rows and columns (0 means unchanged/the size of fg_console)
  656.  * [this is to be used together with some user program
  657.  * like resize that changes the hardware videomode]
  658.  */
  659. int vc_resize(unsigned int lines, unsigned int cols,
  660.       unsigned int first, unsigned int last)
  661. {
  662. unsigned int cc, ll, ss, sr, todo = 0;
  663. unsigned int currcons = fg_console, i;
  664. unsigned short *newscreens[MAX_NR_CONSOLES];
  665. cc = (cols ? cols : video_num_columns);
  666. ll = (lines ? lines : video_num_lines);
  667. sr = cc << 1;
  668. ss = sr * ll;
  669.   for (currcons = first; currcons <= last; currcons++) {
  670. if (!vc_cons_allocated(currcons) ||
  671.     (cc == video_num_columns && ll == video_num_lines))
  672. newscreens[currcons] = NULL;
  673. else {
  674. unsigned short *p = (unsigned short *) kmalloc(ss, GFP_USER);
  675. if (!p) {
  676. for (i = first; i< currcons; i++)
  677. if (newscreens[i])
  678. kfree(newscreens[i]);
  679. return -ENOMEM;
  680. }
  681. newscreens[currcons] = p;
  682. todo++;
  683. }
  684. }
  685. if (!todo)
  686. return 0;
  687. for (currcons = first; currcons <= last; currcons++) {
  688. unsigned int occ, oll, oss, osr;
  689. unsigned long ol, nl, nlend, rlth, rrem;
  690. if (!newscreens[currcons] || !vc_cons_allocated(currcons))
  691. continue;
  692. oll = video_num_lines;
  693. occ = video_num_columns;
  694. osr = video_size_row;
  695. oss = screenbuf_size;
  696. video_num_lines = ll;
  697. video_num_columns = cc;
  698. video_size_row = sr;
  699. screenbuf_size = ss;
  700. rlth = MIN(osr, sr);
  701. rrem = sr - rlth;
  702. ol = origin;
  703. nl = (long) newscreens[currcons];
  704. nlend = nl + ss;
  705. if (ll < oll)
  706. ol += (oll - ll) * osr;
  707. update_attr(currcons);
  708. while (ol < scr_end) {
  709. scr_memcpyw((unsigned short *) nl, (unsigned short *) ol, rlth);
  710. if (rrem)
  711. scr_memsetw((void *)(nl + rlth), video_erase_char, rrem);
  712. ol += osr;
  713. nl += sr;
  714. }
  715. if (nlend > nl)
  716. scr_memsetw((void *) nl, video_erase_char, nlend - nl);
  717. if (kmalloced)
  718. kfree(screenbuf);
  719. screenbuf = newscreens[currcons];
  720. kmalloced = 1;
  721. screenbuf_size = ss;
  722. set_origin(currcons);
  723. /* do part of a reset_terminal() */
  724. top = 0;
  725. bottom = video_num_lines;
  726. gotoxy(currcons, x, y);
  727. save_cur(currcons);
  728. if (console_table[currcons]) {
  729. struct winsize ws, *cws = &console_table[currcons]->winsize;
  730. memset(&ws, 0, sizeof(ws));
  731. ws.ws_row = video_num_lines;
  732. ws.ws_col = video_num_columns;
  733. if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col) &&
  734.     console_table[currcons]->pgrp > 0)
  735. kill_pg(console_table[currcons]->pgrp, SIGWINCH, 1);
  736. *cws = ws;
  737. }
  738. if (IS_VISIBLE)
  739. update_screen(currcons);
  740. }
  741. return 0;
  742. }
  743. void vc_disallocate(unsigned int currcons)
  744. {
  745. acquire_console_sem();
  746. if (vc_cons_allocated(currcons)) {
  747.     sw->con_deinit(vc_cons[currcons].d);
  748.     if (kmalloced)
  749. kfree(screenbuf);
  750.     if (currcons >= MIN_NR_CONSOLES)
  751. kfree(vc_cons[currcons].d);
  752.     vc_cons[currcons].d = NULL;
  753. }
  754. release_console_sem();
  755. }
  756. /*
  757.  * VT102 emulator
  758.  */
  759. #define set_kbd(x) set_vc_kbd_mode(kbd_table+currcons,x)
  760. #define clr_kbd(x) clr_vc_kbd_mode(kbd_table+currcons,x)
  761. #define is_kbd(x) vc_kbd_mode(kbd_table+currcons,x)
  762. #define decarm VC_REPEAT
  763. #define decckm VC_CKMODE
  764. #define kbdapplic VC_APPLIC
  765. #define lnm VC_CRLF
  766. /*
  767.  * this is what the terminal answers to a ESC-Z or csi0c query.
  768.  */
  769. #define VT100ID "33[?1;2c"
  770. #define VT102ID "33[?6c"
  771. unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7,
  772.        8,12,10,14, 9,13,11,15 };
  773. /* the default colour table, for VGA+ colour systems */
  774. int default_red[] = {0x00,0xaa,0x00,0xaa,0x00,0xaa,0x00,0xaa,
  775.     0x55,0xff,0x55,0xff,0x55,0xff,0x55,0xff};
  776. int default_grn[] = {0x00,0x00,0xaa,0xaa,0x00,0x00,0xaa,0xaa,
  777.     0x55,0x55,0xff,0xff,0x55,0x55,0xff,0xff};
  778. int default_blu[] = {0x00,0x00,0x00,0x00,0xaa,0xaa,0xaa,0xaa,
  779.     0x55,0x55,0x55,0x55,0xff,0xff,0xff,0xff};
  780. /*
  781.  * gotoxy() must verify all boundaries, because the arguments
  782.  * might also be negative. If the given position is out of
  783.  * bounds, the cursor is placed at the nearest margin.
  784.  */
  785. static void gotoxy(int currcons, int new_x, int new_y)
  786. {
  787. int min_y, max_y;
  788. if (new_x < 0)
  789. x = 0;
  790. else
  791. if (new_x >= video_num_columns)
  792. x = video_num_columns - 1;
  793. else
  794. x = new_x;
  795.   if (decom) {
  796. min_y = top;
  797. max_y = bottom;
  798. } else {
  799. min_y = 0;
  800. max_y = video_num_lines;
  801. }
  802. if (new_y < min_y)
  803. y = min_y;
  804. else if (new_y >= max_y)
  805. y = max_y - 1;
  806. else
  807. y = new_y;
  808. pos = origin + y*video_size_row + (x<<1);
  809. need_wrap = 0;
  810. }
  811. /* for absolute user moves, when decom is set */
  812. static void gotoxay(int currcons, int new_x, int new_y)
  813. {
  814. gotoxy(currcons, new_x, decom ? (top+new_y) : new_y);
  815. }
  816. void scrollback(int lines)
  817. {
  818. int currcons = fg_console;
  819. if (!lines)
  820. lines = video_num_lines/2;
  821. scrolldelta(-lines);
  822. }
  823. void scrollfront(int lines)
  824. {
  825. int currcons = fg_console;
  826. if (!lines)
  827. lines = video_num_lines/2;
  828. scrolldelta(lines);
  829. }
  830. static void lf(int currcons)
  831. {
  832.      /* don't scroll if above bottom of scrolling region, or
  833.  * if below scrolling region
  834.  */
  835.      if (y+1 == bottom)
  836. scrup(currcons,top,bottom,1);
  837. else if (y < video_num_lines-1) {
  838.      y++;
  839. pos += video_size_row;
  840. }
  841. need_wrap = 0;
  842. }
  843. static void ri(int currcons)
  844. {
  845.      /* don't scroll if below top of scrolling region, or
  846.  * if above scrolling region
  847.  */
  848. if (y == top)
  849. scrdown(currcons,top,bottom,1);
  850. else if (y > 0) {
  851. y--;
  852. pos -= video_size_row;
  853. }
  854. need_wrap = 0;
  855. }
  856. static inline void cr(int currcons)
  857. {
  858. pos -= x<<1;
  859. need_wrap = x = 0;
  860. }
  861. static inline void bs(int currcons)
  862. {
  863. if (x) {
  864. pos -= 2;
  865. x--;
  866. need_wrap = 0;
  867. }
  868. }
  869. static inline void del(int currcons)
  870. {
  871. /* ignored */
  872. }
  873. static void csi_J(int currcons, int vpar)
  874. {
  875. unsigned int count;
  876. unsigned short * start;
  877. switch (vpar) {
  878. case 0: /* erase from cursor to end of display */
  879. count = (scr_end-pos)>>1;
  880. start = (unsigned short *) pos;
  881. if (DO_UPDATE) {
  882. /* do in two stages */
  883. sw->con_clear(vc_cons[currcons].d, y, x, 1,
  884.       video_num_columns-x);
  885. sw->con_clear(vc_cons[currcons].d, y+1, 0,
  886.       video_num_lines-y-1,
  887.       video_num_columns);
  888. }
  889. break;
  890. case 1: /* erase from start to cursor */
  891. count = ((pos-origin)>>1)+1;
  892. start = (unsigned short *) origin;
  893. if (DO_UPDATE) {
  894. /* do in two stages */
  895. sw->con_clear(vc_cons[currcons].d, 0, 0, y,
  896.       video_num_columns);
  897. sw->con_clear(vc_cons[currcons].d, y, 0, 1,
  898.       x + 1);
  899. }
  900. break;
  901. case 2: /* erase whole display */
  902. count = video_num_columns * video_num_lines;
  903. start = (unsigned short *) origin;
  904. if (DO_UPDATE)
  905. sw->con_clear(vc_cons[currcons].d, 0, 0,
  906.       video_num_lines,
  907.       video_num_columns);
  908. break;
  909. default:
  910. return;
  911. }
  912. scr_memsetw(start, video_erase_char, 2*count);
  913. need_wrap = 0;
  914. }
  915. static void csi_K(int currcons, int vpar)
  916. {
  917. unsigned int count;
  918. unsigned short * start;
  919. switch (vpar) {
  920. case 0: /* erase from cursor to end of line */
  921. count = video_num_columns-x;
  922. start = (unsigned short *) pos;
  923. if (DO_UPDATE)
  924. sw->con_clear(vc_cons[currcons].d, y, x, 1,
  925.       video_num_columns-x);
  926. break;
  927. case 1: /* erase from start of line to cursor */
  928. start = (unsigned short *) (pos - (x<<1));
  929. count = x+1;
  930. if (DO_UPDATE)
  931. sw->con_clear(vc_cons[currcons].d, y, 0, 1,
  932.       x + 1);
  933. break;
  934. case 2: /* erase whole line */
  935. start = (unsigned short *) (pos - (x<<1));
  936. count = video_num_columns;
  937. if (DO_UPDATE)
  938. sw->con_clear(vc_cons[currcons].d, y, 0, 1,
  939.       video_num_columns);
  940. break;
  941. default:
  942. return;
  943. }
  944. scr_memsetw(start, video_erase_char, 2 * count);
  945. need_wrap = 0;
  946. }
  947. static void csi_X(int currcons, int vpar) /* erase the following vpar positions */
  948. {   /* not vt100? */
  949. int count;
  950. if (!vpar)
  951. vpar++;
  952. count = (vpar > video_num_columns-x) ? (video_num_columns-x) : vpar;
  953. scr_memsetw((unsigned short *) pos, video_erase_char, 2 * count);
  954. if (DO_UPDATE)
  955. sw->con_clear(vc_cons[currcons].d, y, x, 1, count);
  956. need_wrap = 0;
  957. }
  958. static void default_attr(int currcons)
  959. {
  960. intensity = 1;
  961. underline = 0;
  962. reverse = 0;
  963. blink = 0;
  964. color = def_color;
  965. }
  966. /* console_sem is held */
  967. static void csi_m(int currcons)
  968. {
  969. int i;
  970. for (i=0;i<=npar;i++)
  971. switch (par[i]) {
  972. case 0: /* all attributes off */
  973. default_attr(currcons);
  974. break;
  975. case 1:
  976. intensity = 2;
  977. break;
  978. case 2:
  979. intensity = 0;
  980. break;
  981. case 4:
  982. underline = 1;
  983. break;
  984. case 5:
  985. blink = 1;
  986. break;
  987. case 7:
  988. reverse = 1;
  989. break;
  990. case 10: /* ANSI X3.64-1979 (SCO-ish?)
  991.   * Select primary font, don't display
  992.   * control chars if defined, don't set
  993.   * bit 8 on output.
  994.   */
  995. translate = set_translate(charset == 0
  996. ? G0_charset
  997. : G1_charset,currcons);
  998. disp_ctrl = 0;
  999. toggle_meta = 0;
  1000. break;
  1001. case 11: /* ANSI X3.64-1979 (SCO-ish?)
  1002.   * Select first alternate font, lets
  1003.   * chars < 32 be displayed as ROM chars.
  1004.   */
  1005. translate = set_translate(IBMPC_MAP,currcons);
  1006. disp_ctrl = 1;
  1007. toggle_meta = 0;
  1008. break;
  1009. case 12: /* ANSI X3.64-1979 (SCO-ish?)
  1010.   * Select second alternate font, toggle
  1011.   * high bit before displaying as ROM char.
  1012.   */
  1013. translate = set_translate(IBMPC_MAP,currcons);
  1014. disp_ctrl = 1;
  1015. toggle_meta = 1;
  1016. break;
  1017. case 21:
  1018. case 22:
  1019. intensity = 1;
  1020. break;
  1021. case 24:
  1022. underline = 0;
  1023. break;
  1024. case 25:
  1025. blink = 0;
  1026. break;
  1027. case 27:
  1028. reverse = 0;
  1029. break;
  1030. case 38: /* ANSI X3.64-1979 (SCO-ish?)
  1031.   * Enables underscore, white foreground
  1032.   * with white underscore (Linux - use
  1033.   * default foreground).
  1034.   */
  1035. color = (def_color & 0x0f) | background;
  1036. underline = 1;
  1037. break;
  1038. case 39: /* ANSI X3.64-1979 (SCO-ish?)
  1039.   * Disable underline option.
  1040.   * Reset colour to default? It did this
  1041.   * before...
  1042.   */
  1043. color = (def_color & 0x0f) | background;
  1044. underline = 0;
  1045. break;
  1046. case 49:
  1047. color = (def_color & 0xf0) | foreground;
  1048. break;
  1049. default:
  1050. if (par[i] >= 30 && par[i] <= 37)
  1051. color = color_table[par[i]-30]
  1052. | background;
  1053. else if (par[i] >= 40 && par[i] <= 47)
  1054. color = (color_table[par[i]-40]<<4)
  1055. | foreground;
  1056. break;
  1057. }
  1058. update_attr(currcons);
  1059. }
  1060. static void respond_string(const char * p, struct tty_struct * tty)
  1061. {
  1062. while (*p) {
  1063. tty_insert_flip_char(tty, *p, 0);
  1064. p++;
  1065. }
  1066. con_schedule_flip(tty);
  1067. }
  1068. static void cursor_report(int currcons, struct tty_struct * tty)
  1069. {
  1070. char buf[40];
  1071. sprintf(buf, "33[%d;%dR", y + (decom ? top+1 : 1), x+1);
  1072. respond_string(buf, tty);
  1073. }
  1074. static inline void status_report(struct tty_struct * tty)
  1075. {
  1076. respond_string("33[0n", tty); /* Terminal ok */
  1077. }
  1078. static inline void respond_ID(struct tty_struct * tty)
  1079. {
  1080. respond_string(VT102ID, tty);
  1081. }
  1082. void mouse_report(struct tty_struct * tty, int butt, int mrx, int mry)
  1083. {
  1084. char buf[8];
  1085. sprintf(buf, "33[M%c%c%c", (char)(' ' + butt), (char)('!' + mrx),
  1086. (char)('!' + mry));
  1087. respond_string(buf, tty);
  1088. }
  1089. /* invoked via ioctl(TIOCLINUX) and through set_selection */
  1090. int mouse_reporting(void)
  1091. {
  1092. int currcons = fg_console;
  1093. return report_mouse;
  1094. }
  1095. /* console_sem is held */
  1096. static void set_mode(int currcons, int on_off)
  1097. {
  1098. int i;
  1099. for (i=0; i<=npar; i++)
  1100. if (ques) switch(par[i]) { /* DEC private modes set/reset */
  1101. case 1: /* Cursor keys send ^[Ox/^[[x */
  1102. if (on_off)
  1103. set_kbd(decckm);
  1104. else
  1105. clr_kbd(decckm);
  1106. break;
  1107. case 3: /* 80/132 mode switch unimplemented */
  1108. deccolm = on_off;
  1109. #if 0
  1110. (void) vc_resize(video_num_lines, deccolm ? 132 : 80);
  1111. /* this alone does not suffice; some user mode
  1112.    utility has to change the hardware regs */
  1113. #endif
  1114. break;
  1115. case 5: /* Inverted screen on/off */
  1116. if (decscnm != on_off) {
  1117. decscnm = on_off;
  1118. invert_screen(currcons, 0, screenbuf_size, 0);
  1119. update_attr(currcons);
  1120. }
  1121. break;
  1122. case 6: /* Origin relative/absolute */
  1123. decom = on_off;
  1124. gotoxay(currcons,0,0);
  1125. break;
  1126. case 7: /* Autowrap on/off */
  1127. decawm = on_off;
  1128. break;
  1129. case 8: /* Autorepeat on/off */
  1130. if (on_off)
  1131. set_kbd(decarm);
  1132. else
  1133. clr_kbd(decarm);
  1134. break;
  1135. case 9:
  1136. report_mouse = on_off ? 1 : 0;
  1137. break;
  1138. case 25: /* Cursor on/off */
  1139. deccm = on_off;
  1140. break;
  1141. case 1000:
  1142. report_mouse = on_off ? 2 : 0;
  1143. break;
  1144. } else switch(par[i]) { /* ANSI modes set/reset */
  1145. case 3: /* Monitor (display ctrls) */
  1146. disp_ctrl = on_off;
  1147. break;
  1148. case 4: /* Insert Mode on/off */
  1149. decim = on_off;
  1150. break;
  1151. case 20: /* Lf, Enter == CrLf/Lf */
  1152. if (on_off)
  1153. set_kbd(lnm);
  1154. else
  1155. clr_kbd(lnm);
  1156. break;
  1157. }
  1158. }
  1159. /* console_sem is held */
  1160. static void setterm_command(int currcons)
  1161. {
  1162. switch(par[0]) {
  1163. case 1: /* set color for underline mode */
  1164. if (can_do_color && par[1] < 16) {
  1165. ulcolor = color_table[par[1]];
  1166. if (underline)
  1167. update_attr(currcons);
  1168. }
  1169. break;
  1170. case 2: /* set color for half intensity mode */
  1171. if (can_do_color && par[1] < 16) {
  1172. halfcolor = color_table[par[1]];
  1173. if (intensity == 0)
  1174. update_attr(currcons);
  1175. }
  1176. break;
  1177. case 8: /* store colors as defaults */
  1178. def_color = attr;
  1179. if (hi_font_mask == 0x100)
  1180. def_color >>= 1;
  1181. default_attr(currcons);
  1182. update_attr(currcons);
  1183. break;
  1184. case 9: /* set blanking interval */
  1185. #ifdef CONFIG_CONSOLE_PM // bushi
  1186. blankinterval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ;
  1187. poke_blanked_console();
  1188. #endif
  1189. break;
  1190. case 10: /* set bell frequency in Hz */
  1191. if (npar >= 1)
  1192. bell_pitch = par[1];
  1193. else
  1194. bell_pitch = DEFAULT_BELL_PITCH;
  1195. break;
  1196. case 11: /* set bell duration in msec */
  1197. if (npar >= 1)
  1198. bell_duration = (par[1] < 2000) ?
  1199. par[1]*HZ/1000 : 0;
  1200. else
  1201. bell_duration = DEFAULT_BELL_DURATION;
  1202. break;
  1203. case 12: /* bring specified console to the front */
  1204. if (par[1] >= 1 && vc_cons_allocated(par[1]-1))
  1205. set_console(par[1] - 1);
  1206. break;
  1207. case 13: /* unblank the screen */
  1208. #ifdef CONFIG_CONSOLE_PM // bushi
  1209. poke_blanked_console();
  1210. #endif
  1211. break;
  1212. case 14: /* set vesa powerdown interval */
  1213. #ifdef CONFIG_CONSOLE_PM // bushi
  1214. vesa_off_interval = ((par[1] < 60) ? par[1] : 60) * 60 * HZ;
  1215. #endif
  1216. break;
  1217. }
  1218. }
  1219. /* console_sem is held */
  1220. static void csi_at(int currcons, unsigned int nr)
  1221. {
  1222. if (nr > video_num_columns - x)
  1223. nr = video_num_columns - x;
  1224. else if (!nr)
  1225. nr = 1;
  1226. insert_char(currcons, nr);
  1227. }
  1228. /* console_sem is held */
  1229. static void csi_L(int currcons, unsigned int nr)
  1230. {
  1231. if (nr > video_num_lines - y)
  1232. nr = video_num_lines - y;
  1233. else if (!nr)
  1234. nr = 1;
  1235. scrdown(currcons,y,bottom,nr);
  1236. need_wrap = 0;
  1237. }
  1238. /* console_sem is held */
  1239. static void csi_P(int currcons, unsigned int nr)
  1240. {
  1241. if (nr > video_num_columns - x)
  1242. nr = video_num_columns - x;
  1243. else if (!nr)
  1244. nr = 1;
  1245. delete_char(currcons, nr);
  1246. }
  1247. /* console_sem is held */
  1248. static void csi_M(int currcons, unsigned int nr)
  1249. {
  1250. if (nr > video_num_lines - y)
  1251. nr = video_num_lines - y;
  1252. else if (!nr)
  1253. nr=1;
  1254. scrup(currcons,y,bottom,nr);
  1255. need_wrap = 0;
  1256. }
  1257. /* console_sem is held (except via vc_init->reset_terminal */
  1258. static void save_cur(int currcons)
  1259. {
  1260. saved_x = x;
  1261. saved_y = y;
  1262. s_intensity = intensity;
  1263. s_underline = underline;
  1264. s_blink = blink;
  1265. s_reverse = reverse;
  1266. s_charset = charset;
  1267. s_color = color;
  1268. saved_G0 = G0_charset;
  1269. saved_G1 = G1_charset;
  1270. }
  1271. /* console_sem is held */
  1272. static void restore_cur(int currcons)
  1273. {
  1274. gotoxy(currcons,saved_x,saved_y);
  1275. intensity = s_intensity;
  1276. underline = s_underline;
  1277. blink = s_blink;
  1278. reverse = s_reverse;
  1279. charset = s_charset;
  1280. color = s_color;
  1281. G0_charset = saved_G0;
  1282. G1_charset = saved_G1;
  1283. translate = set_translate(charset ? G1_charset : G0_charset,currcons);
  1284. update_attr(currcons);
  1285. need_wrap = 0;
  1286. }
  1287. static int con_write_ctrl_ESnormal(int, struct tty_struct *, unsigned int);
  1288. static int con_write_ctrl_ESesc(int, struct tty_struct *, unsigned int);
  1289. static int con_write_ctrl_ESnonstd(int, struct tty_struct *, unsigned int);
  1290. static int con_write_ctrl_ESpalette(int, struct tty_struct *, unsigned int);
  1291. static int con_write_ctrl_ESsquare(int, struct tty_struct *, unsigned int);
  1292. static int con_write_ctrl_ESgetpars(int, struct tty_struct *, unsigned int);
  1293. static int con_write_ctrl_ESgotpars(int, struct tty_struct *, unsigned int);
  1294. static int con_write_ctrl_ESpercent(int, struct tty_struct *, unsigned int);
  1295. static int con_write_ctrl_ESfunckey(int, struct tty_struct *, unsigned int);
  1296. static int con_write_ctrl_EShash(int, struct tty_struct *, unsigned int);
  1297. static int con_write_ctrl_ESsetG0(int, struct tty_struct *, unsigned int);
  1298. static int con_write_ctrl_ESsetG1(int, struct tty_struct *, unsigned int);
  1299. enum { ESnormal, ESesc, ESsquare, ESgetpars, ESgotpars, ESfunckey,
  1300. EShash, ESsetG0, ESsetG1, ESpercent, ESignore, ESnonstd,
  1301. ESpalette };
  1302. /* console_sem is held (except via vc_init()) */
  1303. static void reset_terminal(int currcons, int do_clear)
  1304. {
  1305. top = 0;
  1306. bottom = video_num_lines;
  1307. vc_state = con_write_ctrl_ESnormal;
  1308. ques = 0;
  1309. translate = set_translate(LAT1_MAP,currcons);
  1310. G0_charset = LAT1_MAP;
  1311. G1_charset = GRAF_MAP;
  1312. charset = 0;
  1313. need_wrap = 0;
  1314. report_mouse = 0;
  1315. utf             = 0;
  1316. utf_count       = 0;
  1317. disp_ctrl = 0;
  1318. toggle_meta = 0;
  1319. decscnm = 0;
  1320. decom = 0;
  1321. decawm = 1;
  1322. deccm = 1;
  1323. decim = 0;
  1324. set_kbd(decarm);
  1325. clr_kbd(decckm);
  1326. clr_kbd(kbdapplic);
  1327. clr_kbd(lnm);
  1328. kbd_table[currcons].lockstate = 0;
  1329. kbd_table[currcons].slockstate = 0;
  1330. kbd_table[currcons].ledmode = LED_SHOW_FLAGS;
  1331. kbd_table[currcons].ledflagstate = kbd_table[currcons].default_ledflagstate;
  1332. set_leds();
  1333. cursor_type = CUR_DEFAULT;
  1334. complement_mask = s_complement_mask;
  1335. default_attr(currcons);
  1336. update_attr(currcons);
  1337. tab_stop[0] = 0x01010100;
  1338. tab_stop[1] =
  1339. tab_stop[2] =
  1340. tab_stop[3] =
  1341. tab_stop[4] = 0x01010101;
  1342. bell_pitch = DEFAULT_BELL_PITCH;
  1343. bell_duration = DEFAULT_BELL_DURATION;
  1344. gotoxy(currcons,0,0);
  1345. save_cur(currcons);
  1346. if (do_clear)
  1347.     csi_J(currcons,2);
  1348. }
  1349. /* console_sem is held */
  1350. static void do_con_trol(struct tty_struct *tty, unsigned int currcons, int c)
  1351. {
  1352. /*
  1353.  *  Control characters can be used in the _middle_
  1354.  *  of an escape sequence.
  1355.  */
  1356. switch (c) {
  1357. case 0:
  1358. return;
  1359. case 7:
  1360. if (bell_duration)
  1361. kd_mksound(bell_pitch, bell_duration);
  1362. return;
  1363. case 8:
  1364. bs(currcons);
  1365. return;
  1366. case 9:
  1367. pos -= (x << 1);
  1368. while (x < video_num_columns - 1) {
  1369. x++;
  1370. if (tab_stop[x >> 5] & (1 << (x & 31)))
  1371. break;
  1372. }
  1373. pos += (x << 1);
  1374. return;
  1375. case 10: case 11: case 12:
  1376. lf(currcons);
  1377. if (!is_kbd(lnm))
  1378. return;
  1379. case 13:
  1380. cr(currcons);
  1381. return;
  1382. case 14:
  1383. charset = 1;
  1384. translate = set_translate(G1_charset,currcons);
  1385. disp_ctrl = 1;
  1386. return;
  1387. case 15:
  1388. charset = 0;
  1389. translate = set_translate(G0_charset,currcons);
  1390. disp_ctrl = 0;
  1391. return;
  1392. case 24: case 26:
  1393. vc_state = con_write_ctrl_ESnormal;
  1394. return;
  1395. case 27:
  1396. vc_state = con_write_ctrl_ESesc;
  1397. return;
  1398. case 127:
  1399. del(currcons);
  1400. return;
  1401. case 128+27:
  1402. vc_state = con_write_ctrl_ESsquare;
  1403. return;
  1404. }
  1405. vc_state(currcons, tty, c);
  1406. }
  1407. static int con_write_utf(int currcons, int c)
  1408. {
  1409. unsigned int chr;
  1410. /* Combine UTF-8 into Unicode */
  1411. /* Incomplete characters silently ignored */
  1412. if (c < 0x80) {
  1413. utf_count = 0;
  1414. return c;
  1415. }
  1416. if (utf_count > 0 && (c & 0xc0) == 0x80) {
  1417. chr = (utf_char << 6) | (c & 0x3f);
  1418. utf_count--;
  1419. if (utf_count == 0)
  1420. return chr;
  1421. } else {
  1422. unsigned int count;
  1423. if ((c & 0xe0) == 0xc0) {
  1424. count = 1;
  1425. chr = (c & 0x1f);
  1426. } else if ((c & 0xf0) == 0xe0) {
  1427. count = 2;
  1428. chr = (c & 0x0f);
  1429. } else if ((c & 0xf8) == 0xf0) {
  1430. count = 3;
  1431. chr = (c & 0x07);
  1432. } else if ((c & 0xfc) == 0xf8) {
  1433. count = 4;
  1434. chr = (c & 0x03);
  1435. } else if ((c & 0xfe) == 0xfc) {
  1436. count = 5;
  1437. chr = (c & 0x01);
  1438. } else {
  1439. count = 0;
  1440. chr = 0;
  1441. }
  1442. utf_count = count;
  1443. }
  1444. utf_char = chr;
  1445. return -1;
  1446. }
  1447. static int con_write_ctrl_ESnormal(int currcons, struct tty_struct *tty, unsigned int c)
  1448. {
  1449. return 0;
  1450. }
  1451. static int con_write_ctrl_ESesc(int currcons, struct tty_struct *tty, unsigned int c)
  1452. {
  1453. vc_state = con_write_ctrl_ESnormal;
  1454. switch (c) {
  1455. case '[':
  1456. vc_state = con_write_ctrl_ESsquare;
  1457. break;
  1458. case ']':
  1459. vc_state = con_write_ctrl_ESnonstd;
  1460. break;
  1461. case '%':
  1462. vc_state = con_write_ctrl_ESpercent;
  1463. break;
  1464. case 'E':
  1465. cr(currcons);
  1466. lf(currcons);
  1467. break;
  1468. case 'M':
  1469. ri(currcons);
  1470. break;
  1471. case 'D':
  1472. lf(currcons);
  1473. break;
  1474. case 'H':
  1475. tab_stop[x >> 5] |= (1 << (x & 31));
  1476. break;
  1477. case 'Z':
  1478. respond_ID(tty);
  1479. break;
  1480. case '7':
  1481. save_cur(currcons);
  1482. break;
  1483. case '8':
  1484. restore_cur(currcons);
  1485. return 1;
  1486. case '(':
  1487. vc_state = con_write_ctrl_ESsetG0;
  1488. break;
  1489. case ')':
  1490. vc_state = con_write_ctrl_ESsetG1;
  1491. break;
  1492. case '#':
  1493. vc_state = con_write_ctrl_EShash;
  1494. break;
  1495. case 'c':
  1496. reset_terminal(currcons,1);
  1497. return 1;
  1498. case '>':  /* Numeric keypad */
  1499. clr_kbd(kbdapplic);
  1500. break;
  1501. case '=':  /* Appl. keypad */
  1502. set_kbd(kbdapplic);
  1503.   break;
  1504. }
  1505. return 0;
  1506. }
  1507. static int con_write_ctrl_ESnonstd(int currcons, struct tty_struct *tty, unsigned int c)
  1508. {
  1509. switch (c) {
  1510. case 'P': /* palette escape sequence */
  1511. for (npar=0; npar<NPAR; npar++)
  1512. par[npar] = 0 ;
  1513. npar = 0 ;
  1514. vc_state = con_write_ctrl_ESpalette;
  1515. break;
  1516. case 'R': /* reset palette */
  1517. reset_palette (currcons);
  1518. default:
  1519. vc_state = con_write_ctrl_ESnormal;
  1520. }
  1521. return 0;
  1522. }
  1523. static int con_write_ctrl_ESpalette(int currcons, struct tty_struct *tty, unsigned int c)
  1524. {
  1525. if ( (c>='0'&&c<='9') || (c>='A'&&c<='F') || (c>='a'&&c<='f') ) {
  1526. par[npar++] = (c>'9' ? (c&0xDF)-'A'+10 : c-'0') ;
  1527. if (npar==7) {
  1528. int i = par[0]*3, j = 1;
  1529. palette[i] = 16*par[j++];
  1530. palette[i++] += par[j++];
  1531. palette[i] = 16*par[j++];
  1532. palette[i++] += par[j++];
  1533. palette[i] = 16*par[j++];
  1534. palette[i] += par[j];
  1535. set_palette(currcons);
  1536. vc_state = con_write_ctrl_ESnormal;
  1537. }
  1538. } else
  1539. vc_state = con_write_ctrl_ESnormal;
  1540. return 0;
  1541. }
  1542. static int con_write_ctrl_ESsquare(int currcons, struct tty_struct *tty, unsigned int c)
  1543. {
  1544. for(npar = 0 ; npar < NPAR ; npar++)
  1545. par[npar] = 0;
  1546. npar = 0;
  1547. vc_state = con_write_ctrl_ESgetpars;
  1548. if (c == '[') { /* Function key */
  1549. vc_state = con_write_ctrl_ESfunckey;
  1550. return 0;
  1551. }
  1552. ques = (c=='?');
  1553. if (ques)
  1554. return 0;
  1555. return con_write_ctrl_ESgetpars(currcons, tty, c);
  1556. }
  1557. static int con_write_ctrl_ESgetpars(int currcons, struct tty_struct *tty, unsigned int c)
  1558. {
  1559. if (c==';' && npar<NPAR-1) {
  1560. npar++;
  1561. return 0;
  1562. } else if (c>='0' && c<='9') {
  1563. par[npar] *= 10;
  1564. par[npar] += c-'0';
  1565. return 0;
  1566. } else vc_state = con_write_ctrl_ESgotpars;
  1567. return con_write_ctrl_ESgotpars(currcons, tty, c);
  1568. }
  1569. static int con_write_ctrl_ESgotpars(int currcons, struct tty_struct *tty, unsigned int c)
  1570. {
  1571. vc_state = con_write_ctrl_ESnormal;
  1572. switch(c) {
  1573. case 'h':
  1574. set_mode(currcons,1);
  1575. return 0;
  1576. case 'l':
  1577. set_mode(currcons,0);
  1578. return 0;
  1579. case 'c':
  1580. if (ques) {
  1581. if (par[0])
  1582. cursor_type = par[0] | (par[1]<<8) | (par[2]<<16);
  1583. else
  1584. cursor_type = CUR_DEFAULT;
  1585. return 0;
  1586. }
  1587. break;
  1588. case 'm':
  1589. if (ques) {
  1590. clear_selection();
  1591. if (par[0])
  1592. complement_mask = par[0]<<8 | par[1];
  1593. else
  1594. complement_mask = s_complement_mask;
  1595. return 0;
  1596. }
  1597. break;
  1598. case 'n':
  1599. if (!ques) {
  1600. if (par[0] == 5)
  1601. status_report(tty);
  1602. else if (par[0] == 6)
  1603. cursor_report(currcons,tty);
  1604. }
  1605. return 0;
  1606. }
  1607. if (ques) {
  1608. ques = 0;
  1609. return 0;
  1610. }
  1611. switch(c) {
  1612. case 'G': case '`':
  1613. if (par[0]) par[0]--;
  1614. gotoxy(currcons,par[0],y);
  1615. break;
  1616. case 'A':
  1617. if (!par[0]) par[0]++;
  1618. gotoxy(currcons,x,y-par[0]);
  1619. break;
  1620. case 'B': case 'e':
  1621. if (!par[0]) par[0]++;
  1622. gotoxy(currcons,x,y+par[0]);
  1623. break;
  1624. case 'C': case 'a':
  1625. if (!par[0]) par[0]++;
  1626. gotoxy(currcons,x+par[0],y);
  1627. break;
  1628. case 'D':
  1629. if (!par[0]) par[0]++;
  1630. gotoxy(currcons,x-par[0],y);
  1631. break;
  1632. case 'E':
  1633. if (!par[0]) par[0]++;
  1634. gotoxy(currcons,0,y+par[0]);
  1635. break;
  1636. case 'F':
  1637. if (!par[0]) par[0]++;
  1638. gotoxy(currcons,0,y-par[0]);
  1639. break;
  1640. case 'd':
  1641. if (par[0]) par[0]--;
  1642. gotoxay(currcons,x,par[0]);
  1643. break;
  1644. case 'H': case 'f':
  1645. if (par[0]) par[0]--;
  1646. if (par[1]) par[1]--;
  1647. gotoxay(currcons,par[1],par[0]);
  1648. break;
  1649. case 'J':
  1650. csi_J(currcons,par[0]);
  1651. break;
  1652. case 'K':
  1653. csi_K(currcons,par[0]);
  1654. break;
  1655. case 'L':
  1656. csi_L(currcons,par[0]);
  1657. break;
  1658. case 'M':
  1659. csi_M(currcons,par[0]);
  1660. break;
  1661. case 'P':
  1662. csi_P(currcons,par[0]);
  1663. break;
  1664. case 'c':
  1665. if (!par[0])
  1666. respond_ID(tty);
  1667. break;
  1668. case 'g':
  1669. if (!par[0])
  1670. tab_stop[x >> 5] &= ~(1 << (x & 31));
  1671. else if (par[0] == 3) {
  1672. tab_stop[0] =
  1673. tab_stop[1] =
  1674. tab_stop[2] =
  1675. tab_stop[3] =
  1676. tab_stop[4] = 0;
  1677. }
  1678. break;
  1679. case 'm':
  1680. csi_m(currcons);
  1681. return 1;
  1682. case 'q': /* DECLL - but only 3 leds */
  1683. /* map 0,1,2,3 to 0,1,2,4 */
  1684. if (par[0] < 4)
  1685.   setledstate(kbd_table + currcons,
  1686.       (par[0] < 3) ? par[0] : 4);
  1687. break;
  1688. case 'r':
  1689. if (!par[0])
  1690. par[0]++;
  1691. if (!par[1])
  1692. par[1] = video_num_lines;
  1693. /* Minimum allowed region is 2 lines */
  1694. if (par[0] < par[1] &&
  1695.     par[1] <= video_num_lines) {
  1696. top=par[0]-1;
  1697. bottom=par[1];
  1698. gotoxay(currcons,0,0);
  1699. }
  1700. break;
  1701. case 's':
  1702. save_cur(currcons);
  1703. break;
  1704. case 'u':
  1705. restore_cur(currcons);
  1706. return 1;
  1707. case 'X':
  1708. csi_X(currcons, par[0]);
  1709. break;
  1710. case '@':
  1711. csi_at(currcons,par[0]);
  1712. break;
  1713. case ']': /* setterm functions */
  1714. setterm_command(currcons);
  1715. break;
  1716. }
  1717. return 0;
  1718. }
  1719. static int con_write_ctrl_ESpercent(int currcons, struct tty_struct *tty, unsigned int c)
  1720. {
  1721. vc_state = con_write_ctrl_ESnormal;
  1722. switch (c) {
  1723. case '@':  /* defined in ISO 2022 */
  1724. utf = 0;
  1725. break;
  1726. case 'G':  /* prelim official escape code */
  1727. case '8':  /* retained for compatibility */
  1728. utf = 1;
  1729. break;
  1730. }
  1731. return 0;
  1732. }
  1733. static int con_write_ctrl_ESfunckey(int currcons, struct tty_struct *tty, unsigned int c)
  1734. {
  1735. vc_state = con_write_ctrl_ESnormal;
  1736. return 0;
  1737. }
  1738. static int con_write_ctrl_EShash(int currcons, struct tty_struct *tty, unsigned int c)
  1739. {
  1740. vc_state = con_write_ctrl_ESnormal;
  1741. if (c == '8') {
  1742. /* DEC screen alignment test. kludge :-) */
  1743. video_erase_char =
  1744. (video_erase_char & 0xff00) | 'E';
  1745. csi_J(currcons, 2);
  1746. video_erase_char =
  1747. (video_erase_char & 0xff00) | ' ';
  1748. do_update_region(currcons, origin, screenbuf_size/2);
  1749. }
  1750. return 0;
  1751. }
  1752. static int con_write_ctrl_ESsetG0(int currcons, struct tty_struct *tty, unsigned int c)
  1753. {
  1754. switch (c) {
  1755. case '0':
  1756. G0_charset = GRAF_MAP;
  1757. break;
  1758. case 'B':
  1759. G0_charset = LAT1_MAP;
  1760. break;
  1761. case 'U':
  1762. G0_charset = IBMPC_MAP;
  1763. break;
  1764. case 'K':
  1765. G0_charset = USER_MAP;
  1766. break;
  1767. }
  1768. if (charset == 0) {
  1769. translate = set_translate(G0_charset,currcons);
  1770. return 1;
  1771. }
  1772. vc_state = con_write_ctrl_ESnormal;
  1773. return 0;
  1774. }
  1775. static int con_write_ctrl_ESsetG1(int currcons, struct tty_struct *tty, unsigned int c)
  1776. {
  1777. switch (c) {
  1778. case '0':
  1779. G1_charset = GRAF_MAP;
  1780. break;
  1781. case 'B':
  1782. G1_charset = LAT1_MAP;
  1783. break;
  1784. case 'U':
  1785. G1_charset = IBMPC_MAP;
  1786. break;
  1787. case 'K':
  1788. G1_charset = USER_MAP;
  1789. break;
  1790. }
  1791. if (charset == 1) {
  1792. translate = set_translate(G1_charset,currcons);
  1793. return 1;
  1794. }
  1795. vc_state = con_write_ctrl_ESnormal;
  1796. return 0;
  1797. }
  1798. /* This is a temporary buffer used to prepare a tty console write
  1799.  * so that we can easily avoid touching user space while holding the
  1800.  * console spinlock.  It is allocated in con_init and is shared by
  1801.  * this code and the vc_screen read/write tty calls.
  1802.  *
  1803.  * We have to allocate this statically in the kernel data section
  1804.  * since console_init (and thus con_init) are called before any
  1805.  * kernel memory allocation is available.
  1806.  */
  1807. char con_buf[PAGE_SIZE];
  1808. #define CON_BUF_SIZE PAGE_SIZE
  1809. DECLARE_MUTEX(con_buf_sem);
  1810. /* acquires console_sem */
  1811. static int do_con_write(struct tty_struct * tty, int from_user,
  1812. const unsigned char *buf, int count)
  1813. {
  1814. #ifdef VT_BUF_VRAM_ONLY
  1815. #define FLUSH do { } while(0);
  1816. #else
  1817. #define FLUSH if (draw_x >= 0) { 
  1818. sw->con_putcs(vc_cons[currcons].d, (u16 *)draw_from, (u16 *)draw_to-(u16 *)draw_from, y, draw_x); 
  1819. draw_x = -1; 
  1820. }
  1821. #endif
  1822. int c, tc, ok, n = 0, draw_x = -1;
  1823. unsigned int currcons;
  1824. unsigned long draw_from = 0, draw_to = 0;
  1825. struct vt_struct *vt = (struct vt_struct *)tty->driver_data;
  1826. u16 himask, charmask;
  1827. const unsigned char *orig_buf;
  1828. int orig_count;
  1829. if (in_interrupt())
  1830. return count;
  1831. currcons = vt->vc_num;
  1832. if (!vc_cons_allocated(currcons)) {
  1833.     /* could this happen? */
  1834.     static int error = 0;
  1835.     if (!error) {
  1836. error = 1;
  1837. printk("con_write: tty %d not allocatedn", currcons+1);
  1838.     }
  1839.     return 0;
  1840. }
  1841. orig_buf = buf;
  1842. orig_count = count;
  1843. if (from_user) {
  1844. down(&con_buf_sem);
  1845. again:
  1846. if (count > CON_BUF_SIZE)
  1847. count = CON_BUF_SIZE;
  1848. console_conditional_schedule();
  1849. if (copy_from_user(con_buf, buf, count)) {
  1850. n = 0; /* ?? are error codes legal here ?? */
  1851. goto out;
  1852. }
  1853. buf = con_buf;
  1854. }
  1855. /* At this point 'buf' is guarenteed to be a kernel buffer
  1856.  * and therefore no access to userspace (and therefore sleeping)
  1857.  * will be needed.  The con_buf_sem serializes all tty based
  1858.  * console rendering and vcs write/read operations.  We hold
  1859.  * the console spinlock during the entire write.
  1860.  */
  1861. acquire_console_sem();
  1862. himask = hi_font_mask;
  1863. charmask = himask ? 0x1ff : 0xff;
  1864. /* undraw cursor first */
  1865. if (IS_FG)
  1866. hide_cursor(currcons);
  1867. while (!tty->stopped && count) {
  1868. c = *buf;
  1869. buf++;
  1870. n++;
  1871. count--;
  1872. if (utf) {
  1873. tc = con_write_utf(currcons, c);
  1874. if (tc < 0)
  1875. continue;
  1876. c = tc;
  1877. } else /* no utf */
  1878. tc = translate[toggle_meta ? (c|0x80) : c];
  1879.                 /* If the original code was a control character we
  1880.                  * only allow a glyph to be displayed if the code is
  1881.                  * not normally used (such as for cursor movement) or
  1882.                  * if the disp_ctrl mode has been explicitly enabled.
  1883.                  * Certain characters (as given by the CTRL_ALWAYS
  1884.                  * bitmap) are always displayed as control characters,
  1885.                  * as the console would be pretty useless without
  1886.                  * them; to display an arbitrary font position use the
  1887.                  * direct-to-font zone in UTF-8 mode.
  1888.                  */
  1889.                 ok = tc && (c >= 32 ||
  1890.                             (!utf && !(((disp_ctrl ? CTRL_ALWAYS
  1891.                                          : CTRL_ACTION) >> c) & 1)))
  1892.                         && (c != 127 || disp_ctrl)
  1893. && (c != 128+27);
  1894. if (vc_state == con_write_ctrl_ESnormal && ok) {
  1895. /* Now try to find out how to display it */
  1896. tc = conv_uni_to_pc(vc_cons[currcons].d, tc);
  1897. if ( tc == -4 ) {
  1898.                                 /* If we got -4 (not found) then see if we have
  1899.                                    defined a replacement character (U+FFFD) */
  1900.                                 tc = conv_uni_to_pc(vc_cons[currcons].d, 0xfffd);
  1901. /* One reason for the -4 can be that we just
  1902.    did a clear_unimap();
  1903.    try at least to show something. */
  1904. if (tc == -4)
  1905.      tc = c;
  1906.                         } else if ( tc == -3 ) {
  1907.                                 /* Bad hash table -- hope for the best */
  1908.                                 tc = c;
  1909.                         }
  1910. if (tc & ~charmask)
  1911.                                 continue; /* Conversion failed */
  1912. if (need_wrap || decim)
  1913. FLUSH
  1914. if (need_wrap) {
  1915. cr(currcons);
  1916. lf(currcons);
  1917. }
  1918. if (decim)
  1919. insert_char(currcons, 1);
  1920. scr_writew(himask ?
  1921.      ((attr << 8) & ~himask) + ((tc & 0x100) ? himask : 0) + (tc & 0xff) :
  1922.      (attr << 8) + tc,
  1923.    (u16 *) pos);
  1924. if (DO_UPDATE && draw_x < 0) {
  1925. draw_x = x;
  1926. draw_from = pos;
  1927. }
  1928. if (x == video_num_columns - 1) {
  1929. need_wrap = decawm;
  1930. draw_to = pos+2;
  1931. } else {
  1932. x++;
  1933. draw_to = (pos+=2);
  1934. }
  1935. continue;
  1936. }
  1937. FLUSH
  1938. do_con_trol(tty, currcons, c);
  1939. }
  1940. FLUSH
  1941. console_conditional_schedule();
  1942. release_console_sem();
  1943. out:
  1944. if (from_user) {
  1945. /* If the user requested something larger than
  1946.  * the CON_BUF_SIZE, and the tty is not stopped,
  1947.  * keep going.
  1948.  */
  1949. if ((orig_count > CON_BUF_SIZE) && !tty->stopped) {
  1950. orig_count -= CON_BUF_SIZE;
  1951. orig_buf += CON_BUF_SIZE;
  1952. count = orig_count;
  1953. buf = orig_buf;
  1954. goto again;
  1955. }
  1956. up(&con_buf_sem);
  1957. }
  1958. return n;
  1959. #undef FLUSH
  1960. }
  1961. /*
  1962.  * This is the console switching callback.
  1963.  *
  1964.  * Doing console switching in a process context allows
  1965.  * us to do the switches asynchronously (needed when we want
  1966.  * to switch due to a keyboard interrupt).  Synchronization
  1967.  * with other console code and prevention of re-entrancy is
  1968.  * ensured with console_sem.
  1969.  */
  1970. static void console_callback(void *ignored)
  1971. {
  1972. acquire_console_sem();
  1973. if (want_console >= 0) {
  1974. if (want_console != fg_console && vc_cons_allocated(want_console)) {
  1975. hide_cursor(fg_console);
  1976. change_console(want_console);
  1977. /* we only changed when the console had already
  1978.    been allocated - a new console is not created
  1979.    in an interrupt routine */
  1980. }
  1981. want_console = -1;
  1982. }
  1983. #ifdef CONFIG_CONSOLE_PM // bushi
  1984. if (do_poke_blanked_console) { /* do not unblank for a LED change */
  1985. do_poke_blanked_console = 0;
  1986. poke_blanked_console();
  1987. }
  1988. #endif
  1989. if (scrollback_delta) {
  1990. int currcons = fg_console;
  1991. clear_selection();
  1992. if (vcmode == KD_TEXT)
  1993. sw->con_scrolldelta(vc_cons[currcons].d, scrollback_delta);
  1994. scrollback_delta = 0;
  1995. }
  1996. release_console_sem();
  1997. }
  1998. void set_console(int nr)
  1999. {
  2000. want_console = nr;
  2001. schedule_console_callback();
  2002. }
  2003. #ifdef CONFIG_VT_CONSOLE
  2004. /*
  2005.  * Console on virtual terminal
  2006.  *
  2007.  * The console must be locked when we get here.
  2008.  */
  2009. void vt_console_print(struct console *co, const char * b, unsigned count)
  2010. {
  2011. int currcons = fg_console;
  2012. unsigned char c;
  2013. static unsigned long printing;
  2014. const ushort *start;
  2015. ushort cnt = 0;
  2016. ushort myx;
  2017. /* console busy or not yet initialized */
  2018. if (!printable || test_and_set_bit(0, &printing))
  2019. return;
  2020. #ifdef CONFIG_CONSOLE_PM // bushi
  2021. pm_access(pm_con);
  2022. #endif
  2023. if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1))
  2024. currcons = kmsg_redirect - 1;
  2025. /* read `x' only after setting currcons properly (otherwise
  2026.    the `x' macro will read the x of the foreground console). */
  2027. myx = x;
  2028. if (!vc_cons_allocated(currcons)) {
  2029. /* impossible */
  2030. /* printk("vt_console_print: tty %d not allocated ??n", currcons+1); */
  2031. goto quit;
  2032. }
  2033. if (vcmode != KD_TEXT)
  2034. goto quit;
  2035. /* undraw cursor first */
  2036. if (IS_FG)
  2037. hide_cursor(currcons);
  2038. start = (ushort *)pos;
  2039. /* Contrived structure to try to emulate original need_wrap behaviour
  2040.  * Problems caused when we have need_wrap set on 'n' character */
  2041. while (count--) {
  2042. c = *b++;
  2043. if (c == 10 || c == 13 || c == 8 || need_wrap) {
  2044. if (cnt > 0) {
  2045. if (IS_VISIBLE)
  2046. sw->con_putcs(vc_cons[currcons].d, start, cnt, y, x);
  2047. x += cnt;
  2048. if (need_wrap)
  2049. x--;
  2050. cnt = 0;
  2051. }
  2052. if (c == 8) { /* backspace */
  2053. bs(currcons);
  2054. start = (ushort *)pos;
  2055. myx = x;
  2056. continue;
  2057. }
  2058. if (c != 13)
  2059. lf(currcons);
  2060. cr(currcons);
  2061. start = (ushort *)pos;
  2062. myx = x;
  2063. if (c == 10 || c == 13)
  2064. continue;
  2065. }
  2066. scr_writew((attr << 8) + c, (unsigned short *) pos);
  2067. cnt++;
  2068. if (myx == video_num_columns - 1) {
  2069. need_wrap = 1;
  2070. continue;
  2071. }
  2072. pos+=2;
  2073. myx++;
  2074. }
  2075. if (cnt > 0) {
  2076. if (IS_VISIBLE)
  2077. sw->con_putcs(vc_cons[currcons].d, start, cnt, y, x);
  2078. x += cnt;
  2079. if (x == video_num_columns) {
  2080. x--;
  2081. need_wrap = 1;
  2082. }
  2083. }
  2084. set_cursor(currcons);
  2085. #ifdef CONFIG_CONSOLE_PM // bushi
  2086. if (!oops_in_progress)
  2087. poke_blanked_console();
  2088. #endif
  2089. quit:
  2090. clear_bit(0, &printing);
  2091. }
  2092. static kdev_t vt_console_device(struct console *c)
  2093. {
  2094. return MKDEV(TTY_MAJOR, c->index ? c->index : fg_console + 1);
  2095. }
  2096. struct console vt_console_driver = {
  2097. name: "tty",
  2098. write: vt_console_print,
  2099. device: vt_console_device,
  2100. wait_key: keyboard_wait_for_keypress,
  2101. #ifdef CONFIG_CONSOLE_PM // bushi
  2102. unblank: unblank_screen,
  2103. #endif
  2104. flags: CON_PRINTBUFFER,
  2105. index: -1,
  2106. };
  2107. #endif
  2108. /*
  2109.  * Handling of Linux-specific VC ioctls
  2110.  */
  2111. /*
  2112.  * Generally a bit racy with respect to console_sem().
  2113.  *
  2114.  * There are some functions which don't need it.
  2115.  *
  2116.  * There are some functions which can sleep for arbitrary periods (paste_selection)
  2117.  * but we don't need the lock there anyway.
  2118.  *
  2119.  * set_selection has locking, and definitely needs it
  2120.  */
  2121. int tioclinux(struct tty_struct *tty, unsigned long arg)
  2122. {
  2123. char type, data;
  2124. int ret;
  2125. if (tty->driver.type != TTY_DRIVER_TYPE_CONSOLE)
  2126. return -EINVAL;
  2127. if (current->tty != tty && !capable(CAP_SYS_ADMIN))
  2128. return -EPERM;
  2129. if (get_user(type, (char *)arg))
  2130. return -EFAULT;
  2131. ret = 0;
  2132. switch (type)
  2133. {
  2134. case 2:
  2135. acquire_console_sem();
  2136. ret = set_selection(arg, tty, 1);
  2137. release_console_sem();
  2138. break;
  2139. case 3:
  2140. ret = paste_selection(tty);
  2141. break;
  2142. case 4:
  2143. #ifdef CONFIG_CONSOLE_PM // bushi
  2144. unblank_screen();
  2145. #endif
  2146. break;
  2147. case 5:
  2148. ret = sel_loadlut(arg);
  2149. break;
  2150. case 6:
  2151. /*
  2152.  * Make it possible to react to Shift+Mousebutton.
  2153.  * Note that 'shift_state' is an undocumented
  2154.  * kernel-internal variable; programs not closely
  2155.  * related to the kernel should not use this.
  2156.  */
  2157.   data = shift_state;
  2158. ret = __put_user(data, (char *) arg);
  2159. break;
  2160. case 7:
  2161. data = mouse_reporting();
  2162. ret = __put_user(data, (char *) arg);
  2163. break;
  2164. case 10:
  2165. #ifdef CONFIG_CONSOLE_PM //bushi
  2166. set_vesa_blanking(arg);
  2167. #endif
  2168. break;;
  2169. case 11: /* set kmsg redirect */
  2170. if (!capable(CAP_SYS_ADMIN)) {
  2171. ret = -EPERM;
  2172. } else {
  2173. if (get_user(data, (char *)arg+1))
  2174. ret = -EFAULT;
  2175. else
  2176. kmsg_redirect = data;
  2177. }
  2178. break;
  2179. case 12: /* get fg_console */
  2180. ret = fg_console;
  2181. break;
  2182. default:
  2183. ret = -EINVAL;
  2184. break;
  2185. }
  2186. return ret;
  2187. }
  2188. /*
  2189.  * /dev/ttyN handling
  2190.  */
  2191. static int con_write(struct tty_struct * tty, int from_user,
  2192.      const unsigned char *buf, int count)
  2193. {
  2194. int retval;
  2195. #ifdef CONFIG_CONSOLE_PM // bushi
  2196. pm_access(pm_con);
  2197. #endif
  2198. retval = do_con_write(tty, from_user, buf, count);
  2199. con_flush_chars(tty);
  2200. return retval;
  2201. }
  2202. static void con_put_char(struct tty_struct *tty, unsigned char ch)
  2203. {
  2204. if (in_interrupt())
  2205. return; /* n_r3964 calls put_char() from interrupt context */
  2206. #ifdef CONFIG_CONSOLE_PM // bushi
  2207. pm_access(pm_con);
  2208. #endif
  2209. do_con_write(tty, 0, &ch, 1);
  2210. }
  2211. static int con_write_room(struct tty_struct *tty)
  2212. {
  2213. if (tty->stopped)
  2214. return 0;
  2215. return 4096; /* No limit, really; we're not buffering */
  2216. }
  2217. static int con_chars_in_buffer(struct tty_struct *tty)
  2218. {
  2219. return 0; /* we're not buffering */
  2220. }
  2221. /*
  2222.  * con_throttle and con_unthrottle are only used for
  2223.  * paste_selection(), which has to stuff in a large number of
  2224.  * characters...
  2225.  */
  2226. static void con_throttle(struct tty_struct *tty)
  2227. {
  2228. }
  2229. static void con_unthrottle(struct tty_struct *tty)
  2230. {
  2231. struct vt_struct *vt = (struct vt_struct *) tty->driver_data;
  2232. wake_up_interruptible(&vt->paste_wait);
  2233. }
  2234. /*
  2235.  * Turn the Scroll-Lock LED on when the tty is stopped
  2236.  */
  2237. static void con_stop(struct tty_struct *tty)
  2238. {
  2239. int console_num;
  2240. if (!tty)
  2241. return;
  2242. console_num = MINOR(tty->device) - (tty->driver.minor_start);
  2243. if (!vc_cons_allocated(console_num))
  2244. return;
  2245. set_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK);
  2246. set_leds();
  2247. }
  2248. /*
  2249.  * Turn the Scroll-Lock LED off when the console is started
  2250.  */
  2251. static void con_start(struct tty_struct *tty)
  2252. {
  2253. int console_num;
  2254. if (!tty)
  2255. return;
  2256. console_num = MINOR(tty->device) - (tty->driver.minor_start);
  2257. if (!vc_cons_allocated(console_num))
  2258. return;
  2259. clr_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK);
  2260. set_leds();
  2261. }
  2262. /*
  2263.  * we can race here against con_close, so we grab the bkl
  2264.  * and check the pointer before calling set_cursor
  2265.  */
  2266. static void con_flush_chars(struct tty_struct *tty)
  2267. {
  2268. struct vt_struct *vt;
  2269. if (in_interrupt()) /* from flush_to_ldisc */
  2270. return;
  2271. #if 0
  2272. pm_access(pm_con);
  2273. #endif
  2274. lock_kernel();
  2275. acquire_console_sem();
  2276. vt = (struct vt_struct *)tty->driver_data;
  2277. if (vt)
  2278. set_cursor(vt->vc_num);
  2279. release_console_sem();
  2280. unlock_kernel();
  2281. }
  2282. /*
  2283.  * Allocate the console screen memory.
  2284.  */
  2285. static int con_open(struct tty_struct *tty, struct file * filp)
  2286. {
  2287. unsigned int currcons;
  2288. int i;
  2289. currcons = MINOR(tty->device) - tty->driver.minor_start;
  2290. i = vc_allocate(currcons);
  2291. if (i)
  2292. return i;
  2293. vt_cons[currcons]->vc_num = currcons;
  2294. tty->driver_data = vt_cons[currcons];
  2295. if (!tty->winsize.ws_row && !tty->winsize.ws_col) {
  2296. tty->winsize.ws_row = video_num_lines;
  2297. tty->winsize.ws_col = video_num_columns;
  2298. }
  2299. if (tty->count == 1)
  2300. vcs_make_devfs (currcons, 0);
  2301. return 0;
  2302. }
  2303. static void con_close(struct tty_struct *tty, struct file * filp)
  2304. {
  2305. if (!tty)
  2306. return;
  2307. if (tty->count != 1) return;
  2308. vcs_make_devfs (MINOR (tty->device) - tty->driver.minor_start, 1);
  2309. tty->driver_data = 0;
  2310. }
  2311. static void vc_init(unsigned int currcons, unsigned int rows, unsigned int cols, int do_clear)
  2312. {
  2313. int j, k ;
  2314. video_num_columns = cols;
  2315. video_num_lines = rows;
  2316. video_size_row = cols<<1;
  2317. screenbuf_size = video_num_lines * video_size_row;
  2318. set_origin(currcons);
  2319. pos = origin;
  2320. reset_vc(currcons);
  2321. for (j=k=0; j<16; j++) {
  2322. vc_cons[currcons].d->vc_palette[k++] = default_red[j] ;
  2323. vc_cons[currcons].d->vc_palette[k++] = default_grn[j] ;
  2324. vc_cons[currcons].d->vc_palette[k++] = default_blu[j] ;
  2325. }
  2326. def_color       = 0x07;   /* white */
  2327. ulcolor = 0x0f;   /* bold white */
  2328. halfcolor       = 0x08;   /* grey */
  2329. init_waitqueue_head(&vt_cons[currcons]->paste_wait);
  2330. reset_terminal(currcons, do_clear);
  2331. }
  2332. /*
  2333.  * This routine initializes console interrupts, and does nothing
  2334.  * else. If you want the screen to clear, call tty_write with
  2335.  * the appropriate escape-sequence.
  2336.  */
  2337. struct tty_driver console_driver;
  2338. static int console_refcount;
  2339. void __init con_init(void)
  2340. {
  2341. const char *display_desc = NULL;
  2342. unsigned int currcons = 0;
  2343. if (conswitchp)
  2344. display_desc = conswitchp->con_startup();
  2345. if (!display_desc) {
  2346. fg_console = 0;
  2347. return;
  2348. }
  2349. memset(&console_driver, 0, sizeof(struct tty_driver));
  2350. console_driver.magic = TTY_DRIVER_MAGIC;
  2351. console_driver.name = "vc/%d";
  2352. console_driver.name_base = 1;
  2353. console_driver.major = TTY_MAJOR;
  2354. console_driver.minor_start = 1;
  2355. console_driver.num = MAX_NR_CONSOLES;
  2356. console_driver.type = TTY_DRIVER_TYPE_CONSOLE;
  2357. console_driver.init_termios = tty_std_termios;
  2358. console_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS;
  2359. /* Tell tty_register_driver() to skip consoles because they are
  2360.  * registered before kmalloc() is ready. We'll patch them in later.
  2361.  * See comments at console_init(); see also con_init_devfs().
  2362.  */
  2363. console_driver.flags |= TTY_DRIVER_NO_DEVFS;
  2364. console_driver.refcount = &console_refcount;
  2365. console_driver.table = console_table;
  2366. console_driver.termios = console_termios;
  2367. console_driver.termios_locked = console_termios_locked;
  2368. console_driver.open = con_open;
  2369. console_driver.close = con_close;
  2370. console_driver.write = con_write;
  2371. console_driver.write_room = con_write_room;
  2372. console_driver.put_char = con_put_char;
  2373. console_driver.flush_chars = con_flush_chars;
  2374. console_driver.chars_in_buffer = con_chars_in_buffer;
  2375. console_driver.ioctl = vt_ioctl;
  2376. console_driver.stop = con_stop;
  2377. console_driver.start = con_start;
  2378. console_driver.throttle = con_throttle;
  2379. console_driver.unthrottle = con_unthrottle;
  2380. if (tty_register_driver(&console_driver))
  2381. panic("Couldn't register console drivern");
  2382. #ifdef CONFIG_CONSOLE_PM // bushi
  2383. init_timer(&console_timer);
  2384. console_timer.function = blank_screen;
  2385. if (blankinterval) {
  2386. mod_timer(&console_timer, jiffies + blankinterval);
  2387. }
  2388. #endif
  2389. /*
  2390.  * kmalloc is not running yet - we use the bootmem allocator.
  2391.  */
  2392. for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) {
  2393. vc_cons[currcons].d = (struct vc_data *)
  2394. alloc_bootmem(sizeof(struct vc_data));
  2395. vt_cons[currcons] = (struct vt_struct *)
  2396. alloc_bootmem(sizeof(struct vt_struct));
  2397. visual_init(currcons, 1);
  2398. screenbuf = (unsigned short *) alloc_bootmem(screenbuf_size);
  2399. kmalloced = 0;
  2400. vc_init(currcons, video_num_lines, video_num_columns, 
  2401. currcons || !sw->con_save_screen);
  2402. }
  2403. currcons = fg_console = 0;
  2404. master_display_fg = vc_cons[currcons].d;
  2405. set_origin(currcons);
  2406. save_screen(currcons);
  2407. gotoxy(currcons,x,y);
  2408. csi_J(currcons, 0);
  2409. update_screen(fg_console);
  2410. printk("Console: %s %s %dx%d",
  2411. can_do_color ? "colour" : "mono",
  2412. display_desc, video_num_columns, video_num_lines);
  2413. printable = 1;
  2414. printk("n");
  2415. #ifdef CONFIG_VT_CONSOLE
  2416. register_console(&vt_console_driver);
  2417. #endif
  2418. }
  2419. #ifndef VT_SINGLE_DRIVER
  2420. static void clear_buffer_attributes(int currcons)
  2421. {
  2422. unsigned short *p = (unsigned short *) origin;
  2423. int count = screenbuf_size/2;
  2424. int mask = hi_font_mask | 0xff;
  2425. for (; count > 0; count--, p++) {
  2426. scr_writew((scr_readw(p)&mask) | (video_erase_char&~mask), p);
  2427. }
  2428. }
  2429. /*
  2430.  * If we support more console drivers, this function is used
  2431.  * when a driver wants to take over some existing consoles
  2432.  * and become default driver for newly opened ones.
  2433.  */
  2434. void take_over_console(const struct consw *csw, int first, int last, int deflt)
  2435. {
  2436. int i, j = -1;
  2437. const char *desc;
  2438. desc = csw->con_startup();
  2439. if (!desc) return;
  2440. if (deflt)
  2441. conswitchp = csw;
  2442. for (i = first; i <= last; i++) {
  2443. int old_was_color;
  2444. int currcons = i;
  2445. con_driver_map[i] = csw;
  2446. if (!vc_cons[i].d || !vc_cons[i].d->vc_sw)
  2447. continue;
  2448. j = i;
  2449. if (IS_VISIBLE)
  2450. save_screen(i);
  2451. old_was_color = vc_cons[i].d->vc_can_do_color;
  2452. vc_cons[i].d->vc_sw->con_deinit(vc_cons[i].d);
  2453. visual_init(i, 0);
  2454. update_attr(i);
  2455. /* If the console changed between mono <-> color, then
  2456.  * the attributes in the screenbuf will be wrong.  The
  2457.  * following resets all attributes to something sane.
  2458.  */
  2459. if (old_was_color != vc_cons[i].d->vc_can_do_color)
  2460. clear_buffer_attributes(i);
  2461. if (IS_VISIBLE)
  2462. update_screen(i);
  2463. }
  2464. printk("Console: switching ");
  2465. if (!deflt)
  2466. printk("consoles %d-%d ", first+1, last+1);
  2467. if (j >= 0)
  2468. printk("to %s %s %dx%dn",
  2469.        vc_cons[j].d->vc_can_do_color ? "colour" : "mono",
  2470.        desc, vc_cons[j].d->vc_cols, vc_cons[j].d->vc_rows);
  2471. else
  2472. printk("to %sn", desc);
  2473. }
  2474. void give_up_console(const struct consw *csw)
  2475. {
  2476. int i;
  2477. for(i = 0; i < MAX_NR_CONSOLES; i++)
  2478. if (con_driver_map[i] == csw)
  2479. con_driver_map[i] = NULL;
  2480. }
  2481. #endif
  2482. #ifdef CONFIG_CONSOLE_PM // bushi
  2483. /*
  2484.  * Screen blanking
  2485.  */
  2486. static void set_vesa_blanking(unsigned long arg)
  2487. {
  2488. char *argp = (char *)arg + 1;
  2489. unsigned int mode;
  2490. if (get_user(mode, argp) == 0)
  2491. vesa_blank_mode = (mode < 4) ? mode : 0;
  2492. }
  2493. #endif // CONFIG_CONSOLE_PM
  2494. /* We can't register the console with devfs during con_init(), because it
  2495.  * is called before kmalloc() works.  This function is called later to
  2496.  * do the registration.
  2497.  */
  2498. void __init con_init_devfs (void)
  2499. {
  2500. int i;
  2501. for (i = 0; i < console_driver.num; i++)
  2502. tty_register_devfs (&console_driver, DEVFS_FL_AOPEN_NOTIFY,
  2503.     console_driver.minor_start + i);
  2504. }
  2505. #ifdef CONFIG_CONSOLE_PM // bushi
  2506. /*
  2507.  * This is called by a timer handler
  2508.  */
  2509. static void vesa_powerdown(void)
  2510. {
  2511.     struct vc_data *c = vc_cons[fg_console].d;
  2512.     /*
  2513.      *  Power down if currently suspended (1 or 2),
  2514.      *  suspend if currently blanked (0),
  2515.      *  else do nothing (i.e. already powered down (3)).
  2516.      *  Called only if powerdown features are allowed.
  2517.      */
  2518.     switch (vesa_blank_mode) {
  2519. case VESA_NO_BLANKING:
  2520.     c->vc_sw->con_blank(c, VESA_VSYNC_SUSPEND+1);
  2521.     break;
  2522. case VESA_VSYNC_SUSPEND:
  2523. case VESA_HSYNC_SUSPEND:
  2524.     c->vc_sw->con_blank(c, VESA_POWERDOWN+1);
  2525.     break;
  2526.     }
  2527. }
  2528. /*
  2529.  * This is a timer handler
  2530.  */
  2531. static void vesa_powerdown_screen(unsigned long dummy)
  2532. {
  2533. console_timer.function = unblank_screen_t;
  2534. vesa_powerdown();
  2535. }
  2536. static void timer_do_blank_screen(int entering_gfx, int from_timer_handler)
  2537. {
  2538. int currcons = fg_console;
  2539. int i;
  2540. if (console_blanked)
  2541. return;
  2542. /* entering graphics mode? */
  2543. if (entering_gfx) {
  2544. hide_cursor(currcons);
  2545. save_screen(currcons);
  2546. sw->con_blank(vc_cons[currcons].d, -1);
  2547. console_blanked = fg_console + 1;
  2548. set_origin(currcons);
  2549. return;
  2550. }
  2551. /* don't blank graphics */
  2552. if (vcmode != KD_TEXT) {
  2553. console_blanked = fg_console + 1;
  2554. return;
  2555. }
  2556. hide_cursor(currcons);
  2557. if (!from_timer_handler)
  2558. del_timer_sync(&console_timer);
  2559. if (vesa_off_interval) {
  2560. console_timer.function = vesa_powerdown_screen;
  2561. mod_timer(&console_timer, jiffies + vesa_off_interval);
  2562. } else {
  2563. if (!from_timer_handler)
  2564. del_timer_sync(&console_timer);
  2565. console_timer.function = unblank_screen_t;
  2566. }
  2567. save_screen(currcons);
  2568. /* In case we need to reset origin, blanking hook returns 1 */
  2569. i = sw->con_blank(vc_cons[currcons].d, 1);
  2570. console_blanked = fg_console + 1;
  2571. if (i)
  2572. set_origin(currcons);
  2573. if (console_blank_hook && console_blank_hook(1))
  2574. return;
  2575. if (vesa_blank_mode)
  2576. sw->con_blank(vc_cons[currcons].d, vesa_blank_mode + 1);
  2577. }
  2578. void do_blank_screen(int entering_gfx)
  2579. {
  2580. timer_do_blank_screen(entering_gfx, 0);
  2581. }
  2582. /*
  2583.  * This is a timer handler
  2584.  */
  2585. static void unblank_screen_t(unsigned long dummy)
  2586. {
  2587. unblank_screen();
  2588. }
  2589. /*
  2590.  * Called by timer as well as from vt_console_driver
  2591.  */
  2592. void unblank_screen(void)
  2593. {
  2594. int currcons;
  2595. if (!console_blanked)
  2596. return;
  2597. if (!vc_cons_allocated(fg_console)) {
  2598. /* impossible */
  2599. printk("unblank_screen: tty %d not allocated ??n", fg_console+1);
  2600. return;
  2601. }
  2602. currcons = fg_console;
  2603. if (vcmode != KD_TEXT)
  2604. return; /* but leave console_blanked != 0 */
  2605. console_timer.function = blank_screen;
  2606. if (blankinterval) {
  2607. mod_timer(&console_timer, jiffies + blankinterval);
  2608. }
  2609. console_blanked = 0;
  2610. if (console_blank_hook)
  2611. console_blank_hook(0);
  2612. set_palette(currcons);
  2613. if (sw->con_blank(vc_cons[currcons].d, 0))
  2614. /* Low-level driver cannot restore -> do it ourselves */
  2615. update_screen(fg_console);
  2616. set_cursor(fg_console);
  2617. }
  2618. /*
  2619.  * This is both a user-level callable and a timer handler
  2620.  */
  2621. static void blank_screen(unsigned long dummy)
  2622. {
  2623. timer_do_blank_screen(0, 1);
  2624. }
  2625. void poke_blanked_console(void)
  2626. {
  2627. del_timer(&console_timer);
  2628. if (!vt_cons[fg_console] || vt_cons[fg_console]->vc_mode == KD_GRAPHICS)
  2629. return;
  2630. if (console_blanked) {
  2631. console_timer.function = unblank_screen_t;
  2632. mod_timer(&console_timer, jiffies); /* Now */
  2633. } else if (blankinterval) {
  2634. mod_timer(&console_timer, jiffies + blankinterval);
  2635. }
  2636. }
  2637. #endif // CONFIG_CONSOLE_PM - bushi
  2638. /*
  2639.  * Palettes
  2640.  */
  2641. void set_palette(int currcons)
  2642. {
  2643. if (vcmode != KD_GRAPHICS)
  2644. sw->con_set_palette(vc_cons[currcons].d, color_table);
  2645. }
  2646. static int set_get_cmap(unsigned char *arg, int set)
  2647. {
  2648.     int i, j, k;
  2649.     for (i = 0; i < 16; i++)
  2650. if (set) {
  2651.     get_user(default_red[i], arg++);
  2652.     get_user(default_grn[i], arg++);
  2653.     get_user(default_blu[i], arg++);
  2654. } else {
  2655.     put_user(default_red[i], arg++);
  2656.     put_user(default_grn[i], arg++);
  2657.     put_user(default_blu[i], arg++);
  2658. }
  2659.     if (set) {
  2660. for (i = 0; i < MAX_NR_CONSOLES; i++)
  2661.     if (vc_cons_allocated(i)) {
  2662. for (j = k = 0; j < 16; j++) {
  2663.     vc_cons[i].d->vc_palette[k++] = default_red[j];
  2664.     vc_cons[i].d->vc_palette[k++] = default_grn[j];
  2665.     vc_cons[i].d->vc_palette[k++] = default_blu[j];
  2666. }
  2667. set_palette(i);
  2668.     }
  2669.     }
  2670.     return 0;
  2671. }
  2672. /*
  2673.  * Load palette into the DAC registers. arg points to a colour
  2674.  * map, 3 bytes per colour, 16 colours, range from 0 to 255.
  2675.  */
  2676. int con_set_cmap(unsigned char *arg)
  2677. {
  2678. return set_get_cmap (arg,1);
  2679. }
  2680. int con_get_cmap(unsigned char *arg)
  2681. {
  2682. return set_get_cmap (arg,0);
  2683. }
  2684. void reset_palette(int currcons)
  2685. {
  2686. int j, k;
  2687. for (j=k=0; j<16; j++) {
  2688. palette[k++] = default_red[j];
  2689. palette[k++] = default_grn[j];
  2690. palette[k++] = default_blu[j];
  2691. }
  2692. set_palette(currcons);
  2693. }
  2694. /*
  2695.  *  Font switching
  2696.  *
  2697.  *  Currently we only support fonts up to 32 pixels wide, at a maximum height
  2698.  *  of 32 pixels. Userspace fontdata is stored with 32 bytes (shorts/ints, 
  2699.  *  depending on width) reserved for each character which is kinda wasty, but 
  2700.  *  this is done in order to maintain compatibility with the EGA/VGA fonts. It 
  2701.  *  is upto the actual low-level console-driver convert data into its favorite
  2702.  *  format (maybe we should add a `fontoffset' field to the `display'
  2703.  *  structure so we wont have to convert the fontdata all the time.
  2704.  *  /Jes
  2705.  */
  2706. #define max_font_size 65536
  2707. int con_font_op(int currcons, struct console_font_op *op)
  2708. {
  2709. int rc = -EINVAL;
  2710. int size = max_font_size, set;
  2711. u8 *temp = NULL;
  2712. struct console_font_op old_op;
  2713. if (vt_cons[currcons]->vc_mode != KD_TEXT)
  2714. goto quit;
  2715. memcpy(&old_op, op, sizeof(old_op));
  2716. if (op->op == KD_FONT_OP_SET) {
  2717. if (!op->data)
  2718. return -EINVAL;
  2719. if (op->charcount > 512)
  2720. goto quit;
  2721. if (!op->height) { /* Need to guess font height [compat] */
  2722. int h, i;
  2723. u8 *charmap = op->data, tmp;
  2724. /* If from KDFONTOP ioctl, don't allow things which can be done in userland,
  2725.    so that we can get rid of this soon */
  2726. if (!(op->flags & KD_FONT_FLAG_OLD))
  2727. goto quit;
  2728. rc = -EFAULT;
  2729. for (h = 32; h > 0; h--)
  2730. for (i = 0; i < op->charcount; i++) {
  2731. if (get_user(tmp, &charmap[32*i+h-1]))
  2732. goto quit;
  2733. if (tmp)
  2734. goto nonzero;
  2735. }
  2736. rc = -EINVAL;
  2737. goto quit;
  2738. nonzero:
  2739. rc = -EINVAL;
  2740. op->height = h;
  2741. }
  2742. if (op->width > 32 || op->height > 32)
  2743. goto quit;
  2744. size = (op->width+7)/8 * 32 * op->charcount;
  2745. if (size > max_font_size)
  2746. return -ENOSPC;
  2747. set = 1;
  2748. } else if (op->op == KD_FONT_OP_GET)
  2749. set = 0;
  2750. else
  2751. return sw->con_font_op(vc_cons[currcons].d, op);
  2752. if (op->data) {
  2753. temp = kmalloc(size, GFP_KERNEL);
  2754. if (!temp)
  2755. return -ENOMEM;
  2756. if (set && copy_from_user(temp, op->data, size)) {
  2757. rc = -EFAULT;
  2758. goto quit;
  2759. }
  2760. op->data = temp;
  2761. }
  2762. acquire_console_sem();
  2763. rc = sw->con_font_op(vc_cons[currcons].d, op);
  2764. release_console_sem();
  2765. op->data = old_op.data;
  2766. if (!rc && !set) {
  2767. int c = (op->width+7)/8 * 32 * op->charcount;
  2768. if (op->data && op->charcount > old_op.charcount)
  2769. rc = -ENOSPC;
  2770. if (!(op->flags & KD_FONT_FLAG_OLD)) {
  2771. if (op->width > old_op.width ||
  2772.     op->height > old_op.height)
  2773. rc = -ENOSPC;
  2774. } else {
  2775. if (op->width != 8)
  2776. rc = -EIO;
  2777. else if ((old_op.height && op->height > old_op.height) ||
  2778.  op->height > 32)
  2779. rc = -ENOSPC;
  2780. }
  2781. if (!rc && op->data && copy_to_user(op->data, temp, c))
  2782. rc = -EFAULT;
  2783. }
  2784. quit: if (temp)
  2785. kfree(temp);
  2786. return rc;
  2787. }
  2788. /*
  2789.  * Interface exported to selection and vcs.
  2790.  */
  2791. /* used by selection */
  2792. u16 screen_glyph(int currcons, int offset)
  2793. {
  2794. u16 w = scr_readw(screenpos(currcons, offset, 1));
  2795. u16 c = w & 0xff;
  2796. if (w & hi_font_mask)
  2797. c |= 0x100;
  2798. return c;
  2799. }
  2800. /* used by vcs - note the word offset */
  2801. unsigned short *screen_pos(int currcons, int w_offset, int viewed)
  2802. {
  2803. return screenpos(currcons, 2 * w_offset, viewed);
  2804. }
  2805. void getconsxy(int currcons, char *p)
  2806. {
  2807. p[0] = x;
  2808. p[1] = y;
  2809. }
  2810. void putconsxy(int currcons, char *p)
  2811. {
  2812. gotoxy(currcons, p[0], p[1]);
  2813. set_cursor(currcons);
  2814. }
  2815. u16 vcs_scr_readw(int currcons, const u16 *org)
  2816. {
  2817. #ifdef CONFIG_CONSOLE_PM // bushi
  2818. if ((unsigned long)org == pos && softcursor_original != -1)
  2819. return softcursor_original;
  2820. #endif
  2821. return scr_readw(org);
  2822. }
  2823. void vcs_scr_writew(int currcons, u16 val, u16 *org)
  2824. {
  2825. scr_writew(val, org);
  2826. #ifdef CONFIG_CONSOLE_PM // bushi
  2827. if ((unsigned long)org == pos) {
  2828. softcursor_original = -1;
  2829. add_softcursor(currcons);
  2830. }
  2831. #endif
  2832. }
  2833. #ifdef CONFIG_CONSOLE_PM // bushi
  2834. static int pm_con_request(struct pm_dev *dev, pm_request_t rqst, void *data)
  2835. {
  2836. switch (rqst)
  2837. {
  2838. case PM_RESUME:
  2839. unblank_screen();
  2840. break;
  2841. case PM_SUSPEND:
  2842. do_blank_screen(0);
  2843. break;
  2844. }
  2845. return 0;
  2846. }
  2847. #endif
  2848. /*
  2849.  * Visible symbols for modules
  2850.  */
  2851. EXPORT_SYMBOL(color_table);
  2852. EXPORT_SYMBOL(default_red);
  2853. EXPORT_SYMBOL(default_grn);
  2854. EXPORT_SYMBOL(default_blu);
  2855. EXPORT_SYMBOL(video_font_height);
  2856. EXPORT_SYMBOL(video_scan_lines);
  2857. EXPORT_SYMBOL(vc_resize);
  2858. EXPORT_SYMBOL(fg_console);
  2859. #ifdef CONFIG_CONSOLE_PM // bushi
  2860. EXPORT_SYMBOL(console_blank_hook);
  2861. #endif
  2862. #ifdef CONFIG_VT
  2863. EXPORT_SYMBOL(vt_cons);
  2864. #endif
  2865. #ifndef VT_SINGLE_DRIVER
  2866. EXPORT_SYMBOL(take_over_console);
  2867. EXPORT_SYMBOL(give_up_console);
  2868. #endif