4 * Mapping from internal code (such as Latin-1 or Unicode or IBM PC code)
9 * Support for multiple unimaps by Jakub Jelinek <jj@ultra.linux.cz>, July 1998
11 * Fix bug in inverse translation. Stanislav Voronyi <stas@cnti.uanet.kharkov.ua>, Dec 1998
14 #include <linux/module.h>
16 #include <linux/errno.h>
18 #include <linux/slab.h>
19 #include <linux/init.h>
20 #include <linux/tty.h>
21 #include <asm/uaccess.h>
22 #include <linux/consolemap.h>
23 #include <linux/vt_kern.h>
25 static unsigned short translations[][256] = {
26 /* 8-bit Latin-1 mapped to Unicode -- trivial mapping */
28 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
29 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
30 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
31 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
32 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
33 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
34 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
35 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
36 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
37 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
38 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
39 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
40 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
41 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
42 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
43 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x007f,
44 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
45 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
46 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
47 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
48 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
49 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
50 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
51 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
52 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
53 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
54 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
55 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
56 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
57 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
58 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
59 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
61 /* VT100 graphics mapped to Unicode */
63 0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
64 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f,
65 0x0010, 0x0011, 0x0012, 0x0013, 0x0014, 0x0015, 0x0016, 0x0017,
66 0x0018, 0x0019, 0x001a, 0x001b, 0x001c, 0x001d, 0x001e, 0x001f,
67 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
68 0x0028, 0x0029, 0x002a, 0x2192, 0x2190, 0x2191, 0x2193, 0x002f,
69 0x2588, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
70 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
71 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
72 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
73 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
74 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x00a0,
75 0x25c6, 0x2592, 0x2409, 0x240c, 0x240d, 0x240a, 0x00b0, 0x00b1,
76 0x2591, 0x240b, 0x2518, 0x2510, 0x250c, 0x2514, 0x253c, 0x23ba,
77 0x23bb, 0x2500, 0x23bc, 0x23bd, 0x251c, 0x2524, 0x2534, 0x252c,
78 0x2502, 0x2264, 0x2265, 0x03c0, 0x2260, 0x00a3, 0x00b7, 0x007f,
79 0x0080, 0x0081, 0x0082, 0x0083, 0x0084, 0x0085, 0x0086, 0x0087,
80 0x0088, 0x0089, 0x008a, 0x008b, 0x008c, 0x008d, 0x008e, 0x008f,
81 0x0090, 0x0091, 0x0092, 0x0093, 0x0094, 0x0095, 0x0096, 0x0097,
82 0x0098, 0x0099, 0x009a, 0x009b, 0x009c, 0x009d, 0x009e, 0x009f,
83 0x00a0, 0x00a1, 0x00a2, 0x00a3, 0x00a4, 0x00a5, 0x00a6, 0x00a7,
84 0x00a8, 0x00a9, 0x00aa, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x00af,
85 0x00b0, 0x00b1, 0x00b2, 0x00b3, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
86 0x00b8, 0x00b9, 0x00ba, 0x00bb, 0x00bc, 0x00bd, 0x00be, 0x00bf,
87 0x00c0, 0x00c1, 0x00c2, 0x00c3, 0x00c4, 0x00c5, 0x00c6, 0x00c7,
88 0x00c8, 0x00c9, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf,
89 0x00d0, 0x00d1, 0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d6, 0x00d7,
90 0x00d8, 0x00d9, 0x00da, 0x00db, 0x00dc, 0x00dd, 0x00de, 0x00df,
91 0x00e0, 0x00e1, 0x00e2, 0x00e3, 0x00e4, 0x00e5, 0x00e6, 0x00e7,
92 0x00e8, 0x00e9, 0x00ea, 0x00eb, 0x00ec, 0x00ed, 0x00ee, 0x00ef,
93 0x00f0, 0x00f1, 0x00f2, 0x00f3, 0x00f4, 0x00f5, 0x00f6, 0x00f7,
94 0x00f8, 0x00f9, 0x00fa, 0x00fb, 0x00fc, 0x00fd, 0x00fe, 0x00ff
96 /* IBM Codepage 437 mapped to Unicode */
98 0x0000, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
99 0x25d8, 0x25cb, 0x25d9, 0x2642, 0x2640, 0x266a, 0x266b, 0x263c,
100 0x25b6, 0x25c0, 0x2195, 0x203c, 0x00b6, 0x00a7, 0x25ac, 0x21a8,
101 0x2191, 0x2193, 0x2192, 0x2190, 0x221f, 0x2194, 0x25b2, 0x25bc,
102 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
103 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
104 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
105 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
106 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
107 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
108 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
109 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
110 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
111 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
112 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
113 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302,
114 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
115 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
116 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
117 0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
118 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
119 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
120 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
121 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
122 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
123 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
124 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
125 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
126 0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
127 0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
128 0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
129 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0
131 /* User mapping -- default to codes for direct font mapping */
133 0xf000, 0xf001, 0xf002, 0xf003, 0xf004, 0xf005, 0xf006, 0xf007,
134 0xf008, 0xf009, 0xf00a, 0xf00b, 0xf00c, 0xf00d, 0xf00e, 0xf00f,
135 0xf010, 0xf011, 0xf012, 0xf013, 0xf014, 0xf015, 0xf016, 0xf017,
136 0xf018, 0xf019, 0xf01a, 0xf01b, 0xf01c, 0xf01d, 0xf01e, 0xf01f,
137 0xf020, 0xf021, 0xf022, 0xf023, 0xf024, 0xf025, 0xf026, 0xf027,
138 0xf028, 0xf029, 0xf02a, 0xf02b, 0xf02c, 0xf02d, 0xf02e, 0xf02f,
139 0xf030, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036, 0xf037,
140 0xf038, 0xf039, 0xf03a, 0xf03b, 0xf03c, 0xf03d, 0xf03e, 0xf03f,
141 0xf040, 0xf041, 0xf042, 0xf043, 0xf044, 0xf045, 0xf046, 0xf047,
142 0xf048, 0xf049, 0xf04a, 0xf04b, 0xf04c, 0xf04d, 0xf04e, 0xf04f,
143 0xf050, 0xf051, 0xf052, 0xf053, 0xf054, 0xf055, 0xf056, 0xf057,
144 0xf058, 0xf059, 0xf05a, 0xf05b, 0xf05c, 0xf05d, 0xf05e, 0xf05f,
145 0xf060, 0xf061, 0xf062, 0xf063, 0xf064, 0xf065, 0xf066, 0xf067,
146 0xf068, 0xf069, 0xf06a, 0xf06b, 0xf06c, 0xf06d, 0xf06e, 0xf06f,
147 0xf070, 0xf071, 0xf072, 0xf073, 0xf074, 0xf075, 0xf076, 0xf077,
148 0xf078, 0xf079, 0xf07a, 0xf07b, 0xf07c, 0xf07d, 0xf07e, 0xf07f,
149 0xf080, 0xf081, 0xf082, 0xf083, 0xf084, 0xf085, 0xf086, 0xf087,
150 0xf088, 0xf089, 0xf08a, 0xf08b, 0xf08c, 0xf08d, 0xf08e, 0xf08f,
151 0xf090, 0xf091, 0xf092, 0xf093, 0xf094, 0xf095, 0xf096, 0xf097,
152 0xf098, 0xf099, 0xf09a, 0xf09b, 0xf09c, 0xf09d, 0xf09e, 0xf09f,
153 0xf0a0, 0xf0a1, 0xf0a2, 0xf0a3, 0xf0a4, 0xf0a5, 0xf0a6, 0xf0a7,
154 0xf0a8, 0xf0a9, 0xf0aa, 0xf0ab, 0xf0ac, 0xf0ad, 0xf0ae, 0xf0af,
155 0xf0b0, 0xf0b1, 0xf0b2, 0xf0b3, 0xf0b4, 0xf0b5, 0xf0b6, 0xf0b7,
156 0xf0b8, 0xf0b9, 0xf0ba, 0xf0bb, 0xf0bc, 0xf0bd, 0xf0be, 0xf0bf,
157 0xf0c0, 0xf0c1, 0xf0c2, 0xf0c3, 0xf0c4, 0xf0c5, 0xf0c6, 0xf0c7,
158 0xf0c8, 0xf0c9, 0xf0ca, 0xf0cb, 0xf0cc, 0xf0cd, 0xf0ce, 0xf0cf,
159 0xf0d0, 0xf0d1, 0xf0d2, 0xf0d3, 0xf0d4, 0xf0d5, 0xf0d6, 0xf0d7,
160 0xf0d8, 0xf0d9, 0xf0da, 0xf0db, 0xf0dc, 0xf0dd, 0xf0de, 0xf0df,
161 0xf0e0, 0xf0e1, 0xf0e2, 0xf0e3, 0xf0e4, 0xf0e5, 0xf0e6, 0xf0e7,
162 0xf0e8, 0xf0e9, 0xf0ea, 0xf0eb, 0xf0ec, 0xf0ed, 0xf0ee, 0xf0ef,
163 0xf0f0, 0xf0f1, 0xf0f2, 0xf0f3, 0xf0f4, 0xf0f5, 0xf0f6, 0xf0f7,
164 0xf0f8, 0xf0f9, 0xf0fa, 0xf0fb, 0xf0fc, 0xf0fd, 0xf0fe, 0xf0ff
168 /* The standard kernel character-to-font mappings are not invertible
169 -- this is just a best effort. */
171 #define MAX_GLYPH 512 /* Max possible glyph value */
173 static int inv_translate[MAX_NR_CONSOLES];
177 unsigned long refcount;
179 unsigned char *inverse_translations[4];
183 static struct uni_pagedir *dflt;
185 static void set_inverse_transl(struct vc_data *conp, struct uni_pagedir *p, int i)
188 unsigned short *t = translations[i];
192 q = p->inverse_translations[i];
195 q = p->inverse_translations[i] = (unsigned char *)
196 kmalloc(MAX_GLYPH, GFP_KERNEL);
199 memset(q, 0, MAX_GLYPH);
201 for (j = 0; j < E_TABSZ; j++) {
202 glyph = conv_uni_to_pc(conp, t[j]);
203 if (glyph >= 0 && glyph < MAX_GLYPH && q[glyph] < 32) {
204 /* prefer '-' above SHY etc. */
210 unsigned short *set_translate(int m, struct vc_data *vc)
212 inv_translate[vc->vc_num] = m;
213 return translations[m];
217 * Inverse translation is impossible for several reasons:
218 * 1. The font<->character maps are not 1-1.
219 * 2. The text may have been written while a different translation map
220 * was active, or using Unicode.
221 * Still, it is now possible to a certain extent to cut and paste non-ASCII.
223 unsigned char inverse_translate(struct vc_data *conp, int glyph)
225 struct uni_pagedir *p;
226 if (glyph < 0 || glyph >= MAX_GLYPH)
228 else if (!(p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc) ||
229 !p->inverse_translations[inv_translate[conp->vc_num]])
232 return p->inverse_translations[inv_translate[conp->vc_num]][glyph];
235 static void update_user_maps(void)
238 struct uni_pagedir *p, *q = NULL;
240 for (i = 0; i < MAX_NR_CONSOLES; i++) {
241 if (!vc_cons_allocated(i))
243 p = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
245 set_inverse_transl(vc_cons[i].d, p, USER_MAP);
252 * Load customizable translation table
253 * arg points to a 256 byte translation table.
255 * The "old" variants are for translation directly to font (using the
256 * 0xf000-0xf0ff "transparent" Unicodes) whereas the "new" variants set
257 * Unicodes explicitly.
259 int con_set_trans_old(unsigned char __user * arg)
262 unsigned short *p = translations[USER_MAP];
264 if (!access_ok(VERIFY_READ, arg, E_TABSZ))
267 for (i=0; i<E_TABSZ ; i++) {
269 __get_user(uc, arg+i);
270 p[i] = UNI_DIRECT_BASE | uc;
277 int con_get_trans_old(unsigned char __user * arg)
280 unsigned short *p = translations[USER_MAP];
282 if (!access_ok(VERIFY_WRITE, arg, E_TABSZ))
285 for (i=0; i<E_TABSZ ; i++)
287 ch = conv_uni_to_pc(vc_cons[fg_console].d, p[i]);
288 __put_user((ch & ~0xff) ? 0 : ch, arg+i);
293 int con_set_trans_new(ushort __user * arg)
296 unsigned short *p = translations[USER_MAP];
298 if (!access_ok(VERIFY_READ, arg, E_TABSZ*sizeof(unsigned short)))
301 for (i=0; i<E_TABSZ ; i++) {
303 __get_user(us, arg+i);
311 int con_get_trans_new(ushort __user * arg)
314 unsigned short *p = translations[USER_MAP];
316 if (!access_ok(VERIFY_WRITE, arg, E_TABSZ*sizeof(unsigned short)))
319 for (i=0; i<E_TABSZ ; i++)
320 __put_user(p[i], arg+i);
326 * Unicode -> current font conversion
328 * A font has at most 512 chars, usually 256.
329 * But one font position may represent several Unicode chars.
330 * A hashtable is somewhat of a pain to deal with, so use a
331 * "paged table" instead. Simulation has shown the memory cost of
332 * this 3-level paged table scheme to be comparable to a hash table.
335 extern u8 dfont_unicount[]; /* Defined in console_defmap.c */
336 extern u16 dfont_unitable[];
338 static void con_release_unimap(struct uni_pagedir *p)
343 if (p == dflt) dflt = NULL;
344 for (i = 0; i < 32; i++) {
345 if ((p1 = p->uni_pgdir[i]) != NULL) {
346 for (j = 0; j < 32; j++)
350 p->uni_pgdir[i] = NULL;
352 for (i = 0; i < 4; i++) {
353 kfree(p->inverse_translations[i]);
354 p->inverse_translations[i] = NULL;
358 void con_free_unimap(struct vc_data *vc)
360 struct uni_pagedir *p;
362 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
365 *vc->vc_uni_pagedir_loc = 0;
368 con_release_unimap(p);
372 static int con_unify_unimap(struct vc_data *conp, struct uni_pagedir *p)
375 struct uni_pagedir *q;
377 for (i = 0; i < MAX_NR_CONSOLES; i++) {
378 if (!vc_cons_allocated(i))
380 q = (struct uni_pagedir *)*vc_cons[i].d->vc_uni_pagedir_loc;
381 if (!q || q == p || q->sum != p->sum)
383 for (j = 0; j < 32; j++) {
385 p1 = p->uni_pgdir[j]; q1 = q->uni_pgdir[j];
390 for (k = 0; k < 32; k++) {
391 if (!p1[k] && !q1[k])
393 if (!p1[k] || !q1[k])
395 if (memcmp(p1[k], q1[k], 64*sizeof(u16)))
403 *conp->vc_uni_pagedir_loc = (unsigned long)q;
404 con_release_unimap(p);
413 con_insert_unipair(struct uni_pagedir *p, u_short unicode, u_short fontpos)
418 if (!(p1 = p->uni_pgdir[n = unicode >> 11])) {
419 p1 = p->uni_pgdir[n] = kmalloc(32*sizeof(u16 *), GFP_KERNEL);
420 if (!p1) return -ENOMEM;
421 for (i = 0; i < 32; i++)
425 if (!(p2 = p1[n = (unicode >> 6) & 0x1f])) {
426 p2 = p1[n] = kmalloc(64*sizeof(u16), GFP_KERNEL);
427 if (!p2) return -ENOMEM;
428 memset(p2, 0xff, 64*sizeof(u16)); /* No glyphs for the characters (yet) */
431 p2[unicode & 0x3f] = fontpos;
433 p->sum += (fontpos << 20) + unicode;
438 /* ui is a leftover from using a hashtable, but might be used again */
439 int con_clear_unimap(struct vc_data *vc, struct unimapinit *ui)
441 struct uni_pagedir *p, *q;
443 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
444 if (p && p->readonly) return -EIO;
445 if (!p || --p->refcount) {
446 q = kmalloc(sizeof(*p), GFP_KERNEL);
448 if (p) p->refcount++;
451 memset(q, 0, sizeof(*q));
453 *vc->vc_uni_pagedir_loc = (unsigned long)q;
455 if (p == dflt) dflt = NULL;
458 con_release_unimap(p);
463 int con_set_unimap(struct vc_data *vc, ushort ct, struct unipair __user *list)
465 int err = 0, err1, i;
466 struct uni_pagedir *p, *q;
468 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
469 if (p->readonly) return -EIO;
473 if (p->refcount > 1) {
477 err1 = con_clear_unimap(vc, NULL);
478 if (err1) return err1;
480 q = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
481 for (i = 0, l = 0; i < 32; i++)
482 if ((p1 = p->uni_pgdir[i]))
483 for (j = 0; j < 32; j++)
485 for (k = 0; k < 64; k++, l++)
486 if (p2[k] != 0xffff) {
487 err1 = con_insert_unipair(q, l, p2[k]);
490 *vc->vc_uni_pagedir_loc = (unsigned long)p;
491 con_release_unimap(q);
497 } else if (p == dflt)
501 unsigned short unicode, fontpos;
502 __get_user(unicode, &list->unicode);
503 __get_user(fontpos, &list->fontpos);
504 if ((err1 = con_insert_unipair(p, unicode,fontpos)) != 0)
509 if (con_unify_unimap(vc, p))
512 for (i = 0; i <= 3; i++)
513 set_inverse_transl(vc, p, i); /* Update all inverse translations */
518 /* Loads the unimap for the hardware font, as defined in uni_hash.tbl.
519 The representation used was the most compact I could come up
520 with. This routine is executed at sys_setup time, and when the
521 PIO_FONTRESET ioctl is called. */
523 int con_set_default_unimap(struct vc_data *vc)
525 int i, j, err = 0, err1;
527 struct uni_pagedir *p;
530 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
534 *vc->vc_uni_pagedir_loc = (unsigned long)dflt;
535 if (p && --p->refcount) {
536 con_release_unimap(p);
542 /* The default font is always 256 characters */
544 err = con_clear_unimap(vc, NULL);
547 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
550 for (i = 0; i < 256; i++)
551 for (j = dfont_unicount[i]; j; j--) {
552 err1 = con_insert_unipair(p, *(q++), i);
557 if (con_unify_unimap(vc, p)) {
558 dflt = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
562 for (i = 0; i <= 3; i++)
563 set_inverse_transl(vc, p, i); /* Update all inverse translations */
567 EXPORT_SYMBOL(con_set_default_unimap);
569 int con_copy_unimap(struct vc_data *dst_vc, struct vc_data *src_vc)
571 struct uni_pagedir *q;
573 if (!*src_vc->vc_uni_pagedir_loc)
575 if (*dst_vc->vc_uni_pagedir_loc == *src_vc->vc_uni_pagedir_loc)
577 con_free_unimap(dst_vc);
578 q = (struct uni_pagedir *)*src_vc->vc_uni_pagedir_loc;
580 *dst_vc->vc_uni_pagedir_loc = (long)q;
584 int con_get_unimap(struct vc_data *vc, ushort ct, ushort __user *uct, struct unipair __user *list)
588 struct uni_pagedir *p;
591 if (*vc->vc_uni_pagedir_loc) {
592 p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
593 for (i = 0; i < 32; i++)
594 if ((p1 = p->uni_pgdir[i]))
595 for (j = 0; j < 32; j++)
597 for (k = 0; k < 64; k++) {
598 if (*p2 < MAX_GLYPH && ect++ < ct) {
599 __put_user((u_short)((i<<11)+(j<<6)+k),
601 __put_user((u_short) *p2,
608 __put_user(ect, uct);
609 return ((ect <= ct) ? 0 : -ENOMEM);
612 void con_protect_unimap(struct vc_data *vc, int rdonly)
614 struct uni_pagedir *p = (struct uni_pagedir *)*vc->vc_uni_pagedir_loc;
617 p->readonly = rdonly;
621 conv_uni_to_pc(struct vc_data *conp, long ucs)
625 struct uni_pagedir *p;
627 /* Only 16-bit codes supported at this time */
629 ucs = 0xfffd; /* U+FFFD: REPLACEMENT CHARACTER */
630 else if (ucs < 0x20 || ucs >= 0xfffe)
631 return -1; /* Not a printable character */
632 else if (ucs == 0xfeff || (ucs >= 0x200a && ucs <= 0x200f))
633 return -2; /* Zero-width space */
635 * UNI_DIRECT_BASE indicates the start of the region in the User Zone
636 * which always has a 1:1 mapping to the currently loaded font. The
637 * UNI_DIRECT_MASK indicates the bit span of the region.
639 else if ((ucs & ~UNI_DIRECT_MASK) == UNI_DIRECT_BASE)
640 return ucs & UNI_DIRECT_MASK;
642 if (!*conp->vc_uni_pagedir_loc)
645 p = (struct uni_pagedir *)*conp->vc_uni_pagedir_loc;
646 if ((p1 = p->uni_pgdir[ucs >> 11]) &&
647 (p2 = p1[(ucs >> 6) & 0x1f]) &&
648 (h = p2[ucs & 0x3f]) < MAX_GLYPH)
651 return -4; /* not found */
655 * This is called at sys_setup time, after memory and the console are
656 * initialized. It must be possible to call kmalloc(..., GFP_KERNEL)
657 * from this function, hence the call from sys_setup.
660 console_map_init(void)
664 for (i = 0; i < MAX_NR_CONSOLES; i++)
665 if (vc_cons_allocated(i) && !*vc_cons[i].d->vc_uni_pagedir_loc)
666 con_set_default_unimap(vc_cons[i].d);
669 EXPORT_SYMBOL(con_copy_unimap);