console.c
上传用户:jlfgdled
上传日期:2013-04-10
资源大小:33168k
文件大小:70k
源码类别:

Linux/Unix编程

开发平台:

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